battstat support for acpi 20020208



this patch makes the acpi support in battstat work with the 20020208
release of acpi.

i just used the acpi file reading from the applet i wrote; i think it's
simpler and less prone to kernel changes (ie, if the order of fields
changes in the kernel the old applet would break).

also it removes C++ comments from acpi-linux.c

it should work with older (> 2.4.12) acpi also, but i haven't yet tested
this yet.  someone else running one of these please let me know if it
works or doesn't work before i commit this.

jacob
-- 
Index: acpi-linux.c
===================================================================
RCS file: /cvs/gnome/gnome-applets/battstat/acpi-linux.c,v
retrieving revision 1.3
diff -u -r1.3 acpi-linux.c
--- acpi-linux.c	2001/11/04 23:41:22	1.3
+++ acpi-linux.c	2002/02/18 06:26:06
@@ -18,8 +18,10 @@
  $Id: acpi-linux.c,v 1.3 2001/11/04 23:41:22 jdthood Exp $
  */
 
-// ACPI battery read-out functions for Linux >= 2.4.12
-// October 2001 by Lennart Poettering <lennart poettering de>
+/*
+ * ACPI battery read-out functions for Linux >= 2.4.12
+ * October 2001 by Lennart Poettering <lennart poettering de>
+ */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -32,87 +34,161 @@
 #include <glib.h>
 #include <string.h>
 #include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
 #include "acpi-linux.h"
 
-// Returns the first line of file f which starts with "field: " in
-// tmp. Return value is a pointer to the end of the string
-static gchar *al_get_field(FILE *f, const gchar *field, gchar *tmp, int s)
+static GHashTable *
+read_file (const char *file, char *buf, size_t bufsize)
 {
-  g_assert(f && field && tmp && s);
+  GHashTable *hash = NULL;
 
-  while (!feof(f))
-    {
-      gchar *c, *e;
-      
-      if (!fgets(tmp, s, f)) break;
-      
-      if ((c = strchr(tmp, ':'))) // Is a colon separated line
-        {
-          *c = 0;
-          if (strcmp(tmp, field) == 0) // It is the right line
-            {
-              c++; // Find the beginning of the data
-              if (*c)
-                c ++;
-              c = c + strspn(c, " \t");
-              
-              if ((e = strchr(c, 0)) > tmp) // Remove NL from end
-                {
-                  e--;
-                  if (*e == '\n')
-                    *e = 0;
-                }
-
-              return c;
-            }
-          
-        }
+  int fd, len, i;
+  char *key, *value;
+  gboolean reading_key;
+
+  fd = open (file, O_RDONLY);
+
+  if (fd == -1) {
+    g_message ("Couldn't open %s: %s", file, g_strerror (errno));
+    return hash;
+  }
+
+  len = read (fd, buf, bufsize);
+
+  close (fd);
+
+  if (len < 0) {
+    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 NULL;
+  }
+
+  return hash;
 }
 
-// Returns the same as the function above, but converted into an integer
-static int al_get_field_int(FILE *f, const gchar *field)
+#if 0
+static gboolean
+read_bool (GHashTable *hash, const char *key)
 {
-  gchar tmp[256];
-  gchar *p;
-  
-  g_assert(f && field);
- 
-  p = al_get_field(f, field, tmp, sizeof(tmp));
-  if (p)
-    return atoi(p);
-  else
-    return 0;
+  char *s;
+
+  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');
+}
+#endif
+
+static long
+read_long (GHashTable *hash, const char *key)
+{
+  char *s;
+
+  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;
 }
 
-// Fills out a classic apm_info structure with the data gathered from
-// the ACPI kernel interface in /proc
+static gulong
+read_ulong (GHashTable *hash, const char *key)
+{
+  char *s;
+
+  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;
+}
+
+static const char *
+read_string (GHashTable *hash, const char *key)
+{
+  return g_hash_table_lookup (hash, key);
+}
+
+/*
+ * 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)
 {
   guint32 max_capacity, low_capacity, critical_capacity, remain;
   gboolean charging, ac_online;
-  FILE *f;
-
-  // 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
+  gulong acpi_ver;
+  char buf[BUFSIZ];
+  GHashTable *hash;
+  const char *batt_info, *batt_state, *ac_state, *ac_state_state, *charging_state;
+
+  /*
+   * 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);
 
   max_capacity = 0;
   low_capacity = 0;
   critical_capacity = 0;
+
+  hash = read_file ("/proc/acpi/info", buf, sizeof (buf));
+  if (!hash)
+    return FALSE;
+
+  acpi_ver = read_ulong (hash, "version");
+  g_hash_table_destroy (hash);
 
-  if ((f = fopen("/proc/acpi/battery/1/info", "r")))
+  if (acpi_ver < (gulong)20020208) {
+    batt_info  = "/proc/acpi/battery/1/info";
+    batt_state = "/proc/acpi/battery/1/status";
+    ac_state   = "/proc/acpi/ac_adapter/0/status";
+    ac_state_state = "status";
+    charging_state = "state";
+  } else {
+    batt_info  = "/proc/acpi/battery/BAT1/info";
+    batt_state = "/proc/acpi/battery/BAT1/state";
+    ac_state   = "/proc/acpi/ac_adapter/ACAD/state";
+    ac_state_state = "state";
+    charging_state = "charging state";
+  }
+
+  hash = read_file (batt_info, buf, sizeof (buf));
+  if (hash)
     {
-      max_capacity = al_get_field_int(f, "Design Capacity");
-      low_capacity = al_get_field_int(f, "Design Capacity Warning");
-      critical_capacity = al_get_field_int(f, "Design Capacity Low");
-      
-      fclose(f);
+      max_capacity = read_long (hash, "design capacity");
+      low_capacity = read_long (hash, "design capacity warning");
+      critical_capacity = read_long (hash, "design capacity low");
+      g_hash_table_destroy (hash);
     }
   
   if (!max_capacity)
@@ -121,30 +197,25 @@
   charging = FALSE;
   remain = 0;
 
-  if ((f = fopen("/proc/acpi/battery/1/status", "r")))
+  hash = read_file (batt_state, buf, sizeof (buf));
+  if (hash)
     {
-      gchar *s;
-      gchar tmp[256];
-
-      if ((s = al_get_field(f, "State", tmp, sizeof(tmp))))
-        charging = strcmp(s, "charging") == 0;
-      
-      remain = al_get_field_int(f, "Remaining Capacity");
-
-      fclose(f);
+      const char *s;
+      s = read_string (hash, charging_state);
+      charging = s ? (strcmp (s, "charging") == 0) : 0;
+      remain = read_long (hash, "remaining capacity");
+      g_hash_table_destroy (hash);
     }
-  
+
   ac_online = FALSE;
   
-  if ((f = fopen("/proc/acpi/ac_adapter/0/status", "r")))
+  hash = read_file (ac_state, buf, sizeof (buf));
+  if (hash)
     {
-      gchar *s;
-      gchar tmp[256];      
-
-      if ((s = al_get_field(f, "Status", tmp, sizeof(tmp))))
-        ac_online = strcmp(s, "on-line") == 0;
-
-      fclose(f);
+      const char *s;
+      s = read_string (hash, ac_state_state);
+      ac_online = s ? (strcmp (s, "on-line") == 0) : 0;
+      g_hash_table_destroy (hash);
     }
 
   apminfo->ac_line_status = ac_online ? 1 : 0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]