diff mbox

lib: fwts_battery: added interface for cycle count. acpi: battery: added cycle count check for acpi batteries.

Message ID 1337090832-20452-1-git-send-email-alex.hung@canonical.com
State Accepted
Headers show

Commit Message

Alex Hung May 15, 2012, 2:07 p.m. UTC
Signed-off-by: Alex Hung <alex.hung@canonical.com>
---
 src/acpi/battery/battery.c     |   18 +++++++
 src/lib/include/fwts_battery.h |    1 +
 src/lib/src/fwts_battery.c     |  113 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+)

Comments

Colin Ian King May 15, 2012, 2:33 p.m. UTC | #1
On 15/05/12 15:07, Alex Hung wrote:
> Signed-off-by: Alex Hung<alex.hung@canonical.com>
> ---
>   src/acpi/battery/battery.c     |   18 +++++++
>   src/lib/include/fwts_battery.h |    1 +
>   src/lib/src/fwts_battery.c     |  113 ++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 132 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..d8cc318 100644
> --- a/src/lib/src/fwts_battery.c
> +++ b/src/lib/src/fwts_battery.c
> @@ -261,6 +261,119 @@ 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;
> +
> +	*cycle_count = 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;
> +
> +	*cycle_count = 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;

Looks OK to me. Thanks Alex.

Acked-by: Colin Ian King <colin.king@canonical.com>
Keng-Yu Lin May 17, 2012, 5:59 a.m. UTC | #2
On Tue, May 15, 2012 at 10:33 PM, Colin Ian King
<colin.king@canonical.com> wrote:
> On 15/05/12 15:07, Alex Hung wrote:
>>
>> Signed-off-by: Alex Hung<alex.hung@canonical.com>
>> ---
>>  src/acpi/battery/battery.c     |   18 +++++++
>>  src/lib/include/fwts_battery.h |    1 +
>>  src/lib/src/fwts_battery.c     |  113
>> ++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 132 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..d8cc318 100644
>> --- a/src/lib/src/fwts_battery.c
>> +++ b/src/lib/src/fwts_battery.c
>> @@ -261,6 +261,119 @@ 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;
>> +
>> +       *cycle_count = 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;
>> +
>> +       *cycle_count = 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;
>
>
> Looks OK to me. Thanks Alex.
>
> Acked-by: Colin Ian King <colin.king@canonical.com>
>
Acked-by: Keng-Yu Lin <kengyu@canonical.com>
Ivan Hu May 17, 2012, 10:11 a.m. UTC | #3
On 05/17/2012 01:59 PM, Keng-Yu Lin wrote:
> On Tue, May 15, 2012 at 10:33 PM, Colin Ian King
> <colin.king@canonical.com>  wrote:
>> On 15/05/12 15:07, Alex Hung wrote:
>>> Signed-off-by: Alex Hung<alex.hung@canonical.com>
>>> ---
>>>   src/acpi/battery/battery.c     |   18 +++++++
>>>   src/lib/include/fwts_battery.h |    1 +
>>>   src/lib/src/fwts_battery.c     |  113
>>> ++++++++++++++++++++++++++++++++++++++++
>>>   3 files changed, 132 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..d8cc318 100644
>>> --- a/src/lib/src/fwts_battery.c
>>> +++ b/src/lib/src/fwts_battery.c
>>> @@ -261,6 +261,119 @@ 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;
>>> +
>>> +       *cycle_count = 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;
>>> +
>>> +       *cycle_count = 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;
>>
>> Looks OK to me. Thanks Alex.
>>
>> Acked-by: Colin Ian King<colin.king@canonical.com>
>>
> Acked-by: Keng-Yu Lin<kengyu@canonical.com>
Acked-by: Ivan Hu<ivan.hu@canonical.com>
diff mbox

Patch

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..d8cc318 100644
--- a/src/lib/src/fwts_battery.c
+++ b/src/lib/src/fwts_battery.c
@@ -261,6 +261,119 @@  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;
+
+	*cycle_count = 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;
+
+	*cycle_count = 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;