/* * Copyright (C) 2006, Intel Corporation * * This file is part of the Linux-ready Firmware Developer Kit * * This program file is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation;version 2.1 of the License. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program in a file named COPYING; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include static unsigned long get_full(char *dir) { FILE *file; char path[PATH_MAX]; unsigned long value = 0; if (!dir) return 0; sprintf(path, "%s/state", dir); file = fopen(path, "r"); if (file == NULL) return 0; while (!feof(file)) { char buffer[4096]; memset(buffer, 0, 4096); if (fgets(buffer, 4095, file)==NULL) break; if (strstr(buffer,"remaining capacity:") && strlen(buffer)>25) value = strtoull(buffer+25, NULL, 10); } fclose(file); return value; } static void check_charging(char *dir, char *uri, char *name) { int i; /* when we get here we KNOW the state is "charging" */ unsigned long initial_value, new_value; char buf[4095]; if (name==NULL) return; initial_value = get_full(dir); report_testrun_progress(10); for (i=1; i<30; i++) { new_value = get_full(dir); if (new_value>initial_value) { sprintf(buf, "Battery %s charge is incrementing as expected", name); report_result("battery", PASS, buf , NULL, uri); return; } sleep(1); report_testrun_progress(10+i*3); } sprintf(buf, "Battery %s claims it's charging but no charge is added", name); report_result("battery", FAIL, buf , NULL, uri); } static void check_discharging(char *dir, char *uri, char *name) { int i; /* when we get here we KNOW the state is "discharging" */ unsigned long initial_value, new_value; char buf[4095]; if (name==NULL) return; initial_value = get_full(dir); report_testrun_progress(10); for (i=1; i<30; i++) { new_value = get_full(dir); if (new_value25) state=strdup(buffer+25); } fclose(file); sprintf(path, "%s/info", dir); file = fopen(path, "r"); if (file == NULL) { report_result("battery", WARN, "Battery present but undersupported - no info present", path, NULL); return; } while (!feof(file)) { char buffer[4096]; memset(buffer, 0, 4096); if (fgets(buffer, 4095, file)==NULL) break; if (strcmp(buffer,"present: yes")==0) present = 1; if (strstr(buffer,"model number:") && strlen(buffer)>25) model=strdup(buffer+25); } fclose(file); if (state==NULL || model==NULL) { report_result("battery", WARN, "Battery present but name or state unsupported", path, NULL); return; } chop_newline(model); chop_newline(state); sprintf(path,"\\_SB.%s",name); AML_to_uri(path, uri); sprintf(path,"Battery %s is model %s and is currently %s", name, model, state); report_result("battery", INFO, path, NULL, uri); if (strstr(state,"discharging")) check_discharging(dir, uri, name ); else if (strstr(state,"charging")) check_charging(dir, uri, name ); free(state); free(model); } int main(int argc, char **argv) { DIR *dir; struct dirent *entry; int battdir = 0; start_test("battery", "Battery tests", "This test reports which (if any) batteries there are in the system. " "In addition, for charging or discharging batteries, the test validates " "that the reported 'current capacity' properly increments/decrements " "in line with the charge/discharge state. \n\n" "This test also stresses the entire battery state reporting codepath " "in the ACPI BIOS, and any warnings given by the ACPI interpreter " "will be reported."); dir = opendir("/proc/acpi/battery/"); if (!dir) { report_result("battery", INFO, "No battery information present", NULL, NULL); goto out; } do { char batpath[2048]; entry = readdir(dir); if (entry && strlen(entry->d_name)>2) { sprintf(batpath, "/proc/acpi/battery/%s", entry->d_name); do_battery(batpath, entry->d_name); battdir++; } } while (entry); if(battdir == 0) report_result("battery", INFO, "No battery information present", NULL, NULL); out: finish_test("battery"); return 0; }