tags 466878 + patch
thanks

Hello,

On Mon, 18 Feb 2008, Kapil Hari Paranjape wrote:
> The /sys/class/power_supply/BAT*/uevent output is somewhat
> different from the /proc/acpi/battery/BAT*/state output.

It is more different than I thought! On some systems the value
of POWER_SUPPLY_ENERGY_* is not available and is replaced by
POWER_SUPPLY_CHARGE_*!

> Other than that, all I can say is that this patch "Works For Me" :-)

I hope the enclosed patch will work for more people!

Regards,

Kapil.
--

Index: conky-1.4.9/src/linux.c
===================================================================
--- conky-1.4.9.orig/src/linux.c        2008-02-21 13:49:03.000000000 +0000
+++ conky-1.4.9/src/linux.c     2008-02-22 00:35:58.000000000 +0000
@@ -1257,10 +1257,36 @@
 2241<@jupet?kellari??> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori p??ll? 
mutta ilman verkkovirtaa
 */
 
+/* Kapil Hari Paranjape <[EMAIL PROTECTED]>
+  Linux 2.6.24 onwards battery info is in
+  /sys/class/power_supply/BAT0/
+  On my system I get the following.
+       /sys/class/power_supply/BAT0/uevent:
+       
PHYSDEVPATH=/devices/LNXSYSTM:00/device:00/PNP0A03:00/device:01/PNP0C09:00/PNP0C0A:00
+       PHYSDEVBUS=acpi
+       PHYSDEVDRIVER=battery
+       POWER_SUPPLY_NAME=BAT0
+       POWER_SUPPLY_TYPE=Battery
+       POWER_SUPPLY_STATUS=Discharging
+       POWER_SUPPLY_PRESENT=1
+       POWER_SUPPLY_TECHNOLOGY=Li-ion
+       POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000
+       POWER_SUPPLY_VOLTAGE_NOW=10780000
+       POWER_SUPPLY_CURRENT_NOW=13970000
+       POWER_SUPPLY_ENERGY_FULL_DESIGN=47510000
+       POWER_SUPPLY_ENERGY_FULL=27370000
+       POWER_SUPPLY_ENERGY_NOW=11810000
+       POWER_SUPPLY_MODEL_NAME=IBM-92P1060
+       POWER_SUPPLY_MANUFACTURER=Panasonic
+  On some systems POWER_SUPPLY_ENERGY_* is replaced by POWER_SUPPLY_CHARGE_*
+*/
+
+#define SYSFS_BATTERY_BASE_PATH "/sys/class/power_supply"
 #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery"
 #define APM_PATH "/proc/apm"
 #define MAX_BATTERY_COUNT 4
 
+static FILE *sysfs_bat_fp[MAX_BATTERY_COUNT];
 static FILE *acpi_bat_fp[MAX_BATTERY_COUNT];
 static FILE *apm_bat_fp[MAX_BATTERY_COUNT];
 
@@ -1308,6 +1334,8 @@
        static int idx, rep = 0, rep2 = 0;
        char acpi_path[128];
        snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
+       char sysfs_path[128];
+       snprintf(sysfs_path, 127, SYSFS_BATTERY_BASE_PATH "/%s/uevent", bat);
 
        init_batteries();
 
@@ -1322,12 +1350,116 @@
        memset (last_battery_str[idx], 0, sizeof (last_battery_str[idx]));
        memset (last_battery_time_str[idx], 0, sizeof 
(last_battery_time_str[idx]));
 
-       /* first try ACPI */
+       /* first try SYSFS if that fails try ACPI */
 
-       if (acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL)
+       if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && 
apm_bat_fp[idx] == NULL)
+               sysfs_bat_fp[idx] = open_file(sysfs_path, &rep);
+
+       if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && 
apm_bat_fp[idx] == NULL)
                acpi_bat_fp[idx] = open_file(acpi_path, &rep);
 
