summaryrefslogtreecommitdiff
path: root/battstat/acpi-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'battstat/acpi-linux.c')
-rw-r--r--battstat/acpi-linux.c632
1 files changed, 321 insertions, 311 deletions
diff --git a/battstat/acpi-linux.c b/battstat/acpi-linux.c
index afda8fd7..c383bd2e 100644
--- a/battstat/acpi-linux.c
+++ b/battstat/acpi-linux.c
@@ -24,7 +24,7 @@
*/
#ifdef HAVE_CONFIG_H
- #include <config.h>
+ #include <config.h>
#endif
#ifdef __linux__
@@ -44,91 +44,92 @@
#include <dirent.h>
#include "acpi-linux.h"
-static GHashTable* read_file(const char* file, char* buf, size_t bufsize)
+static GHashTable*
+read_file (const char* file, char* buf, size_t bufsize)
{
- GHashTable* hash = NULL;
-
- int fd, len, i;
- char* key;
- char* value;
- gboolean reading_key;
-
- fd = open(file, O_RDONLY);
-
- if (fd == -1)
- {
- return hash;
- }
-
- len = read(fd, buf, bufsize);
-
- close (fd);
-
- if (len < 0)
- {
- if (getenv("BATTSTAT_DEBUG"))
- {
- g_message("Error reading %s: %s", file, g_strerror(errno));
- }
-
- return hash;
- }
-
- hash = g_hash_table_new(g_str_hash, g_str_equal);
-
- for (i = 0, value = key = buf, reading_key = TRUE; i < len; i++)
- {
- if (buf[i] == ':' && reading_key)
- {
- reading_key = FALSE;
- buf[i] = '\0';
- value = buf + i + 1;
- }
- else if (buf[i] == '\n')
- {
- reading_key = TRUE;
- buf[i] = '\0';
- /* g_message ("Read: %s => %s\n", key, value); */
- g_hash_table_insert(hash, key, g_strstrip(value));
- key = buf + i + 1;
- }
- else if (reading_key)
- {
- /* in acpi 20020214 it switched to lower-case proc
- * entries. fixing this up here simplifies the
- * code.
- */
- buf[i] = g_ascii_tolower(buf[i]);
- }
- }
-
- return hash;
+ GHashTable* hash = NULL;
+
+ int fd, len, i;
+ char* key;
+ char* value;
+ gboolean reading_key;
+
+ fd = open (file, O_RDONLY);
+
+ if (fd == -1)
+ {
+ return hash;
+ }
+
+ len = read (fd, buf, bufsize);
+
+ close (fd);
+
+ if (len < 0)
+ {
+ if (getenv ("BATTSTAT_DEBUG"))
+ {
+ g_message ("Error reading %s: %s", file, g_strerror (errno));
+ }
+
+ return hash;
+ }
+
+ hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0, value = key = buf, reading_key = TRUE; i < len; i++)
+ {
+ if (buf[i] == ':' && reading_key)
+ {
+ reading_key = FALSE;
+ buf[i] = '\0';
+ value = buf + i + 1;
+ }
+ else if (buf[i] == '\n')
+ {
+ reading_key = TRUE;
+ buf[i] = '\0';
+ /* g_message ("Read: %s => %s\n", key, value); */
+ g_hash_table_insert (hash, key, g_strstrip (value));
+ key = buf + i + 1;
+ }
+ else if (reading_key)
+ {
+ /* in acpi 20020214 it switched to lower-case proc
+ * entries. fixing this up here simplifies the
+ * code.
+ */
+ buf[i] = g_ascii_tolower (buf[i]);
+ }
+ }
+
+ return hash;
}
#if 0
static gboolean
read_bool (GHashTable *hash, const char *key)
{
- char *s;
+ char *s;
- g_return_val_if_fail (hash, FALSE);
- g_return_val_if_fail (key, FALSE);
+ g_return_val_if_fail (hash, FALSE);
+ g_return_val_if_fail (key, FALSE);
- s = g_hash_table_lookup (hash, key);
- return s && (*s == 'y');
+ s = g_hash_table_lookup (hash, key);
+ return s && (*s == 'y');
}
#endif
static long
read_long (GHashTable *hash, const char *key)
{
- char* s;
+ char* s;
- g_return_val_if_fail(hash, 0);
- g_return_val_if_fail(key, 0);
+ g_return_val_if_fail (hash, 0);
+ g_return_val_if_fail (key, 0);
- s = g_hash_table_lookup(hash, key);
- return s ? strtol(s, NULL, 10) : 0;
+ s = g_hash_table_lookup (hash, key);
+ return s ? strtol (s, NULL, 10) : 0;
}
static gulong
@@ -136,112 +137,114 @@ read_ulong (GHashTable *hash, const char *key)
{
char *s;
- g_return_val_if_fail (hash, 0);
- g_return_val_if_fail (key, 0);
+ g_return_val_if_fail (hash, 0);
+ g_return_val_if_fail (key, 0);
- s = g_hash_table_lookup (hash, key);
- return s ? strtoul (s, NULL, 10) : 0;
+ s = g_hash_table_lookup (hash, key);
+ return s ? strtoul (s, NULL, 10) : 0;
}
static const char *
read_string (GHashTable *hash, const char *key)
{
- return g_hash_table_lookup (hash, key);
+ return g_hash_table_lookup (hash, key);
}
/* Reads the current status of the AC adapter and stores the
* result in acpiinfo->ac_online. */
-static gboolean update_ac_info(struct acpi_info * acpiinfo)
+static gboolean
+update_ac_info (struct acpi_info * acpiinfo)
{
- gchar *ac_state = NULL;
- DIR * procdir;
- struct dirent * procdirentry;
- char buf[BUFSIZ];
- GHashTable *hash;
- gboolean have_adaptor = FALSE;
-
- acpiinfo->ac_online = FALSE;
-
- procdir=opendir("/proc/acpi/ac_adapter/");
- if (!procdir)
- return FALSE;
-
- while ((procdirentry=readdir(procdir)))
- {
- if (procdirentry->d_name[0]!='.')
- {
- have_adaptor = TRUE;
- ac_state = g_strconcat("/proc/acpi/ac_adapter/",
- procdirentry->d_name,
- "/",
- acpiinfo->ac_state_state,
- NULL);
- hash = read_file (ac_state, buf, sizeof (buf));
- if (hash && !acpiinfo->ac_online)
- {
- const char *s;
- s = read_string (hash, acpiinfo->ac_state_state);
- acpiinfo->ac_online = s ? (strcmp (s, "on-line") == 0) : 0;
- g_hash_table_destroy (hash);
- }
- g_free(ac_state);
- }
- }
+ gchar *ac_state = NULL;
+ DIR * procdir;
+ struct dirent * procdirentry;
+ char buf[BUFSIZ];
+ GHashTable *hash;
+ gboolean have_adaptor = FALSE;
+
+ acpiinfo->ac_online = FALSE;
+
+ procdir=opendir ("/proc/acpi/ac_adapter/");
+ if (!procdir)
+ return FALSE;
+
+ while ((procdirentry=readdir (procdir)))
+ {
+ if (procdirentry->d_name[0]!='.')
+ {
+ have_adaptor = TRUE;
+ ac_state = g_strconcat ("/proc/acpi/ac_adapter/",
+ procdirentry->d_name,
+ "/",
+ acpiinfo->ac_state_state,
+ NULL);
+ hash = read_file (ac_state, buf, sizeof (buf));
+ if (hash && !acpiinfo->ac_online)
+ {
+ const char *s;
+ s = read_string (hash, acpiinfo->ac_state_state);
+ acpiinfo->ac_online = s ? (strcmp (s, "on-line") == 0) : 0;
+ g_hash_table_destroy (hash);
+ }
+ g_free (ac_state);
+ }
+ }
/* If there are no AC adaptors registered in the system, then we're
probably on a desktop (and therefore, on AC power).
*/
- if (have_adaptor == FALSE)
- acpiinfo->ac_online = 1;
+ if (have_adaptor == FALSE)
+ acpiinfo->ac_online = 1;
- closedir(procdir);
+ closedir (procdir);
- return TRUE;
+ return TRUE;
}
/* Reads the ACPI info for the system batteries, and finds
* the total capacity, which is stored in acpiinfo. */
-static gboolean update_battery_info(struct acpi_info* acpiinfo)
+static gboolean
+update_battery_info (struct acpi_info* acpiinfo)
{
- gchar* batt_info = NULL;
- GHashTable* hash;
- DIR* procdir;
- struct dirent* procdirentry;
- char buf[BUFSIZ];
-
- acpiinfo->max_capacity = 0;
- acpiinfo->low_capacity = 0;
- acpiinfo->critical_capacity = 0;
-
- procdir = opendir("/proc/acpi/battery/");
-
- if (!procdir)
- {
- return FALSE;
- }
-
- while ((procdirentry = readdir(procdir)))
- {
- if (procdirentry->d_name[0] != '.')
- {
- batt_info = g_strconcat("/proc/acpi/battery/", procdirentry->d_name, "/info", NULL);
- hash = read_file(batt_info, buf, sizeof(buf));
-
- if (hash)
- {
- acpiinfo->max_capacity += read_long(hash, "last full capacity");
- acpiinfo->low_capacity += read_long(hash, "design capacity warning");
- acpiinfo->critical_capacity += read_long(hash, "design capacity low");
-
- g_hash_table_destroy(hash);
- }
- g_free(batt_info);
- }
- }
-
- closedir(procdir);
-
- return TRUE;
+ gchar* batt_info = NULL;
+ GHashTable* hash;
+ DIR* procdir;
+ struct dirent* procdirentry;
+ char buf[BUFSIZ];
+
+ acpiinfo->max_capacity = 0;
+ acpiinfo->low_capacity = 0;
+ acpiinfo->critical_capacity = 0;
+
+ procdir = opendir ("/proc/acpi/battery/");
+
+ if (!procdir)
+ {
+ return FALSE;
+ }
+
+ while ((procdirentry = readdir (procdir)))
+ {
+ if (procdirentry->d_name[0] != '.')
+ {
+ batt_info = g_strconcat ("/proc/acpi/battery/", procdirentry->d_name, "/info", NULL);
+ hash = read_file (batt_info, buf, sizeof (buf));
+
+ if (hash)
+ {
+ acpiinfo->max_capacity += read_long (hash, "last full capacity");
+ acpiinfo->low_capacity += read_long (hash, "design capacity warning");
+ acpiinfo->critical_capacity += read_long (hash, "design capacity low");
+
+ g_hash_table_destroy (hash);
+ }
+ g_free (batt_info);
+ }
+ }
+
+ closedir (procdir);
+
+ return TRUE;
}
@@ -250,72 +253,74 @@ static gboolean update_battery_info(struct acpi_info* acpiinfo)
* /proc/acpi/event exported by the kernel, or if it's already
* in use, the /var/run/acpid.socket maintained by acpid. Also
* initializes the stored battery and AC adapter information. */
-gboolean acpi_linux_init(struct acpi_info * acpiinfo)
+gboolean
+acpi_linux_init (struct acpi_info * acpiinfo)
{
- GHashTable *hash;
- char buf[BUFSIZ];
- gchar *pbuf;
- gulong acpi_ver;
- int fd;
-
- g_assert(acpiinfo);
-
- if (g_file_get_contents ("/sys/module/acpi/parameters/acpica_version", &pbuf, NULL, NULL)) {
- acpi_ver = strtoul (pbuf, NULL, 10);
- g_free (pbuf);
- } else if ((hash = read_file ("/proc/acpi/info", buf, sizeof (buf)))) {
- acpi_ver = read_ulong (hash, "version");
- g_hash_table_destroy (hash);
- } else
- return FALSE;
-
- if (acpi_ver < (gulong)20020208) {
- acpiinfo->ac_state_state = "status";
- acpiinfo->batt_state_state = "status";
- acpiinfo->charging_state = "state";
- } else {
- acpiinfo->ac_state_state = "state";
- acpiinfo->batt_state_state = "state";
- acpiinfo->charging_state = "charging state";
- }
-
- if (!update_battery_info(acpiinfo) || !update_ac_info(acpiinfo))
- return FALSE;
+ GHashTable *hash;
+ char buf[BUFSIZ];
+ gchar *pbuf;
+ gulong acpi_ver;
+ int fd;
+
+ g_assert (acpiinfo);
+
+ if (g_file_get_contents ("/sys/module/acpi/parameters/acpica_version", &pbuf, NULL, NULL)) {
+ acpi_ver = strtoul (pbuf, NULL, 10);
+ g_free (pbuf);
+ } else if ((hash = read_file ("/proc/acpi/info", buf, sizeof (buf)))) {
+ acpi_ver = read_ulong (hash, "version");
+ g_hash_table_destroy (hash);
+ } else
+ return FALSE;
+
+ if (acpi_ver < (gulong)20020208) {
+ acpiinfo->ac_state_state = "status";
+ acpiinfo->batt_state_state = "status";
+ acpiinfo->charging_state = "state";
+ } else {
+ acpiinfo->ac_state_state = "state";
+ acpiinfo->batt_state_state = "state";
+ acpiinfo->charging_state = "charging state";
+ }
- fd = open("/proc/acpi/event", 0);
- if (fd >= 0) {
- acpiinfo->event_fd = fd;
- acpiinfo->channel = g_io_channel_unix_new(fd);
- return TRUE;
- }
-
- fd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (fd >= 0) {
- struct sockaddr_un addr;
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, "/var/run/acpid.socket");
- if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == 0) {
- acpiinfo->event_fd = fd;
- acpiinfo->channel = g_io_channel_unix_new(fd);
- return TRUE;
+ if (!update_battery_info (acpiinfo) || !update_ac_info (acpiinfo))
+ return FALSE;
+
+ fd = open ("/proc/acpi/event", 0);
+ if (fd >= 0) {
+ acpiinfo->event_fd = fd;
+ acpiinfo->channel = g_io_channel_unix_new (fd);
+ return TRUE;
+ }
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd >= 0) {
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, "/var/run/acpid.socket");
+ if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == 0) {
+ acpiinfo->event_fd = fd;
+ acpiinfo->channel = g_io_channel_unix_new (fd);
+ return TRUE;
+ }
}
- }
- close(fd);
- acpiinfo->event_fd = -1;
- return FALSE;
+ close (fd);
+ acpiinfo->event_fd = -1;
+ return FALSE;
}
/* Cleans up ACPI */
-void acpi_linux_cleanup(struct acpi_info * acpiinfo)
+void
+acpi_linux_cleanup (struct acpi_info * acpiinfo)
{
- g_assert(acpiinfo);
+ g_assert (acpiinfo);
- if (acpiinfo->event_fd >= 0) {
- g_io_channel_unref(acpiinfo->channel);
- close(acpiinfo->event_fd);
- acpiinfo->event_fd = -1;
- }
+ if (acpiinfo->event_fd >= 0) {
+ g_io_channel_unref (acpiinfo->channel);
+ close (acpiinfo->event_fd);
+ acpiinfo->event_fd = -1;
+ }
}
#define ACPI_EVENT_IGNORE 0
@@ -326,56 +331,60 @@ void acpi_linux_cleanup(struct acpi_info * acpiinfo)
/* Given a string event from the ACPI system, returns the type
* of event if we're interested in it. str is updated to point
* to the next event. */
-static int parse_acpi_event(GString *buffer)
+static int
+parse_acpi_event (GString *buffer)
{
- if (strstr(buffer->str, "ac_adapter"))
- return ACPI_EVENT_AC;
- if (strstr(buffer->str, "battery") )
- return ACPI_EVENT_BATTERY_INFO;
+ if (strstr (buffer->str, "ac_adapter"))
+ return ACPI_EVENT_AC;
+ if (strstr (buffer->str, "battery"))
+ return ACPI_EVENT_BATTERY_INFO;
- return ACPI_EVENT_IGNORE;
+ return ACPI_EVENT_IGNORE;
}
/* Handles a new ACPI event by reading it from the event file
* and calling any handlers. Since this does a blocking read,
* it should only be called when there is a new event as indicated
- * by select(). */
-gboolean acpi_process_event(struct acpi_info * acpiinfo)
+ * by select (). */
+gboolean acpi_process_event (struct acpi_info * acpiinfo)
{
gsize i;
int evt;
GString *buffer;
GError *gerror=NULL;
- buffer=g_string_new(NULL);
- g_io_channel_read_line_string ( acpiinfo->channel,buffer,&i,&gerror);
+ buffer=g_string_new (NULL);
+ g_io_channel_read_line_string (acpiinfo->channel,
+ buffer,
+ &i,
+ &gerror);
if (gerror != NULL) {
- g_warning ("%s", gerror->message);
- g_error_free (gerror);
+ g_warning ("%s", gerror->message);
+ g_error_free (gerror);
}
gboolean result;
- evt = parse_acpi_event(buffer);
- switch (evt) {
+ evt = parse_acpi_event (buffer);
+ switch (evt) {
case ACPI_EVENT_AC:
- result = update_ac_info(acpiinfo);
- break;
- case ACPI_EVENT_BATTERY_INFO:
- if (update_battery_info(acpiinfo)) {
- /* Update AC info on battery info updates. This works around
- * a bug in ACPI (as per bug #163013).
- */
- result = update_ac_info(acpiinfo);
+ result = update_ac_info (acpiinfo);
break;
- }
- /* fall-through */
+ case ACPI_EVENT_BATTERY_INFO:
+ if (update_battery_info (acpiinfo)) {
+ /* Update AC info on battery info updates. This works around
+ * a bug in ACPI (as per bug #163013).
+ */
+ result = update_ac_info (acpiinfo);
+ break;
+ }
+ /* fall-through */
default:
- result = FALSE;
- }
+ result = FALSE;
+ }
- g_string_free(buffer, FALSE);
+ g_string_free (buffer, FALSE);
return result;
}
@@ -383,82 +392,83 @@ gboolean acpi_process_event(struct acpi_info * acpiinfo)
* Fills out a classic apm_info structure with the data gathered from
* the ACPI kernel interface in /proc
*/
-gboolean acpi_linux_read(struct apm_info *apminfo, struct acpi_info * acpiinfo)
+gboolean
+acpi_linux_read (struct apm_info *apminfo, struct acpi_info * acpiinfo)
{
- guint32 remain;
- guint32 rate;
- gboolean charging;
- GHashTable *hash;
- gchar* batt_state = NULL;
- DIR * procdir;
- struct dirent * procdirentry;
- char buf[BUFSIZ];
-
- g_assert(acpiinfo);
-
- /*
- * apminfo.ac_line_status must be one when on ac power
- * apminfo.battery_status must be 0 for high, 1 for low, 2 for critical, 3 for charging
- * apminfo.battery_percentage must contain batter charge percentage
- * apminfo.battery_flags & 0x8 must be nonzero when charging
- */
-
- g_assert(apminfo);
-
- charging = FALSE;
- remain = 0;
- rate = 0;
-
- procdir=opendir("/proc/acpi/battery/");
- if (!procdir)
- return FALSE;
+ guint32 remain;
+ guint32 rate;
+ gboolean charging;
+ GHashTable *hash;
+ gchar* batt_state = NULL;
+ DIR * procdir;
+ struct dirent * procdirentry;
+ char buf[BUFSIZ];
+
+ g_assert (acpiinfo);
+
+ /*
+ * apminfo.ac_line_status must be one when on ac power
+ * apminfo.battery_status must be 0 for high, 1 for low, 2 for critical, 3 for charging
+ * apminfo.battery_percentage must contain batter charge percentage
+ * apminfo.battery_flags & 0x8 must be nonzero when charging
+ */
+
+ g_assert (apminfo);
+
+ charging = FALSE;
+ remain = 0;
+ rate = 0;
+
+ procdir=opendir ("/proc/acpi/battery/");
+ if (!procdir)
+ return FALSE;
+
+ /* Get the remaining capacity for the batteries. Other information
+ * such as AC state and battery max capacity are read only when they
+ * change using acpi_process_event (). */
+ while ((procdirentry=readdir (procdir)))
+ {
+ if (procdirentry->d_name[0]!='.')
+ {
+ batt_state = g_strconcat ("/proc/acpi/battery/",
+ procdirentry->d_name,
+ "/",
+ acpiinfo->batt_state_state,
+ NULL);
+ hash = read_file (batt_state, buf, sizeof (buf));
+ if (hash)
+ {
+ const char *s;
+ if (!charging)
+ {
+ s = read_string (hash, acpiinfo->charging_state);
+ charging = s ? (strcmp (s, "charging") == 0) : 0;
+ }
+ remain += read_long (hash, "remaining capacity");
+ rate += read_long (hash, "present rate");
+ g_hash_table_destroy (hash);
+ }
+ g_free (batt_state);
+ }
+ }
+ closedir (procdir);
+
+ apminfo->ac_line_status = acpiinfo->ac_online ? 1 : 0;
+ apminfo->battery_status =
+ remain < acpiinfo->low_capacity ? 1 : remain < acpiinfo->critical_capacity ? 2 : 0;
+ if (!acpiinfo->max_capacity)
+ apminfo->battery_percentage = -1;
+ else
+ apminfo->battery_percentage = (int) (remain/(float)acpiinfo->max_capacity*100);
+ apminfo->battery_flags = charging ? 0x8 : 0;
+ if (rate && !charging)
+ apminfo->battery_time = (int) (remain/(float)rate * 60);
+ else if (rate && charging)
+ apminfo->battery_time = (int) ((acpiinfo->max_capacity-remain)/(float)rate * 60);
+ else
+ apminfo->battery_time = -1;
- /* Get the remaining capacity for the batteries. Other information
- * such as AC state and battery max capacity are read only when they
- * change using acpi_process_event(). */
- while ((procdirentry=readdir(procdir)))
- {
- if (procdirentry->d_name[0]!='.')
- {
- batt_state = g_strconcat("/proc/acpi/battery/",
- procdirentry->d_name,
- "/",
- acpiinfo->batt_state_state,
- NULL);
- hash = read_file (batt_state, buf, sizeof (buf));
- if (hash)
- {
- const char *s;
- if (!charging)
- {
- s = read_string (hash, acpiinfo->charging_state);
- charging = s ? (strcmp (s, "charging") == 0) : 0;
- }
- remain += read_long (hash, "remaining capacity");
- rate += read_long (hash, "present rate");
- g_hash_table_destroy (hash);
- }
- g_free(batt_state);
- }
- }
- closedir(procdir);
-
- apminfo->ac_line_status = acpiinfo->ac_online ? 1 : 0;
- apminfo->battery_status = remain < acpiinfo->low_capacity ? 1 : remain < acpiinfo->critical_capacity ? 2 : 0;
- if (!acpiinfo->max_capacity)
- apminfo->battery_percentage = -1;
- else
- apminfo->battery_percentage = (int) (remain/(float)acpiinfo->max_capacity*100);
- apminfo->battery_flags = charging ? 0x8 : 0;
- if (rate && !charging)
- apminfo->battery_time = (int) (remain/(float)rate * 60);
- else if (rate && charging)
- apminfo->battery_time = (int) ((acpiinfo->max_capacity-remain)/(float)rate * 60);
- else
- apminfo->battery_time = -1;
-
- return TRUE;
+ return TRUE;
}
-
#endif /* __linux__ */