From patchwork Tue May 15 09:40:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Hung X-Patchwork-Id: 159280 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 4D3C3B6FAF for ; Tue, 15 May 2012 19:40:45 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SUEFH-0004dP-7J for incoming@patchwork.ozlabs.org; Tue, 15 May 2012 09:40:43 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SUEFE-0004d3-GV for fwts-devel@lists.ubuntu.com; Tue, 15 May 2012 09:40:40 +0000 Received: from [210.242.151.101] (helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1SUEFD-0002xN-JI; Tue, 15 May 2012 09:40:40 +0000 From: Alex Hung To: fwts-devel@lists.ubuntu.com Subject: [PATCH] lib: fwts_battery: added interface for cycle count. acpi: battery: added cycle count check for acpi batteries. Date: Tue, 15 May 2012 17:40:34 +0800 Message-Id: <1337074834-5573-1-git-send-email-alex.hung@canonical.com> X-Mailer: git-send-email 1.7.9.5 X-BeenThere: fwts-devel@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Firmware Test Suite Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: fwts-devel-bounces@lists.ubuntu.com Errors-To: fwts-devel-bounces@lists.ubuntu.com Signed-off-by: Alex Hung --- src/acpi/battery/battery.c | 18 +++++++ src/lib/include/fwts_battery.h | 1 + src/lib/src/fwts_battery.c | 111 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/src/acpi/battery/battery.c b/src/acpi/battery/battery.c index 660d89b..d9e4d5e 100644 --- a/src/acpi/battery/battery.c +++ b/src/acpi/battery/battery.c @@ -170,6 +170,23 @@ static void check_discharging(fwts_framework *fw, int index, char *name) name); } +static void check_battery_cycle_count(fwts_framework *fw, int index, char *name) +{ + int cycle_count; + + fwts_printf(fw, "==== Checking cycle count of battery '%s' ====\n", name); + if (fwts_battery_get_cycle_count(fw, index, &cycle_count) == FWTS_OK) { + if (cycle_count == 0) { + fwts_log_info(fw, + "Please ignore this error with a new battery"); + fwts_failed(fw, LOG_LEVEL_LOW, "BatteryZeroCycleCount", + "System firmware may not support cycle count interface " + "or it reports it incorrectly for battery %s.", + name); + } + } + +} static void do_battery_test(fwts_framework *fw, int index) { @@ -193,6 +210,7 @@ static void do_battery_test(fwts_framework *fw, int index) fwts_printf(fw, "==== Please now PLUG IN the AC power of the machine ====\n"); wait_for_acpi_event(fw, name); check_charging(fw, index, name); + check_battery_cycle_count(fw, index, name); } static int battery_test1(fwts_framework *fw) diff --git a/src/lib/include/fwts_battery.h b/src/lib/include/fwts_battery.h index 591c4bb..83d381b 100644 --- a/src/lib/include/fwts_battery.h +++ b/src/lib/include/fwts_battery.h @@ -26,6 +26,7 @@ #define FWTS_BATTERY_ALL (-1) int fwts_battery_get_count(fwts_framework *fw, int *count); +int fwts_battery_get_cycle_count(fwts_framework *fw, int index, int *cycle_count); int fwts_battery_get_capacity(fwts_framework *fw, int type, int index, uint32_t *capacity_mAh, uint32_t *capacity_mWh); int fwts_battery_get_name(fwts_framework *fw, int index, char *name); diff --git a/src/lib/src/fwts_battery.c b/src/lib/src/fwts_battery.c index 008951d..5cc5ca7 100644 --- a/src/lib/src/fwts_battery.c +++ b/src/lib/src/fwts_battery.c @@ -261,6 +261,117 @@ static int fwts_battery_get_name_proc_fs(fwts_framework *fw, DIR *dir, int index return FWTS_ERROR; } +static int fwts_battery_get_cycle_count_sys_fs(fwts_framework *fw, DIR *dir, int index, int *cycle_count) +{ + struct dirent *entry; + char *field_cycle_count; + size_t field_cycle_count_len; + int i = 0; + + field_cycle_count = "POWER_SUPPLY_CYCLE_COUNT="; + field_cycle_count_len = strlen(field_cycle_count); + + do { + entry = readdir(dir); + if (entry && strlen(entry->d_name) > 2) { + char path[PATH_MAX]; + char *data; + int val; + FILE *fp; + bool match; + + /* Check that type field matches the expected type */ + snprintf(path, sizeof(path), "%s/%s/type", FWTS_SYS_CLASS_POWER_SUPPLY, entry->d_name); + if ((data = fwts_get(path)) != NULL) { + bool mismatch = (strstr(data, "Battery") == NULL); + free(data); + if (mismatch) + continue; /* type don't match, skip this entry */ + } else + continue; /* can't check type, skip this entry */ + match = ((index == FWTS_BATTERY_ALL) || (index == i)); + i++; + if (!match) + continue; + + snprintf(path, sizeof(path), "%s/%s/uevent", FWTS_SYS_CLASS_POWER_SUPPLY, entry->d_name); + if ((fp = fopen(path, "r")) == NULL) { + fwts_log_info(fw, "Battery %s present but undersupported - no state present.", entry->d_name); + } else { + char buffer[4096]; + while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { + if (strstr(buffer, field_cycle_count) && + strlen(buffer) > field_cycle_count_len) { + sscanf(buffer+field_cycle_count_len, "%d", &val); + *cycle_count = val; + } + } + } + } + } while (entry); + + return FWTS_OK; +} + +static int fwts_battery_get_cycle_count_proc_fs(fwts_framework *fw, DIR *dir, int index, int *cycle_count) +{ + struct dirent *entry; + char *file; + char *field; + int i = 0; + + file = "info"; + field = "cycle count"; + + do { + entry = readdir(dir); + if (entry && strlen(entry->d_name) > 2) { + char path[PATH_MAX]; + int val; + FILE *fp; + bool match = ((index == FWTS_BATTERY_ALL) || (index == i)); + + i++; + if (!match) + continue; + + snprintf(path, sizeof(path), "%s/%s/%s", FWTS_PROC_ACPI_BATTERY, entry->d_name, file); + if ((fp = fopen(path, "r")) == NULL) { + fwts_log_info(fw, "Battery %s present but undersupported - no state present.", entry->d_name); + } else { + char buffer[4096]; + while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { + if (strstr(buffer, field) && + strlen(buffer) > 25) { + sscanf(buffer+25, "%d", &val); + *cycle_count = val; + break; + } + } + } + } + } while (entry); + return FWTS_OK; +} + +int fwts_battery_get_cycle_count(fwts_framework *fw, int index, int *cycle_count) +{ + int ret; + DIR *dir; + + if ((dir = opendir(FWTS_SYS_CLASS_POWER_SUPPLY)) != NULL) { + ret = fwts_battery_get_cycle_count_sys_fs(fw, dir, index, cycle_count); + closedir(dir); + } else if ((dir = opendir(FWTS_PROC_ACPI_BATTERY)) != NULL) { + ret = fwts_battery_get_cycle_count_proc_fs(fw, dir, index, cycle_count); + closedir(dir); + } else { + return FWTS_ERROR; + } + + return ret; +} + int fwts_battery_get_name(fwts_framework *fw, int index, char *name) { int ret;