Switch powertop to use the power supply class (/sys/class/power_supply/) instead of the deprecated /proc interface (/proc/acpi/battery/). This is compatible with 2.6.23 and newer kernels. Caveats: Using the ACPI battery module on my Lenovo ThinkPad T61, current was reported in watts instead of amps, so I used watts_drawn instead of amperes_drawn as I had expected. This appears to violate the kernel documentation in power/power_supply_class.txt so perhaps it should get fixed in the kernel. Similar holds true for energy_now -- it reported watts instead of watt-hours. If either of these isn't true for your computer, this patch won't work. You can check by comparing the contents of /proc/acpi/battery/*/state with /sys/class/power_supply/*/*_now. -Donnie Berkholz Index: powertop.c =================================================================== --- powertop.c (revision 273) +++ powertop.c (working copy) @@ -353,7 +353,7 @@ char filename[256]; - dir = opendir("/proc/acpi/battery"); + dir = opendir("/sys/class/power_supply"); if (!dir) return; @@ -362,53 +362,68 @@ double voltage = 0.0; double amperes_drawn = 0.0; double watts_drawn = 0.0; - double amperes_left = 0.0; double watts_left = 0.0; char line[1024]; - if (strlen(dirent->d_name) < 3) + if (strstr(dirent->d_name, "AC")) continue; - sprintf(filename, "/proc/acpi/battery/%s/state", dirent->d_name); + sprintf(filename, "/sys/class/power_supply/%s/present", dirent->d_name); file = fopen(filename, "r"); if (!file) continue; - memset(line, 0, 1024); - while (fgets(line, 1024, file) != NULL) { - char *c; - if (strstr(line, "present:") && strstr(line, "no")) + int s; + if ((s = getc(file)) != EOF) { + if (s == 0) break; + } + fclose(file); - if (strstr(line, "charging state:") - && !strstr(line, "discharging")) + sprintf(filename, "/sys/class/power_supply/%s/status", dirent->d_name); + file = fopen(filename, "r"); + if (!file) + continue; + memset(line, 0, 1024); + if (fgets(line, 1024, file) != NULL) { + if (!strstr(line, "Discharging")) dontcount = 1; - c = strchr(line, ':'); - if (!c) - continue; - c++; + } + fclose(file); - if (strstr(line, "present voltage")) - voltage = strtoull(c, NULL, 10) / 1000.0; - - if (strstr(line, "remaining capacity") && strstr(c, "mW")) - watts_left = strtoull(c, NULL, 10) / 1000.0; + sprintf(filename, "/sys/class/power_supply/%s/voltage_now", dirent->d_name); + file = fopen(filename, "r"); + if (!file) + continue; + memset(line, 0, 1024); + if (fgets(line, 1024, file) != NULL) { + voltage = strtoull(line, NULL, 10) / 1000000.0; + } + fclose(file); - if (strstr(line, "remaining capacity") && strstr(c, "mAh")) - amperes_left = strtoull(c, NULL, 10) / 1000.0; + sprintf(filename, "/sys/class/power_supply/%s/energy_now", dirent->d_name); + file = fopen(filename, "r"); + if (!file) + continue; + memset(line, 0, 1024); + if (fgets(line, 1024, file) != NULL) { + watts_left = strtoull(line, NULL, 10) / 1000000.0; + } + fclose(file); - if (strstr(line, "present rate") && strstr(c, "mW")) - watts_drawn = strtoull(c, NULL, 10) / 1000.0 ; - - if (strstr(line, "present rate") && strstr(c, "mA")) - amperes_drawn = strtoull(c, NULL, 10) / 1000.0; - + sprintf(filename, "/sys/class/power_supply/%s/current_now", dirent->d_name); + file = fopen(filename, "r"); + if (!file) + continue; + memset(line, 0, 1024); + if (fgets(line, 1024, file) != NULL) { + watts_drawn = strtoull(line, NULL, 10) / 1000000.0; } fclose(file); if (!dontcount) { rate += watts_drawn + voltage * amperes_drawn; } - cap += watts_left + voltage * amperes_left; + cap += watts_left; }