[Pkg-wmaker-commits] [wmbattery] 95/241: * Add support for the new ACPI_SYSFS_POWER kernel interface in 2.6.24. (Still quite rough and probably gets a few things wrong.) Closes: #456247

Doug Torrance dtorrance-guest at moszumanska.debian.org
Mon Aug 24 23:37:39 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch master
in repository wmbattery.

commit faebe3d6b694aa7cb3bba96da8092171327db235
Author: Joey Hess <joey at kodama.kitenet.net>
Date:   Fri Feb 1 17:12:14 2008 -0500

    * Add support for the new ACPI_SYSFS_POWER kernel interface in 2.6.24.
      (Still quite rough and probably gets a few things wrong.)
      Closes: #456247
---
 Makefile             |   4 +-
 autoconf/makeinfo.in |   2 +-
 debian/changelog     |   8 ++
 sys_power.c          | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++
 sys_power.h          |  28 ++++++
 wmbattery.1x         |  24 ++---
 wmbattery.c          |  39 +++++---
 7 files changed, 331 insertions(+), 25 deletions(-)

diff --git a/Makefile b/Makefile
index 1c80798..4aea723 100644
--- a/Makefile
+++ b/Makefile
@@ -21,8 +21,8 @@ install: all
 uninstall:
 	rm -rf $(bindir)/wmbattery $(man1dir)/wmbattery.1x $(icondir)
 
-wmbattery: wmbattery.o acpi.o sonypi.o
-	$(CC) $(LDFLAGS) wmbattery.o acpi.o sonypi.o -o wmbattery $(LIBS)
+wmbattery: wmbattery.o acpi.o sonypi.o sys_power.o
+	$(CC) $(LDFLAGS) wmbattery.o acpi.o sonypi.o sys_power.o -o wmbattery $(LIBS)
 
 wmbattery.o: wmbattery.c wmbattery.h
 
diff --git a/autoconf/makeinfo.in b/autoconf/makeinfo.in
index 37111ff..e23e6d0 100644
--- a/autoconf/makeinfo.in
+++ b/autoconf/makeinfo.in
@@ -7,7 +7,7 @@ prefix		= @prefix@
 srcdir		= @srcdir@
 
 CC		= @CC@
-CFLAGS		= @CFLAGS@ -Wall -DACPI_APM
+CFLAGS		= @CFLAGS@ -Wall -DACPI_APM -DSYS_POWER_APM
 CPPFLAGS	= @CPPFLAGS@ -DICONDIR=\"$(icondir)\"
 INSTALL		= @INSTALL@
 INSTALL_DATA	= @INSTALL_DATA@
diff --git a/debian/changelog b/debian/changelog
index 027e4ac..3652f3f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+wmbattery (2.34) UNRELEASED; urgency=low
+
+  * Add support for the new ACPI_SYSFS_POWER kernel interface in 2.6.24.
+    (Still quite rough and probably gets a few things wrong.)
+    Closes: #456247
+
+ -- Joey Hess <joeyh at debian.org>  Fri, 01 Feb 2008 15:28:53 -0500
+
 wmbattery (2.33) unstable; urgency=low
 
   * Correct issue with the statically allocated string returned by
