From dd3b471f2d454328689583e3a1c1e85dff9b45e4 Mon Sep 17 00:00:00 2001 From: Brenden Matthews Date: Mon, 17 Mar 2008 22:27:20 +0000 Subject: [PATCH] * Applied 2 patches: 1) sysfs battery support (for Linux >=2.6.24) (thanks Kapil) 2) Improved audacious support patch (thanks Miroslav) git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky1@1009 7f574dfc-610e-0410-a909-a81674777703 --- AUTHORS | 7 ++- ChangeLog | 5 ++ src/audacious.c | 6 +- src/conky.c | 15 ----- src/linux.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 185 insertions(+), 29 deletions(-) diff --git a/AUTHORS b/AUTHORS index 2ab67bd..fc9499b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -146,7 +146,8 @@ J Kapil Hari Paranjape ibm_volume patch kFreeBSD support patch - realtime clock patck + realtime clock patch + sysfs battery patch Kevin Lyles add long options patch @@ -178,6 +179,9 @@ Lucas Brutschy Michal Januszewski hddtemp support +Miroslav Lichvar + move audacious thread init to update_audacious() patch + Moncelier Camille METAR patch @@ -201,6 +205,7 @@ Petr Holub Philip Kovacs tcp port monitor with hashing functionality + Audacious, Xmms, BMP, Infopipe stuff Various Xlib changes, e.g. own_window hints, etc. diff --git a/ChangeLog b/ChangeLog index c54a935..b6bd380 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ # $Id$ +2008-03-17 + * Applied 2 patches: + 1) sysfs battery support (for Linux >=2.6.24) (thanks Kapil) + 2) Improved audacious support patch (thanks Miroslav) + 2008-02-08 * Applied 2 patches: 1) Add diskio for individual devices diff --git a/src/audacious.c b/src/audacious.c index ed7e644..4f2cdfb 100644 --- a/src/audacious.c +++ b/src/audacious.c @@ -73,7 +73,11 @@ void update_audacious(void) * We merely copy the audacious_items array into the main thread's info * structure when the main thread's update cycle fires. */ if (!info.audacious.p_timed_thread) { - return; + if (create_audacious_thread() != 0) { + CRIT_ERR("unable to create audacious thread!"); + } + timed_thread_register(info.audacious.p_timed_thread, + &info.audacious.p_timed_thread); } timed_thread_lock(info.audacious.p_timed_thread); diff --git a/src/conky.c b/src/conky.c index 3fd05c8..da1e71c 100644 --- a/src/conky.c +++ b/src/conky.c @@ -7102,13 +7102,6 @@ void reload_config(void) #ifdef TCP_PORT_MONITOR info.p_tcp_port_monitor_collection = NULL; #endif -#ifdef AUDACIOUS - if (create_audacious_thread() != 0) { - CRIT_ERR("unable to create audacious thread!"); - } - timed_thread_register(info.audacious.p_timed_thread, - &info.audacious.p_timed_thread); -#endif extract_variable_text(text); free(text); text = NULL; @@ -8305,14 +8298,6 @@ int main(int argc, char **argv) ERR("error setting signal handler: %s", strerror(errno)); } -#ifdef AUDACIOUS - if (create_audacious_thread() != 0) { - CRIT_ERR("unable to create audacious thread!"); - } - timed_thread_register(info.audacious.p_timed_thread, - &info.audacious.p_timed_thread); -#endif - /* *************** * * MAIN CONKY LOOP * * *************** */ diff --git a/src/linux.c b/src/linux.c index a49e9bf..9dea1ef 100644 --- a/src/linux.c +++ b/src/linux.c @@ -1291,10 +1291,36 @@ present voltage: 16608 mV 2241<@jupet�kellari��> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori p��ll� mutta ilman verkkovirtaa */ +/* Kapil Hari Paranjape + 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]; @@ -1351,6 +1377,8 @@ void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item) 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(); @@ -1366,13 +1394,117 @@ void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item) 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 */ - - if (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) { + /* first try SYSFS if that fails try 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 (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 (sysfs_bat_fp[idx] != NULL) { + /* SYSFS */ + int present_rate = -1; + int remaining_capacity = -1; + char charging_state[64]; + char present[4]; + + 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]); + } + + fclose(sysfs_bat_fp[idx]); + sysfs_bat_fp[idx] = NULL; + + /* 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 */ + 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]; @@ -1543,6 +1675,8 @@ int get_battery_perct(const char *bat) 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(); @@ -1554,15 +1688,38 @@ int get_battery_perct(const char *bat) } 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 */ + 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]); + } + + fclose(sysfs_bat_fp[idx]); + sysfs_bat_fp[idx] = NULL; + + } 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; @@ -1579,7 +1736,7 @@ int get_battery_perct(const char *bat) break; } if (sscanf(b, "last full capacity: %d", - &acpi_design_capacity[idx]) != 0) { + &acpi_design_capacity[idx]) != 0) { break; } } -- 1.7.9.5