Check all battery variants when polling
On Thinkpads T410s sysfs may switch between energy_full/_now and charge_full/_now files across suspend/resume. Instead of polling only one set of files always try all variants when checking battery levels. This fixes a battery level of 0 in GKrellM after resume. Thanks to Joern Engel for tracking this down and for providing a patch via the Debian bugtracker. See also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=630117
This commit is contained in:
parent
9693241883
commit
3a487e3271
|
@ -1802,14 +1802,15 @@ acpi_battery_data(BatteryFile *bf)
|
||||||
#define SYSFS_TYPE_AC_ADAPTER "mains"
|
#define SYSFS_TYPE_AC_ADAPTER "mains"
|
||||||
|
|
||||||
|
|
||||||
|
#define VARIANTS 5
|
||||||
typedef struct syspower
|
typedef struct syspower
|
||||||
{
|
{
|
||||||
gint type;
|
gint type;
|
||||||
gint id;
|
gint id;
|
||||||
gint charge_units;
|
gint charge_units[VARIANTS];
|
||||||
gchar const *sysdir;
|
gchar const *sysdir;
|
||||||
gchar const *sys_charge_full;
|
gchar const *sys_charge_full[VARIANTS];
|
||||||
gchar const *sys_charge_now;
|
gchar const *sys_charge_now[VARIANTS];
|
||||||
gboolean present;
|
gboolean present;
|
||||||
gboolean ac_present;
|
gboolean ac_present;
|
||||||
gboolean charging;
|
gboolean charging;
|
||||||
|
@ -1873,7 +1874,6 @@ sysfs_power_data (struct syspower *sp)
|
||||||
gchar buf[128];
|
gchar buf[128];
|
||||||
gchar *syszap;
|
gchar *syszap;
|
||||||
gboolean charging;
|
gboolean charging;
|
||||||
gboolean stat_full;
|
|
||||||
|
|
||||||
time_left = -1;
|
time_left = -1;
|
||||||
charge_full = charge_now = 0;
|
charge_full = charge_now = 0;
|
||||||
|
@ -1910,15 +1910,26 @@ sysfs_power_data (struct syspower *sp)
|
||||||
|
|
||||||
if (present)
|
if (present)
|
||||||
{
|
{
|
||||||
if (read_sysfs_entry (buf, sizeof (buf), sp->sys_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);
|
charge_full = strtoll (buf, NULL, 0);
|
||||||
}
|
}
|
||||||
if (read_sysfs_entry (buf, sizeof (buf), sp->sys_charge_now))
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (read_sysfs_entry (buf, sizeof (buf), sp->sys_charge_now[i]))
|
||||||
{
|
{
|
||||||
charge_now = strtoll (buf, NULL, 0);
|
charge_now = strtoll (buf, NULL, 0);
|
||||||
}
|
}
|
||||||
if (sp->charge_units == CHGUNITS_PERCENT)
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sp->charge_units[i] == CHGUNITS_PERCENT)
|
||||||
{
|
{
|
||||||
percent = charge_now;
|
percent = charge_now;
|
||||||
}
|
}
|
||||||
|
@ -1927,6 +1938,8 @@ sysfs_power_data (struct syspower *sp)
|
||||||
if (charge_full > 0)
|
if (charge_full > 0)
|
||||||
percent = charge_now * 100 / charge_full;
|
percent = charge_now * 100 / charge_full;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get charging status. */
|
/* Get charging status. */
|
||||||
*syszap = '\0';
|
*syszap = '\0';
|
||||||
|
@ -1934,7 +1947,6 @@ sysfs_power_data (struct syspower *sp)
|
||||||
if (read_sysfs_entry (buf, sizeof (buf), sysentry))
|
if (read_sysfs_entry (buf, sizeof (buf), sysentry))
|
||||||
{
|
{
|
||||||
charging = !strcasecmp (buf, "charging");
|
charging = !strcasecmp (buf, "charging");
|
||||||
stat_full = !strcasecmp (buf, "full");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1952,12 +1964,10 @@ setup_sysfs_ac_power (gchar const *sysdir)
|
||||||
if (_GK.debug_level & DEBUG_BATTERY)
|
if (_GK.debug_level & DEBUG_BATTERY)
|
||||||
g_debug ("setup_sysfs_ac_power: %s\n", sysdir);
|
g_debug ("setup_sysfs_ac_power: %s\n", sysdir);
|
||||||
sp = g_new0 (syspower, 1);
|
sp = g_new0 (syspower, 1);
|
||||||
|
memset(sp, 0, sizeof(*sp));
|
||||||
sp->type = PWRTYPE_MAINS;
|
sp->type = PWRTYPE_MAINS;
|
||||||
sp->id = g_pwr_id++;
|
sp->id = g_pwr_id++;
|
||||||
sp->charge_units = CHGUNITS_INVALID;
|
|
||||||
sp->sysdir = g_strdup (sysdir);
|
sp->sysdir = g_strdup (sysdir);
|
||||||
sp->sys_charge_full =
|
|
||||||
sp->sys_charge_now = NULL;
|
|
||||||
|
|
||||||
/* Add mains power sources to head of list. */
|
/* Add mains power sources to head of list. */
|
||||||
g_sysfs_power_list = g_list_prepend (g_sysfs_power_list, sp);
|
g_sysfs_power_list = g_list_prepend (g_sysfs_power_list, sp);
|
||||||
|
@ -1969,94 +1979,39 @@ static gboolean
|
||||||
setup_sysfs_battery (gchar const *sysdir)
|
setup_sysfs_battery (gchar const *sysdir)
|
||||||
{
|
{
|
||||||
syspower *sp;
|
syspower *sp;
|
||||||
gchar *sys_charge_full = NULL,
|
|
||||||
*sys_charge_now = NULL;
|
|
||||||
gint units;
|
|
||||||
gboolean retval = FALSE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.)
|
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
sys_charge_now = g_strconcat (sysdir, "/capacity_now", NULL);
|
|
||||||
if (access (sys_charge_now, F_OK | R_OK))
|
|
||||||
goto ackphft; /* Look down */
|
|
||||||
|
|
||||||
done:
|
|
||||||
sp = g_new0 (syspower, 1);
|
sp = g_new0 (syspower, 1);
|
||||||
sp->type = PWRTYPE_BATTERY;
|
sp->type = PWRTYPE_BATTERY;
|
||||||
sp->id = g_pwr_id++;
|
sp->id = g_pwr_id++;
|
||||||
sp->charge_units = units;
|
|
||||||
sp->sysdir = g_strdup (sysdir);
|
sp->sysdir = g_strdup (sysdir);
|
||||||
sp->sys_charge_full = sys_charge_full;
|
/*
|
||||||
sp->sys_charge_now = sys_charge_now;
|
* There are three flavors of reporting: 'energy', 'charge', and
|
||||||
|
* 'capacity'. Check for them in that order.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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. */
|
/* Battery power sources are appended to the end of the list. */
|
||||||
g_sysfs_power_list = g_list_append (g_sysfs_power_list, sp);
|
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)
|
return TRUE;
|
||||||
{
|
|
||||||
ackphft:
|
|
||||||
if (sys_charge_full) g_free (sys_charge_full);
|
|
||||||
if (sys_charge_now) g_free (sys_charge_now);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
Loading…
Reference in New Issue