diff --git a/sys_power.c b/sys_power.c
new file mode 100644
index 0000000..30c66ed
--- /dev/null
+++ b/sys_power.c
@@ -0,0 +1,251 @@
+/* 
+ * Support for the linux ACPI_SYS_POWER interface.
+ * By Joey Hess <joey at kitenet.net>
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#ifdef SYS_POWER_APM
+#include "apm.h"
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "sys_power.h"
+
+int sys_power_batt_count = 0;
+int sys_power_ac_count = 0;
+char sys_power_batt_dirs[SYS_POWER_MAXITEM][128];
+char sys_power_ac_dirs[SYS_POWER_MAXITEM][128];
+/* Stores battery capacity, or 0 if the battery is absent. */
+int sys_power_batt_capacity[SYS_POWER_MAXITEM];
+
+/* Read a single value from a sys file from the specified directory (well,
+ * the first 64 bytes anyway), and return a statically allocated array
+ * containing it. The newline, if any, is stripped. If the file is not
+ * present, "0" is returned. */
+char *get_sys_power_value (const char *dir, const char *file) {
+	int fd;
+	int end;
+	static char buf[64];
+	char fn[128];
+	snprintf(fn, 127, "%s/%s/%s", SYS_POWER, dir, file);
+	fd = open(fn, O_RDONLY);
+	if (fd == -1) return "0";
+	end = read(fd, buf, sizeof(buf));
+	close(fd);
+	buf[end-1] = '\0';
+	if (buf[end-2] == '\n')
+		buf[end-2] = '\0';
+	return buf;
+}
+
+/* Returns the maximum capacity of a battery.
+ *
+ * Note that this returns the highest possible capacity for the battery,
+ * even if it can no longer charge that fully. So normally it uses the
+ * design capacity. While the last full capacity of the battery should
+ * never exceed the design capacity, some silly hardware might report
+ * that it does. So if the last full capacity is greater, it will be
+ * returned.
+ */
+int get_sys_power_batt_capacity(int battery) {
+	int dcap=atoi(get_sys_power_value(sys_power_batt_dirs[battery], "charge_full_design"));
+	int lcap=atoi(get_sys_power_value(sys_power_batt_dirs[battery], "charge_full"));
+	
+	if (lcap > dcap)
+		return lcap;
+	else
+		return dcap;
+}
+
+/* Comparison function for qsort. */
+int _sys_power_compare_strings (const void *a, const void *b) {
+	const char **pa = (const char **)a;
+	const char **pb = (const char **)b;
+	return strcasecmp((const char *)*pa, (const char *)*pb);
+}
+
+/* Find something (batteries, ac adpaters, etc), and set up a string array
+ * to hold the paths to the things found.
+ * Returns the number of items found. */
+int find_sys_power_items (char *type, char dirarray[SYS_POWER_MAXITEM][128]) {
+	DIR *dir;
+	struct dirent *ent;
+	int num_devices=0;
+	
+	dir = opendir(SYS_POWER);
+	if (dir == NULL)
+		return 0;
+	while ((ent = readdir(dir))) {
+		if (!strcmp(".", ent->d_name) || 
+		    !strcmp("..", ent->d_name))
+			continue;
+
+		if (strcmp(get_sys_power_value(ent->d_name, "type"), type) == 0) {
+			sprintf(dirarray[num_devices], "%s", ent->d_name);
+			num_devices++;
+			if (num_devices >= SYS_POWER_MAXITEM)
+				break;
+		}
+	}
+	closedir(dir);
+	
+	/* Sort, since readdir can return in any order. */
+	qsort(dirarray, num_devices, sizeof(char *), _sys_power_compare_strings);
+
+	return num_devices;
+}
+
+/* Find batteries, return the number, and set sys_power_batt_count to it as
+ * well. */
+int find_sys_power_batteries(void) {
+	int i;
+	sys_power_batt_count = find_sys_power_items("Battery", sys_power_batt_dirs);
+	for (i = 0; i < sys_power_batt_count; i++)
+		sys_power_batt_capacity[i] = get_sys_power_batt_capacity(i);
+	return sys_power_batt_count;
+}
+
+/* Find AC power adapters, return the number found, and set 
+ * sys_power_ac_count to it as well. */
+int find_sys_power_ac_adapters(void) {
+	sys_power_ac_count = find_sys_power_items("Mains", sys_power_ac_dirs);
+	return sys_power_ac_count;
+}
+
+/* Returns true if the system is on ac power. Call find_sys_power_ac_adapters
+ * first. */
+int sys_power_on_ac (void) {
+	int i;
+	for (i = 0; i < sys_power_ac_count; i++) {
+		if (strcmp(get_sys_power_value(sys_power_ac_dirs[i], "online"), "0") != 0)
+			return 1;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+/* See if we have ACPI_SYS_POWER support. Also find batteries and ac power
+ * adapters. */
+int sys_power_supported (void) {
+	DIR *dir;
+
+	if (!(dir = opendir(SYS_POWER))) {
+		return 0;
+	}
+	closedir(dir);
+	
+	find_sys_power_batteries();
+	find_sys_power_ac_adapters();
+
+	return 1;
+}
+
+#ifdef SYS_POWER_APM
+/* Read ACPI info on a given battery, and fill the passed apm_info struct. */
+int sys_power_read (int battery, apm_info *info) {
+	char *status;
+
+	if (sys_power_batt_count == 0) {
+		info->battery_percentage = 0;
+		info->battery_time = 0;
+		info->battery_status = BATTERY_STATUS_ABSENT;
+		sys_power_batt_capacity[battery] = 0;
+		/* Where else would the power come from, eh? ;-) */
+		info->ac_line_status = 1;
+		return 0;
+	}
+	
+	/* Internally it's zero indexed. */
+	battery--;
+	
+	info->ac_line_status = 0;
+	info->battery_flags = 0;
+	info->using_minutes = 1;
+	
+	/* Work out if the battery is present, and what percentage of full
+	 * it is and how much time is left. */
+	if (strcmp(get_sys_power_value(sys_power_batt_dirs[battery], "present"), "1") == 0) {
+		int charge = atoi(get_sys_power_value(sys_power_batt_dirs[battery], "charge_now"));
+		int current = atoi(get_sys_power_value(sys_power_batt_dirs[battery], "current_now"));
+
+		if (current) {
+			/* time remaining = (charge / current) */
+			info->battery_time = (float) charge / (float) current * 60;
+		}
+		else {
+			/* a zero or unknown in the file; time 
+			 * unknown so use a negative one to
+			 * indicate this */
+			info->battery_time = -1;
+		}
+		
+		if (sys_power_batt_capacity[battery] == 0) {
+			/* The battery was absent, and now is present.
+			 * Well, it might be a different battery. So
+			 * re-probe the battery. */
+			sys_power_batt_capacity[battery] = get_sys_power_batt_capacity(battery);
+		}
+		else if (current > sys_power_batt_capacity[battery]) {
+			/* Battery is somehow charged to greater than max
+			 * capacity. Rescan for a new max capacity. */
+			sys_power_batt_capacity[battery] = get_sys_power_batt_capacity(battery);
+		}
+
+		status = get_sys_power_value(sys_power_batt_dirs[battery], "status");
+		if (strcmp(status, "Discharging") == 0) {
+			info->battery_status = BATTERY_STATUS_CHARGING;
+			/* Explicit power check used here
+			 * because AC power might be on even if a
+			 * battery is discharging in some cases. */
+			info->ac_line_status = sys_power_on_ac();
+		}
+		else if (strcmp(status, "Charging") == 0) {
+			info->battery_status = BATTERY_STATUS_CHARGING;
+			info->ac_line_status = 1;
+			info->battery_flags = info->battery_flags | BATTERY_FLAGS_CHARGING;
+			if (current)
+				info->battery_time = -1 * (float) (sys_power_batt_capacity[battery] - charge) / (float) current * 60;
+			else
+				info->battery_time = 0;
+			if (abs(info->battery_time) < 0.5)
+				info->battery_time = 0;
+		}
+		else {
+			fprintf(stderr, "unknown battery status: %s\n", status);
+			info->battery_status = BATTERY_STATUS_ABSENT;
+		}
+		
+		if (current && sys_power_batt_capacity[battery]) {
+			/* percentage = (current_capacity / max capacity) * 100 */
+			info->battery_percentage = (float) current / (float) sys_power_batt_capacity[battery] * 100;
+		}
+		else {
+			info->battery_percentage = -1;
+		}
+
+	}
+	else {
+		info->battery_percentage = 0;
+		info->battery_time = 0;
+		info->battery_status = BATTERY_STATUS_ABSENT;
+		sys_power_batt_capacity[battery] = 0;
+		if (sys_power_batt_count == 0) {
+			/* Where else would the power come from, eh? ;-) */
+			info->ac_line_status = 1;
+		}
+		else {
+			info->ac_line_status = sys_power_supported();
+		}
+	}
+	
+	return 0;
+}
+#endif
diff --git a/sys_power.h b/sys_power.h
new file mode 100644
index 0000000..b9f452d
--- /dev/null
+++ b/sys_power.h
@@ -0,0 +1,28 @@
+/*
+ * Support for the linux ACPI_SYS_POWER interface.
+ * By Joey Hess <joey at kitenet.net>
+ */
+
+/* Define SYS_POWER_APM to get the sys_power_read function, which is
+ * like apm_read. */
+//#define SYS_POWER_APM 1
+
+/* If you don't have sysfs on /sys, change this.. */
+#define SYS_POWER "/sys/class/power_supply"
+
+/* The number of items of each class supported. */
+#define SYS_POWER_MAXITEM 8
+
+int sys_power_supported (void);
+#ifdef SYS_POWER_APM
+int sys_power_read (int battery, apm_info *info);
+#endif
+char *get_sys_power_value (const char *dir, const char *file);
+int get_sys_power_batt_capacity(int battery);
+
+extern int sys_power_batt_count;
+extern int sys_power_ac_count;
+extern char sys_power_batt_dirs[SYS_POWER_MAXITEM][128];
+extern char sys_power_ac_dirs[SYS_POWER_MAXITEM][128];
+/* Stores battery capacity, or 0 if the battery is absent. */
+extern int sys_power_batt_capacity[SYS_POWER_MAXITEM];
diff --git a/wmbattery.1x b/wmbattery.1x
index d9a7636..e691ab3 100644
--- a/wmbattery.1x
+++ b/wmbattery.1x
@@ -11,9 +11,9 @@ is a battery monitor.  It is used to visually display the system's battery
 status.
 .PP
 .B wmbattery
-can get battery information using APM, ACPI, or the SPIC controller in some
-Sony laptops. You need to build your kernel with support for at least one
-of these for the program to work.
+can get battery information using /sys/class/power_supply, APM, /proc/acpi, or
+the SPIC controller in some Sony laptops. You need to build your kernel with
+support for at least one of these for the program to work.
 .B wmbattery
 is dockable using WindowMaker and AfterStep window managers; under
 other window managers
@@ -66,8 +66,9 @@ it, it will turn red.
 Display list of command-line options.
 .TP
 .B \-w secs
-Pause this many seconds between updates. Defaults to 1 for APM and 3 for
-ACPI (since querying ACPI takes quite a bit more CPU power).
+Pause this many seconds between updates. Defaults to 1 for most things, but
+3 for the /proc/acpi interface (since that interfaces takes quite a bit more
+CPU power).
 .TP
 .B \-d display
 Use the designated X display.
@@ -76,24 +77,25 @@ Use the designated X display.
 Specify geometry. This specifies position, not size.
 .TP
 .B \-b battnum
-Display the given battery. Only of use with ACPI on systems with more than
-one battery. The default is to display the first battery found.
+Display the given battery. Only of use with the /sys/class/power_supply or 
+/proc/acpi interfaces on systems with more than one battery. The default is
+to display the first battery found.
 .TP
 .B \-l percent
-Set the percentaqge at which the battery is considered to be running low. By
-default, this percentage is determined by APM or ACPI, and you shouldn't
+Set the percentage at which the battery is considered to be running low. By
+default, this percentage is determined automaticall, and you shouldn't
 need to set it. If you set this, you should probably also set the \-c
 switch.
 .TP
 .B \-c percent
 Set the percentage at which the battery is considered to be critically low.
-By default, this percentage is determined by APM or ACPI, and you shouldn't
+By default, this percentage is determined automatically, and you shouldn't
 need to set it. If you set this, you should probably also set the \-l
 switch.
 .TP
 .B \-e
 wmbattery contains code for estimating the time remaining before discharge,
-and until full charge,and this code is used if no other source of this
+and until full charge, and this code is used if no other source of this
 informaton is available. This switch makes wmbattery use its time 
 estimation code even if some other estimate is available.
 .TP
diff --git a/wmbattery.c b/wmbattery.c
index e5c696d..3e1ea2d 100644
--- a/wmbattery.c
+++ b/wmbattery.c
@@ -21,6 +21,7 @@
 #include "mask.xbm"
 #include "sonypi.h"
 #include "acpi.h"
+#include "sys_power.h"
 
 Pixmap images[NUM_IMAGES];
 Window root, iconwin, win;
@@ -35,6 +36,7 @@ char *crit_audio;
 int crit_audio_size;
 
 int battnum = 1;
+int use_sys_power = 0;
 int use_sonypi = 0;
 int use_acpi = 0;
 int delay = 0;
@@ -505,7 +507,11 @@ void alarmhandler(int sig) {
 	int old_status;
 
 	old_status = cur_info.battery_status;
-	if (use_acpi) {
+	if (use_sys_power) {
+		if (sys_power_read(battnum, &cur_info) != 0)
+			error("Cannot read " SYS_POWER " information.");
+	}
+	else if (use_acpi) {
 		if (acpi_read(battnum, &cur_info) != 0)
 			error("Cannot read ACPI information.");
 	}
@@ -551,26 +557,37 @@ void alarmhandler(int sig) {
 	alarm(delay);
 }
 
+void check_battery_num(int real, int requested) {
+	if (requested > real || requested < 1) {
+		error("There %s only %i batter%s, and you asked for number %i.",
+			real == 1 ? "is" : "are",
+			real,
+			real == 1 ? "y" : "ies",
+			requested);
+	}
+}
+
 int main(int argc, char *argv[]) {
 	make_window(parse_commandline(argc, argv), argc ,argv);
 
+	/* Check for SYS_POWER support. */
+	if (sys_power_supported() && sys_power_batt_count > 0) {
+		check_battery_num(sys_power_batt_count, battnum);
+		use_sys_power = 1;
+		if (! delay)
+			delay = 1;
+	}
 	/*  Check for APM support (returns 0 on success). */
-	if (apm_exists() == 0) {
+	else if (apm_exists() == 0) {
 		if (! delay)
 			delay = 1;
 	}
 	/* Check for ACPI support. */
 	else if (acpi_supported() && acpi_batt_count > 0) {
-		if (battnum > acpi_batt_count || battnum < 1) {
-			error("There %s only %i batter%s, and you asked for number %i.",
-					acpi_batt_count == 1 ? "is" : "are",
-					acpi_batt_count,
-					acpi_batt_count == 1 ? "y" : "ies",
-					battnum);
-		}
+		check_battery_num(acpi_batt_count, battnum);
 		use_acpi = 1;
 		if (! delay)
-			delay = 3; /* sigh */
+			delay = 3; /* slow interface! */
 	}
 	else if (sonypi_supported()) {
 		use_sonypi = 1;
@@ -581,7 +598,7 @@ int main(int argc, char *argv[]) {
 	}
 	else {
 	
-		error("No APM, ACPI, or SPIC support in kernel.");
+		error("No APM, ACPI, " SYS_POWER ", or SPIC support in kernel.");
 	}
 		
 	load_images();

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-wmaker/wmbattery.git



More information about the Pkg-wmaker-commits mailing list