[PATCH] Port powertop to use power supply class

Donnie Berkholz dberkholz at gentoo.org
Fri Mar 21 13:39:25 PDT 2008


I put together a preliminary patch to 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. I'm not really sure what powertop's backwards 
compatibility goal is, but I dropped code for the old interface.

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.

I'd appreciate any comments you have.

Thanks,
Donnie
-------------- next part --------------
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 <dberkholz at gentoo.org>

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;
 		
 
 	}


More information about the Power mailing list