-       if (acpi_bat_fp[idx] != NULL) {
+       if (sysfs_bat_fp[idx] != NULL) {
+               /* SYSFS */
+               int present_rate = -1;
+               int remaining_capacity = -1;
+               char charging_state[64];
+               char present[4];
+
+               fseek(sysfs_bat_fp[idx], 0, SEEK_SET);
+
+               strcpy(charging_state, "Unknown");
+
+               while (!feof(sysfs_bat_fp[idx])) {
+                       char buf[256];
+                       if (fgets(buf, 256, sysfs_bat_fp[idx]) == NULL)
+                               break;
+
+                       /* let's just hope units are ok */
+                       if (strncmp (buf, "POWER_SUPPLY_PRESENT=1", 22) == 0)
+                               strcpy(present, "Yes");
+                       else if (strncmp (buf, "POWER_SUPPLY_PRESENT=0", 22) == 
0)
+                               strcpy(present, "No");
+                       else if (strncmp (buf, "POWER_SUPPLY_STATUS=", 20) == 0)
+                               sscanf(buf, "POWER_SUPPLY_STATUS=%63s", 
charging_state);
+                       /* present_rate is not the same as the
+                       current flowing now but it is the same value
+                       which was used in the past. so we continue
+                       the tradition! */
+                       else if (strncmp(buf, "POWER_SUPPLY_CURRENT_NOW=", 25) 
== 0)
+                               sscanf(buf, "POWER_SUPPLY_CURRENT_NOW=%d", 
&present_rate);
+                       else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) 
== 0)
+                               sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", 
&remaining_capacity);
+                       else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=", 25) 
== 0)
+                               sscanf(buf, "POWER_SUPPLY_ENERGY_FULL=%d", 
&acpi_last_full[idx]);
+                       else if (strncmp(buf, "POWER_SUPPLY_CHARGE_NOW=", 24) 
== 0)
+                               sscanf(buf, "POWER_SUPPLY_CHARGE_NOW=%d", 
&remaining_capacity);
+                       else if (strncmp(buf, "POWER_SUPPLY_CHARGE_FULL=", 25) 
== 0)
+                               sscanf(buf, "POWER_SUPPLY_CHARGE_FULL=%d", 
&acpi_last_full[idx]);
+               }
+
+               /* Hellf[i]re notes that remaining capacity can exceed 
acpi_last_full */
+               if (remaining_capacity > acpi_last_full[idx])
+                       acpi_last_full[idx] = remaining_capacity;  /* normalize 
to 100% */
+
+               /* not present */
+               if (strcmp(present, "No") == 0) {
+                       strncpy(last_battery_str[idx], "not present", 64);
+               }
+               /* charging */
+               else if (strcmp(charging_state, "Charging") == 0) {
+                       if (acpi_last_full[idx] != 0 && present_rate > 0) {
+                               /* e.g. charging 75% */
+                               snprintf(last_battery_str[idx], 
sizeof(last_battery_str[idx])-1, "Charging %i%%",
+                                       (int) (((float) remaining_capacity / 
acpi_last_full[idx]) * 100 ));
+                               /* e.g. 2h 37m */
+                               format_seconds(last_battery_time_str[idx], 
sizeof(last_battery_time_str[idx])-1,
+                                             (long) 
(((float)(acpi_last_full[idx] - remaining_capacity) / present_rate) * 3600));
+                       } else if (acpi_last_full[idx] != 0 && present_rate <= 
0) {
+                               snprintf(last_battery_str[idx], 
sizeof(last_battery_str[idx])-1, "Charging %d%%",
+                                       (int) (((float)remaining_capacity / 
acpi_last_full[idx]) * 100));
+                       } else {
+                               strncpy(last_battery_str[idx], "Charging", 
sizeof(last_battery_str[idx])-1);
+                       }
+               }
+               /* discharging */
+               else if (strncmp(charging_state, "Discharging", 64) == 0) {
+                       if (present_rate > 0) {
+                               /* e.g. discharging 35% */
+                               snprintf(last_battery_str[idx], 
sizeof(last_battery_str[idx])-1, "Discharging %i%%",
+                                       (int) (((float) remaining_capacity / 
acpi_last_full[idx]) * 100 ));
+                               /* e.g. 1h 12m */
+                               format_seconds(last_battery_time_str[idx], 
sizeof(last_battery_time_str[idx])-1,
+                                             (long) 
(((float)(acpi_last_full[idx] - remaining_capacity) / present_rate) * 3600));
+                       } else if (present_rate == 0) { /* Thanks to Nexox for 
this one */
+                               snprintf(last_battery_str[idx], 
sizeof(last_battery_str[idx])-1, "Full");
+                       } else {
+                               snprintf(last_battery_str[idx], 
sizeof(last_battery_str[idx])-1,
+                                       "Discharging %d%%",
+                                       (int) (((float)remaining_capacity / 
acpi_last_full[idx]) * 100));
+                       }
+               }
+               /* charged */
+               /* thanks to Lukas Zapletal <[EMAIL PROTECTED]> */
+               else if (strncmp(charging_state, "Charged", 64) == 0) {
+                               /* Below happens with the second battery on my 
X40,
+                                * when the second one is empty and the first 
one
+                                * being charged. */
+                               if (remaining_capacity == 0)
+                                       strcpy(last_battery_str[idx], "Empty");
+                               else
+                                       strcpy(last_battery_str[idx], 
"Charged");
+               }
+               /* unknown, probably full / AC */
+               else {
+                       if (acpi_last_full[idx] != 0
+                           && remaining_capacity != acpi_last_full[idx])
+                               snprintf(last_battery_str[idx], 64, "Unknown 
%d%%",
+                                       (int) (((float)remaining_capacity / 
acpi_last_full[idx]) * 100));
+                       else
+                               strncpy(last_battery_str[idx], "AC", 64);
+               }
+       } else if (acpi_bat_fp[idx] != NULL) {
+               /* ACPI */
                int present_rate = -1;
                int remaining_capacity = -1;
                char charging_state[64];
@@ -1491,6 +1623,8 @@
        int idx;
        char acpi_path[128];
        snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
+       char sysfs_path[128];
+       snprintf(sysfs_path, 127, SYSFS_BATTERY_BASE_PATH "/%s/uevent", bat);
 
        init_batteries();
 
@@ -1502,13 +1636,36 @@
        }
        last_battery_perct_time[idx] = current_update_time;
 
