On Thinkpads T410s I have observed sysfs to switch between energy_full
and friends and charge_full and friends across suspend/resume.  Result
is a battery level of 0 after resume, which is annoying at best and can
result in unwanted reboots at worst (when abusing gkrellm to suspend the
system if battery runs low).

While one can argue that the kernel should make up its mind and stick to
one variant, the bad kernels are an ugly fact of life and we have to
deal with them.

signed-off-by: Joern Engel <[email protected]>
---
 src/sysdeps/linux.c |  157 ++++++++++++++++++---------------------------------
 1 files changed, 56 insertions(+), 101 deletions(-)

diff --git a/src/sysdeps/linux.c b/src/sysdeps/linux.c
index e4ff625..a167d70 100644
--- a/src/sysdeps/linux.c
+++ b/src/sysdeps/linux.c
@@ -1801,14 +1801,15 @@ acpi_battery_data(BatteryFile *bf)
 #define        SYSFS_TYPE_AC_ADAPTER           "mains"
 
 
+#define VARIANTS               5
 typedef struct syspower
        {
        gint            type;
        gint            id;
-       gint            charge_units;
+       gint            charge_units[VARIANTS];
        gchar const     *sysdir;
-       gchar const     *sys_charge_full;
-       gchar const     *sys_charge_now;
+       gchar const     *sys_charge_full[VARIANTS];
+       gchar const     *sys_charge_now[VARIANTS];
        gboolean        present;
        gboolean        ac_present;
        gboolean        charging;
@@ -1872,7 +1873,6 @@ sysfs_power_data (struct syspower *sp)
        gchar           buf[128];
        gchar           *syszap;
        gboolean        charging;
-       gboolean        stat_full;
 
        time_left = -1;
        charge_full = charge_now = 0;
@@ -1909,23 +1909,36 @@ sysfs_power_data (struct syspower *sp)
 
        if (present)
                {
-               if (read_sysfs_entry (buf, sizeof (buf), sp->sys_charge_full))
-                       {
-                       charge_full = strtoll (buf, NULL, 0);
-                       }
-               if (read_sysfs_entry (buf, sizeof (buf), sp->sys_charge_now))
-                       {
-                       charge_now = strtoll (buf, NULL, 0);
-                       }
-               if (sp->charge_units == CHGUNITS_PERCENT)
-                       {
-                       percent = charge_now;
-                       }
-               else
-                       {
-                       if (charge_full > 0)
-                               percent = charge_now * 100 / charge_full;
-                       }
+               int i;
+
+               for (i = 0; i < VARIANTS; i++) {
+                       if (read_sysfs_entry (buf, sizeof (buf), 
sp->sys_charge_full[i]))
+                               {
+                               charge_full = strtoll (buf, NULL, 0);
+                               }
+                       else
+                               {
+                               continue;
+                               }
+                       if (read_sysfs_entry (buf, sizeof (buf), 
sp->sys_charge_now[i]))
+                               {
+                               charge_now = strtoll (buf, NULL, 0);
+                               }
+                       else
+                               {
+                               continue;
+                               }
+                       if (sp->charge_units[i] == CHGUNITS_PERCENT)
+                               {
+                               percent = charge_now;
+                               }
+                       else
+                               {
+                               if (charge_full > 0)
+                                       percent = charge_now * 100 / 
charge_full;
+                               }
+                       break;
+               }
 
                /*  Get charging status.  */
                *syszap = '\0';
@@ -1933,7 +1946,6 @@ sysfs_power_data (struct syspower *sp)
                if (read_sysfs_entry (buf, sizeof (buf), sysentry))
                        {
                        charging = !strcasecmp (buf, "charging");
-                       stat_full = !strcasecmp (buf, "full");
                        }
                }
 
@@ -1951,12 +1963,10 @@ setup_sysfs_ac_power (gchar const *sysdir)
        if (_GK.debug_level & DEBUG_BATTERY)
                g_debug ("setup_sysfs_ac_power: %s\n", sysdir);
        sp = g_new0 (syspower, 1);
+       memset(sp, 0, sizeof(*sp));
        sp->type                        = PWRTYPE_MAINS;
        sp->id                          = g_pwr_id++;
-       sp->charge_units        = CHGUNITS_INVALID;
        sp->sysdir                      = g_strdup (sysdir);
-       sp->sys_charge_full     =
-       sp->sys_charge_now      = NULL;
 
        /*  Add mains power sources to head of list.  */
        g_sysfs_power_list = g_list_prepend (g_sysfs_power_list, sp);
@@ -1968,94 +1978,39 @@ static gboolean
 setup_sysfs_battery (gchar const *sysdir)
        {
        syspower        *sp;
-       gchar           *sys_charge_full = NULL,
-                               *sys_charge_now = NULL;
-       gint            units;
-       gboolean        retval = FALSE;
 
+       sp = g_new0 (syspower, 1);
+       sp->type                        = PWRTYPE_BATTERY;
+       sp->id                          = g_pwr_id++;
+       sp->sysdir                      = g_strdup (sysdir);
        /*
         * There are three flavors of reporting:  'energy', 'charge', and
-        * 'capacity'.  Check for them in that order.  (Apologies for the
-        * ugliness; you try coding an unrolled 'if ((A || B) && C)' and make it
-        * pretty.)
+        * 'capacity'.  Check for them in that order.
         */
-       if (_GK.debug_level & DEBUG_BATTERY)
-               g_debug ("setup_sysfs_battery: %s\n", sysdir);
-       units = CHGUNITS_uWH;
-       sys_charge_full = g_strconcat (sysdir, "/energy_full", NULL);
-       if (access (sys_charge_full, F_OK | R_OK))
-               {
-               g_free (sys_charge_full);
-               sys_charge_full = g_strconcat (sysdir, "/energy_full_design", 
NULL);
-               if (access (sys_charge_full, F_OK | R_OK))
-                       {
-                       goto try_charge;        /*  Look down  */
-                       }
-               }
-       sys_charge_now = g_strconcat (sysdir, "/energy_now", NULL);
-       if (!access (sys_charge_now, F_OK | R_OK))
-               goto done;      /*  Look down  */
-
-try_charge:
-       if (sys_charge_full)    g_free (sys_charge_full), sys_charge_full = 
NULL;
-       if (sys_charge_now)             g_free (sys_charge_now), sys_charge_now 
= NULL;
-
-       units = CHGUNITS_uAH;
-       sys_charge_full = g_strconcat (sysdir, "/charge_full", NULL);
-       if (access (sys_charge_full, F_OK | R_OK))
-               {
-               g_free (sys_charge_full);
-               sys_charge_full = g_strconcat (sysdir, "/charge_full_design", 
NULL);
-               if (access (sys_charge_full, F_OK | R_OK))
-                       {
-                       goto try_capacity;      /*  Look down  */
-                       }
-               }
-       sys_charge_now = g_strconcat (sysdir, "/charge_now", NULL);
-       if (!access (sys_charge_now, F_OK | R_OK))
-               goto done;      /*  Look down  */
+       sp->charge_units[0] = CHGUNITS_uWH;
+       sp->sys_charge_full[0] = g_strconcat (sysdir, "/energy_full", NULL);
+       sp->sys_charge_now[0] = g_strconcat (sysdir, "/energy_now", NULL);
 
-try_capacity:
-       if (sys_charge_full)    g_free (sys_charge_full), sys_charge_full = 
NULL;
-       if (sys_charge_now)             g_free (sys_charge_now), sys_charge_now 
= NULL;
+       sp->charge_units[1] = CHGUNITS_uWH;
+       sp->sys_charge_full[1] = g_strconcat (sysdir, "/energy_full_design", 
NULL);
+       sp->sys_charge_now[1] = g_strconcat (sysdir, "/energy_now", NULL);
 
-       /*  This one's a little simpler...  */
-       units = CHGUNITS_PERCENT;
-       /*
-        * FIXME: I have no idea if 'capacity_full' actually shows up, since
-        * 'capacity' always defines "full" as always 100%
-        */
-       sys_charge_full = g_strconcat (sysdir, "/capacity_full", NULL);
-       if (access (sys_charge_full, F_OK | R_OK))
-               goto ackphft;   /*  Look down  */
+       sp->charge_units[2] = CHGUNITS_uAH;
+       sp->sys_charge_full[2] = g_strconcat (sysdir, "/charge_full", NULL);
+       sp->sys_charge_now[2] = g_strconcat (sysdir, "/charge_now", NULL);
 
-       sys_charge_now = g_strconcat (sysdir, "/capacity_now", NULL);
-       if (access (sys_charge_now, F_OK | R_OK))
-               goto ackphft;   /*  Look down  */
+       sp->charge_units[3] = CHGUNITS_uAH;
+       sp->sys_charge_full[3] = g_strconcat (sysdir, "/charge_full_design", 
NULL);
+       sp->sys_charge_now[3] = g_strconcat (sysdir, "/charge_now", NULL);
 
-done:
-       sp = g_new0 (syspower, 1);
-       sp->type                        = PWRTYPE_BATTERY;
-       sp->id                          = g_pwr_id++;
-       sp->charge_units        = units;
-       sp->sysdir                      = g_strdup (sysdir);
-       sp->sys_charge_full     = sys_charge_full;
-       sp->sys_charge_now      = sys_charge_now;
+       sp->charge_units[4] = CHGUNITS_PERCENT;
+       sp->sys_charge_full[4] = g_strconcat (sysdir, "/capacity_full", NULL);
+       sp->sys_charge_now[4] = g_strconcat (sysdir, "/capacity_now", NULL);
 
        /*  Battery power sources are appended to the end of the list.  */
        g_sysfs_power_list = g_list_append (g_sysfs_power_list, sp);
-       if (_GK.debug_level & DEBUG_BATTERY)
-               g_debug ("setup_sysfs_battery: %s, %s\n",
-                       sys_charge_full, sys_charge_now);
-       retval = TRUE;
 
-       if (0)
-               {
-ackphft:
-               if (sys_charge_full)    g_free (sys_charge_full);
-               if (sys_charge_now)             g_free (sys_charge_now);
-               }
-       return retval;
+       return TRUE;
        }
 
 static gboolean
-- 
1.7.9.1




-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to