Hello Jörn,
thanks for looking into this!

I'm also forwarding your results on gkrellm mailing list, so upstream
authors can have a look at your patch and comment/commit it.

Dear gkrellm authors, attached is a patch to fix a problem with
battery level upon suspension; you can also have a look at the full
bug history to get a better idea of how Jörn reached to this patch:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=630117

Cheers,
Sandro

On Sun, Apr 1, 2012 at 23:48, Jörn Engel <jo...@logfs.org> wrote:
> 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 <jo...@logfs.org>
> ---
>  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
>
>
>



-- 
Sandro Tosi (aka morph, morpheus, matrixhasu)
My website: http://matrixhasu.altervista.org/
Me at Debian: http://wiki.debian.org/SandroTosi



--
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to