-       /* Only check for ACPI */
+       /* Only check for SYSFS or ACPI */
+
+       if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && 
apm_bat_fp[idx] == NULL)
+               sysfs_bat_fp[idx] = open_file(sysfs_path, &rep);
 
-       if (acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL)
+       if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && 
apm_bat_fp[idx] == NULL)
                acpi_bat_fp[idx] = open_file(acpi_path, &rep);
 
        int remaining_capacity = -1;
-       if (acpi_bat_fp[idx] != NULL) {
+
+       if (sysfs_bat_fp[idx] != NULL) {
+               /* SYSFS */
+               fseek(sysfs_bat_fp[idx], 0, SEEK_SET);
+
+               while (!feof(sysfs_bat_fp[idx])) {
+                       char buf[256];
+                       if (fgets(buf, 256, sysfs_bat_fp[idx]) == NULL)
+                               break;
+
+                       if (strncmp(buf, "POWER_SUPPLY_CHARGE_NOW=", 24) == 0)
+                               sscanf(buf, "POWER_SUPPLY_CHARGE_NOW=%d", 
&remaining_capacity);
+                       else if (strncmp(buf, "POWER_SUPPLY_CHARGE_FULL=",25) 
!= 0)
+                               sscanf(buf, "POWER_SUPPLY_CHARGE_FULL=%d", 
&acpi_last_full[idx]);
+                       else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) 
== 0)
+                               sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", 
&remaining_capacity);
+                       else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=",25) 
!= 0)
+                               sscanf(buf, "POWER_SUPPLY_ENERGY_FULL=%d", 
&acpi_last_full[idx]);
+               }
+       } else if (acpi_bat_fp[idx] != NULL) {
+               /* ACPI */
                /* read last full capacity if it's zero */
                if (acpi_design_capacity[idx] == 0) {
                        static int rep;

Attachment: signature.asc
Description: Digital signature

Reply via email to