From 16b851a43cf20ee2375584c3d0036c30cd407574 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Mon, 3 Mar 2008 09:48:37 +0000 Subject: [PATCH] move battery fetching/polling of info to its own sub process, pipe of stdout to read like tempget. this means e cant hang hen polling - much better for the mainloop. also clean up the code a lot. all battery specific "driver" code is now in batget - this means it much nicer to later add hal battery info fetching as that is also a remote service (and just not execute batget). i also fixed up (in theory) the new 2.6.24+ /sys/class/power_supply parsing to i think work better in more situations. i'm testing on a device i have that does it - let me know if its wrong... SVN revision: 33903 --- src/modules/battery/Makefile.am | 13 + src/modules/battery/batget.c | 1433 ++++++++++++++++++++++++++ src/modules/battery/e_mod_main.c | 1635 +++--------------------------- src/modules/battery/e_mod_main.h | 41 +- 4 files changed, 1607 insertions(+), 1515 deletions(-) create mode 100644 src/modules/battery/batget.c diff --git a/src/modules/battery/Makefile.am b/src/modules/battery/Makefile.am index c278639d1..fdfa2f7cc 100644 --- a/src/modules/battery/Makefile.am +++ b/src/modules/battery/Makefile.am @@ -26,5 +26,18 @@ module_la_LIBADD = @e_libs@ @cf_libs@ @dlopen_libs@ module_la_LDFLAGS = -module -avoid-version module_la_DEPENDENCIES = $(top_builddir)/config.h +batgetdir = $(pkgdir) +batget_DATA = \ +batget$(EXEEXT) + +x_mode = a=rx,u+x +install-data-hook: + @chmod $(x_mode) $(DESTDIR)$(batgetdir)/batget$(EXEEXT) || true + +noinst_PROGRAMS = batget +batget_SOURCES = batget.c +batget_LDFLAGS = @BATTERY_LIBS@ + + uninstall: rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE) diff --git a/src/modules/battery/batget.c b/src/modules/battery/batget.c new file mode 100644 index 000000000..0847b01dd --- /dev/null +++ b/src/modules/battery/batget.c @@ -0,0 +1,1433 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "e.h" + +#ifdef __FreeBSD__ +# include +# include +# include +# ifdef __i386__ +# include +# endif +# include +#endif +#ifdef HAVE_CFBASE_H +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include +#include + +/* supported batery system schemes - irrespective of OS */ +#define CHECK_NONE 0 +#define CHECK_ACPI 1 +#define CHECK_APM 2 +#define CHECK_PMU 3 +#define CHECK_SYS_CLASS_POWER_SUPPLY 4 + +static void init(void); +static int check(void); +static int poll_cb(void *data); + +static int poll_interval = 512; +static Ecore_Poller *poller = NULL; + +static int mode = CHECK_NONE; + +static int time_left = -2; +static int battery_full = -2; +static int have_battery = -2; +static int have_power = -2; + + + +/* UTILS */ +static int +int_file_get(const char *file) +{ + FILE *f; + int val = -1; + char buf[256]; + + f = fopen(file, "r"); + if (f) + { + fgets(buf, sizeof(buf), f); + val = atoi(buf); + fclose(f); + } + return val; +} + +static char * +str_file_get(const char *file) +{ + FILE *f; + char *val = NULL; + char buf[4096]; + int len; + + f = fopen(file, "r"); + if (f) + { + fgets(buf, sizeof(buf), f); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); + if (len > 0) buf[len - 1] = 0; + val = strdup(buf); + fclose(f); + } + return val; +} + +static int +int_get(char *buf) +{ + char *p, *q; + + p = strchr(buf, ':'); + if (!p) return 0; + p++; + while (*p == ' ') p++; + q = p; + while ((*q != ' ') && (*q != '\n')) q++; + if (q) *q = 0; + return atoi(p); +} + +static char * +str_get(char *buf) +{ + char *p, *q; + + p = strchr(buf, ':'); + if (!p) return NULL; + p++; + while (*p == ' ') p++; + q = p; + while ((*q) && (*q != ' ') && (*q != '\n')) q++; + if (q) *q = 0; + return strdup(p); +} + +static int +axtoi(char *arg) +{ + int n, val, pwr=1, m, rc = 0; + char hex[9], c; + + for (n = 0, m = 0; n < strlen(arg); n++) + { + if (arg[n] != ' ') + { + hex[m++] = c = toupper(arg[n]); + if ((m == sizeof(hex)) || (c < '0') || (c > 'F')) + return 0; /* overflow or invalid */ + } + } + hex[m] = 0; /* terminate string */ + + for (n = 0; n < m; n++) + { + c = hex[m-n-1]; + if ((c >= 'A') && (c <= 'F')) + val = c -'A' + 10; + else + val = c - '0'; + rc = rc + val * pwr; + pwr *= 16; + } + return rc; +} + + + + + +#ifdef __FreeBSD__ + +#define BATTERY_STATE_NONE 0 +#define BATTERY_STATE_DISCHARGING 1 +#define BATTERY_STATE_CHARGING 2 +#define BATTERY_STATE_REMOVED 7 + +/***---***/ +static void +bsd_acpi_init(void) +{ + /* nothing to do */ +} + +static void +bsd_acpi_check(void) +{ + int bat_val = 0; + int mib_state[4]; + int mib_life[4]; + int mib_time[4]; + int mib_units[4]; + size_t len; + int state = 0; + int level = 0; + int time_min = 0; + int life = 0; + int batteries = 0; + + time_left = -1; + battery_full = -1; + have_battery = 0; + have_power = 0; + + /* Read some information on first run. */ + len = 4; + sysctlnametomib("hw.acpi.battery.state", mib_state, &len); + len = sizeof(state); + if (sysctl(mib_state, 4, &state, &len, NULL, 0) == -1) + /* ERROR */ + state = -1; + + len = 4; + sysctlnametomib("hw.acpi.battery.life", mib_life, &len); + len = sizeof(life); + if (sysctl(mib_life, 4, &life, &len, NULL, 0) == -1) + /* ERROR */ + level = -1; + bat_val = life; + + len = 4; + sysctlnametomib("hw.acpi.battery.time", mib_time, &len); + len = sizeof(time); + if (sysctl(mib_time, 4, &time_min, &len, NULL, 0) == -1) + /* ERROR */ + time_min = -1; + + len = 4; + sysctlnametomib("hw.acpi.battery.units", mib_units, &len); + len = sizeof(batteries); + if (sysctl(mib_time, 4, &batteries, &len, NULL, 0) == -1) + /* ERROR */ + batteries = 1; + + if (time_min >= 0) time_left = time_min * 60; + + if (batteries == 1) /* hw.acpi.battery.units = 1 means NO BATTS */ + time_left = -1; + else if ((state == BATTERY_STATE_CHARGING) || + (state == BATTERY_STATE_DISCHARGING)) + { + have_battery = 1; + if (state == BATTERY_STATE_CHARGING) have_power = 1; + else if (state == BATTERY_STATE_DISCHARGING) have_power = 0; + if (level == -1) time_left = -1; + else if (time_min == -1) + { + time_left = -1; + battery_full = bat_val; + } + else battery_full = bat_val; + } + else + { + have_battery = 1; + battery_full = 100; + time_left = -1; + have_power = 1; + } +} + +/***---***/ +static void +bsd_apm_init(void) +{ + /* nothing to do */ +} + +static void +bsd_apm_check(void) +{ + int ac_stat, bat_stat, bat_val, time_val; + char buf[4096]; + int hours, minutes; + int apm_fd = -1; + struct apm_info info; + + time_left = -1; + battery_full = -1; + have_battery = 0; + have_power = 0; + + apm_fd = open("/dev/apm", O_RDONLY); + if ((apm_fd != -1) && (ioctl(apm_fd, APMIO_GETINFO, &info) != -1)) + { + /* set values */ + ac_stat = info.ai_acline; + bat_stat = info.ai_batt_stat; + bat_val = info.ai_batt_life; + time_val = info.ai_batt_time; + } + else return; + + if (info.ai_batteries == 1) /* ai_batteries == 1 means NO battery, + * ai_batteries == 2 means 1 battery */ + { + have_power = 1; + return; + } + + if (ac_stat) /* Wallpowered */ + { + have_power= 1; + have_battery = 1; + switch (bat_stat) /* On FreeBSD the time_val is -1 when AC ist plugged + * in. This means we don't know how long the battery + * will recharge */ + { + case 0: + battery_full = 100; + break; + case 1: + battery_full = 50; + break; + case 2: + battery_full = 25; + break; + case 3: + battery_full = 100; + break; + } + } + else /* Running on battery */ + { + have_battery = 1; + battery_full = bat_val; + time_left = time_val; + } +} + +#elif defined(HAVE_CFBASE_H) /* OS X */ +/***---***/ +static void darwin_init(void); +static void darwin_check(void); + +static void +darwin_init(void) +{ + /* nothing to do */ +} + +static void +darwin_check(void) +{ + const void *values; + int device_num, device_count; + int currentval = 0, maxval = 0; + char buf[4096]; + CFTypeRef blob; + CFArrayRef sources; + CFDictionaryRef device_dict; + + time_left = -1; + battery_full = -1; + have_battery = 0; + have_power = 0; + + /* Retrieve the power source data and the array of sources. */ + blob = IOPSCopyPowerSourcesInfo(); + sources = IOPSCopyPowerSourcesList(blob); + device_count = CFArrayGetCount(sources); + for (device_num = 0; device_num < device_count; device_num++) + { + CFTypeRef ps; + + /* Retrieve a dictionary of values for this device and the count of keys in the dictionary. */ + ps = CFArrayGetValueAtIndex(sources, device_num); + device_dict = IOPSGetPowerSourceDescription(blob, ps); + /* Retrieve the charging key and save the present charging value if one exists. */ + if (CFDictionaryGetValueIfPresent(device_dict, + CFSTR(kIOPSIsChargingKey), &values)) + { + have_battery = 1; + if (CFBooleanGetValue(values) > 0) have_power = 1; + break; + } + + } + + if (!have_battery) + { + CFRelease(sources); + CFRelease(blob); + have_power = 1; + return; + } + + /* Retrieve the current capacity key. */ + values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey)); + CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); + /* Retrieve the max capacity key. */ + values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSMaxCapacityKey)); + CFNumberGetValue(values, kCFNumberSInt32Type, &maxval); + /* Calculate the percentage charged. */ + battery_full = (currentval * 100) / maxval; + + /* Retrieve the remaining battery power or time until charged in minutes. */ + if (!have_power) + { + values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey)); + CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); + time_left = currentval * 60; + } + else + { + values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey)); + CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); + time_left = currentval * 60; + } + CFRelease(sources); + CFRelease(blob); +} +#else + + + + + + + + +/***---***/ +/* new linux power class api to get power info - brand new and this code + * may have bugs, but it is a good attempt to get it right */ +static int linux_sys_class_power_supply_cb_event_fd_active(void *data, Ecore_Fd_Handler *fd_handler); +static void linux_sys_class_power_supply_init(void); +static void linux_sys_class_power_supply_check(void); +typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent; + +struct _Sys_Class_Power_Supply_Uevent +{ + int fd; + Ecore_Fd_Handler *fd_handler; +}; + +static Ecore_List *events = NULL; +static Ecore_Timer *sys_class_delay_check = NULL; + +static int +linux_sys_class_powe_supply_cb_delay_check(void *data) +{ + linux_sys_class_power_supply_init(); + poll_cb(NULL); + sys_class_delay_check = NULL; + return 0; +} + +static int +linux_sys_class_power_supply_cb_event_fd_active(void *data, Ecore_Fd_Handler *fd_handler) +{ + Sys_Class_Power_Supply_Uevent *sysev; + + sysev = data; + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) + { + int lost = 0; + for (;;) + { + char buf[1024]; + int num; + + if ((num = read(sysev->fd, buf, sizeof(buf))) < 1) + { + lost = ((errno == EIO) || + (errno == EBADF) || + (errno == EPIPE) || + (errno == EINVAL) || + (errno == ENOSPC) || + (num == 0)); + } + } + if (lost) + { + ecore_list_goto(events, sysev); + ecore_list_remove(events); + ecore_main_fd_handler_del(sysev->fd_handler); + close(sysev->fd); + free(sysev); + } + else + { + if (sys_class_delay_check) ecore_timer_del(sys_class_delay_check); + sys_class_delay_check = ecore_timer_add(0.2, linux_sys_class_powe_supply_cb_delay_check, NULL); + } + } + return 1; +} + +static void +linux_sys_class_power_supply_init(void) +{ + Ecore_List *bats; + char *name; + char buf[4096]; + + if (events) + { + while (!ecore_list_empty_is(events)) + { + Sys_Class_Power_Supply_Uevent *sysev; + + ecore_list_first_goto(events); + sysev = ecore_list_remove(events); + ecore_main_fd_handler_del(sysev->fd_handler); + close(sysev->fd); + free(sysev); + } + ecore_list_destroy(events); + events = NULL; + } + bats = ecore_file_ls("/sys/class/power_supply/"); + if (bats) + { + events = ecore_list_new(); + while ((name = ecore_list_next(bats))) + { + int fd; + + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/uevent", name); + fd = open(buf, O_RDONLY); + if (fd >= 0) + { + Sys_Class_Power_Supply_Uevent *sysev; + + sysev = E_NEW(Sys_Class_Power_Supply_Uevent, 1); + sysev->fd = fd; + sysev->fd_handler = ecore_main_fd_handler_add(sysev->fd, + ECORE_FD_READ, + linux_sys_class_power_supply_cb_event_fd_active, + NULL, + NULL, NULL); + ecore_list_append(events, sysev); + } + } + ecore_list_destroy(bats); + } +} + +static void +linux_sys_class_power_supply_check(void) +{ + Ecore_List *bats; + char *name; + char buf[4096]; + + battery_full = -1; + time_left = -1; + have_battery = 0; + have_power = 0; + + bats = ecore_file_ls("/sys/class/power_supply/"); + if (bats) + { + int total_pwr_now = 0; + int total_pwr_max = 0; + + time_left = 0; + + while ((name = ecore_list_next(bats))) + { + char *tmp; + int present = 0; + int charging = -1; + int capacity = -1; + int current_avg = -1; + int current_now = -1; + int time_to_full = -1; + int time_to_empty = -1; + int full = -1; + int charge_now = -1; + int charge_empty = -1; + int charge_full = -1; + int charge_empty_design = -1; + int charge_full_design = -1; + int energy_now = -1; + int energy_empty = -1; + int energy_full = -1; + int energy_empty_design = -1; + int energy_full_design = -1; + int voltage_now = -1; + int voltage_empty = -1; + int voltage_full = -1; + int voltage_empty_design = -1; + int voltage_full_design = -1; + int pwr_now = -1; + int pwr_empty = -1; + int pwr_full = -1; + int pwr; + + if (strncasecmp("bat", name, 3)) continue; + + /* FIXME: this is not hyper-efficient. we try and find all sorts + * of entries. they may or may not exist. we don't remember that + * and should figure this out during init. i have tried to make + * this handle as many cases as possible */ + + /* fetch more generic info */ + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/present", name); + present = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/capacity", name); + capacity = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_avg", name); + current_avg = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_now", name); + current_now = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/status", name); + tmp = str_file_get(buf); + if (tmp) + { + if (!strncasecmp("discharging", tmp, 11)) charging = 0; + else if (!strncasecmp("charging", tmp, 8)) charging = 1; + else if (!strncasecmp("full", tmp, 4)) + { + full = 1; + charging = 0; + } + free(tmp); + } + /* some batteries cna/will/want to predict how long they will + * last. if so - take what the battery says. too bad if it's + * wrong. that's a buggy battery or driver */ + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/time_to_full_now", name); + time_to_full = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/time_to_empty_now", name); + time_to_empty = int_file_get(buf); + + /* now get charge, energy and voltage. take the one that provides + * the best info (charge first, then energy, then voltage */ + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_now", name); + charge_now = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full", name); + charge_full = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_empty", name); + charge_empty = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full_design", name); + charge_full_design = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_empty_design", name); + charge_empty_design = int_file_get(buf); + + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_now", name); + energy_now = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full", name); + energy_full = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_empty", name); + energy_empty = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_full_design", name); + energy_full_design = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/energy_empty_design", name); + energy_empty_design = int_file_get(buf); + + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_now", name); + voltage_now = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full", name); + voltage_full = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_empty", name); + voltage_empty = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_full_design", name); + voltage_full_design = int_file_get(buf); + snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/voltage_empty_design", name); + voltage_empty_design = int_file_get(buf); + + /* now the logic of figuring this out */ + if (charge_empty < 0) charge_empty = charge_empty_design; + if (charge_full < 0) charge_full = charge_full_design; + if (energy_empty < 0) energy_empty = energy_empty_design; + if (energy_full < 0) energy_full = energy_full_design; + if (voltage_empty < 0) voltage_empty = voltage_empty_design; + if (voltage_full < 0) voltage_full = voltage_full_design; + + if (charge_full >= 0) + { + pwr_now = charge_now; + pwr_empty = charge_empty; + pwr_full = charge_full; + } + else if (energy_full >= 0) + { + pwr_now = energy_now; + pwr_empty = energy_empty; + pwr_full = energy_full; + } + else if (voltage_full >= 0) + { + pwr_now = voltage_now; + pwr_empty = voltage_empty; + pwr_full = voltage_full; + } + + if (pwr_empty < 0) pwr_empty = 0; + if (full) + { + pwr_now = pwr_full; + } + else + { + if (pwr_now < 0) + pwr_now = ((capacity * (pwr_full - pwr_empty)) / 100) + pwr_empty; + } + + if (present) have_battery = 1; + if (current_avg < 0) current_avg = current_now; + if (charging) + { + have_power = 1; + if (time_to_full >= 0) + { + if (time_to_full > time_left) + time_left = time_to_full; + } + else + { + if (current_avg == 0) + time_left = 0; + else if (current_avg < 0) + time_left = -1; + else + { + pwr = ((pwr_full - pwr_now) * 3600) / current_avg; + if (pwr > time_left) + time_left = pwr; + } + } + } + else + { + if (time_to_empty >= 0) + { + time_left += time_to_empty; + } + else + { + if (time_to_full < 0) + { + if (current_avg > 0) + { + pwr = ((pwr_now - pwr_empty) * 3600) / current_avg; + time_left += pwr; + } + } + } + } + + total_pwr_now += pwr_now - pwr_empty; + total_pwr_max += pwr_full - pwr_empty; + } + if (total_pwr_max > 0) + battery_full = (total_pwr_now * 100) / total_pwr_max; + ecore_list_destroy(bats); + } +} + + + + + + + + + +/***---***/ +/* "here and now" ACPI based power checking. is there for linux and most + * modern laptops. as of linux 2.6.24 it is replaced with + * linux_sys_class_power_supply_init/check() though as this is the new + * power class api to poll for power stuff + */ +static int linux_acpi_cb_acpid_add(void *data, int type, void *event); +static int linux_acpi_cb_acpid_del(void *data, int type, void *event); +static int linux_acpi_cb_acpid_data(void *data, int type, void *event); +static void linux_acpi_init(void); +static void linux_acpi_check(void); + +static int acpi_max_full = -1; +static int acpi_max_design = -1; +static Ecore_Con_Server *acpid = NULL; +static Ecore_Event_Handler *acpid_handler_add = NULL; +static Ecore_Event_Handler *acpid_handler_del = NULL; +static Ecore_Event_Handler *acpid_handler_data = NULL; +static Ecore_Timer *delay_check = NULL; +static int event_fd = -1; +static Ecore_Fd_Handler *event_fd_handler = NULL; + +static int +linux_acpi_cb_delay_check(void *data) +{ + linux_acpi_init(); + poll_cb(NULL); + delay_check = NULL; + return 0; +} + +static int +linux_acpi_cb_acpid_add(void *data, int type, void *event) +{ + return 1; +} + +static int +linux_acpi_cb_acpid_del(void *data, int type, void *event) +{ + ecore_con_server_del(acpid); + acpid = NULL; + if (acpid_handler_add) ecore_event_handler_del(acpid_handler_add); + acpid_handler_add = NULL; + if (acpid_handler_del) ecore_event_handler_del(acpid_handler_del); + acpid_handler_del = NULL; + if (acpid_handler_data) ecore_event_handler_del(acpid_handler_data); + acpid_handler_data = NULL; + return 1; +} + +static int +linux_acpi_cb_acpid_data(void *data, int type, void *event) +{ + Ecore_Con_Event_Server_Data *ev; + + ev = event; + if (delay_check) ecore_timer_del(delay_check); + delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL); + return 1; +} + +static int +linux_acpi_cb_event_fd_active(void *data, Ecore_Fd_Handler *fd_handler) +{ + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) + { + int lost = 0; + for (;;) + { + char buf[1024]; + int num; + + if ((num = read(event_fd, buf, sizeof(buf))) < 1) + { + lost = ((errno == EIO) || + (errno == EBADF) || + (errno == EPIPE) || + (errno == EINVAL) || + (errno == ENOSPC) || + (num == 0)); + } + } + if (lost) + { + ecore_main_fd_handler_del(event_fd_handler); + event_fd_handler = NULL; + close(event_fd); + event_fd = -1; + } + else + { + if (delay_check) ecore_timer_del(delay_check); + delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL); + } + } + return 1; +} + +static void +linux_acpi_init(void) +{ + Ecore_List *powers; + Ecore_List *bats; + + bats = ecore_file_ls("/proc/acpi/battery"); + if (bats) + { + char *name; + + have_power = 0; + powers = ecore_file_ls("/proc/acpi/ac_adapter"); + if (powers) + { + char *name; + while ((name = ecore_list_next(powers))) + { + char buf[4096]; + FILE *f; + + snprintf(buf, sizeof(buf), "/proc/acpi/ac_adapter/%s/state", name); + f = fopen(buf, "r"); + if (f) + { + char *tmp; + + /* state */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (!strcmp(tmp, "on-line")) have_power = 1; + free(tmp); + } + } + } + ecore_list_destroy(powers); + } + + have_battery = 0; + acpi_max_full = 0; + acpi_max_design = 0; + while ((name = ecore_list_next(bats))) + { + char buf[4096]; + FILE *f; + + snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/info", name); + f = fopen(buf, "r"); + if (f) + { + char *tmp; + + /* present */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (!strcmp(tmp, "yes")) have_battery = 1; + free(tmp); + } + /* design cap */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (strcmp(tmp, "unknown")) acpi_max_design += atoi(tmp); + free(tmp); + } + /* last full cap */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (strcmp(tmp, "unknown")) acpi_max_full += atoi(tmp); + free(tmp); + } + fclose(f); + } + } + ecore_list_destroy(bats); + } + if (!acpid) + { + acpid = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM, + "/var/run/acpid.socket", -1, NULL); + if (acpid) + { + acpid_handler_add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, + linux_acpi_cb_acpid_add, NULL); + acpid_handler_del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, + linux_acpi_cb_acpid_del, NULL); + acpid_handler_data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, + linux_acpi_cb_acpid_data, NULL); + } + else + { + if (event_fd < 0) + { + event_fd = open("/proc/acpi/event", O_RDONLY); + if (event_fd >= 0) + event_fd_handler = ecore_main_fd_handler_add(event_fd, + ECORE_FD_READ, + linux_acpi_cb_event_fd_active, + NULL, + NULL, NULL); + } + } + } +} + +static void +linux_acpi_check(void) +{ + Ecore_List *bats; + + battery_full = -1; + time_left = -1; + have_battery = 0; + have_power = 0; + + bats = ecore_file_ls("/proc/acpi/battery"); + if (bats) + { + char *name; + int rate = 0; + int capacity = 0; + + while ((name = ecore_list_next(bats))) + { + char buf[4096]; + FILE *f; + + snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name); + f = fopen(buf, "r"); + if (f) + { + char *tmp; + + /* present */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (!strcmp(tmp, "yes")) have_battery = 1; + free(tmp); + } + /* capacity state: ok/? */ + fgets(buf, sizeof(buf), f); + /* charging state: charging/? */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (have_power == 0) + { + if (!strcmp(tmp, "charging")) have_power = 1; + } + free(tmp); + } + /* present rate: unknown/NNN */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (strcmp(tmp, "unknown")) rate += atoi(tmp); + free(tmp); + } + /* remaining capacity: NNN */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + tmp = str_get(buf); + if (tmp) + { + if (strcmp(tmp, "unknown")) capacity += atoi(tmp); + free(tmp); + } + fclose(f); + } + } + ecore_list_destroy(bats); + if (acpi_max_full > 0) + battery_full = 100 * capacity / acpi_max_full; + else if (acpi_max_design > 0) + battery_full = 100 * capacity / acpi_max_design; + else + battery_full = -1; + if (rate <= 0) time_left = -1; + else + { + if (have_power) + time_left = (3600 * (acpi_max_full - capacity)) / rate; + else + time_left = (3600 * capacity) / rate; + } + } +} + + + + + + + + + + + + +/***---***/ +/* old school apm support - very old laptops and some devices support this. + * this is here for legacy support and i wouldn't suggest spending any + * effort on it as it is complete below as best i know, but could have missed + * one or 2 things, but not worth fixing */ +static void linux_apm_init(void); +static void linux_apm_check(void); + +static void +linux_apm_init(void) +{ + /* nothing to do */ +} + +static void +linux_apm_check(void) +{ + FILE *f; + char s[256], s1[32], s2[32], s3[32], buf[4096]; + int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val; + int hours, minutes; + + battery_full = -1; + time_left = -1; + have_battery = 0; + have_power = 0; + + f = fopen("/proc/apm", "r"); + if (!f) return; + + fgets(s, sizeof(s), f); s[sizeof(s) - 1] = 0; + if (sscanf(s, "%*s %*s %x %x %x %x %s %s %s", + &apm_flags, &ac_stat, &bat_stat, &bat_flags, s1, s2, s3) != 7) + { + fclose(f); + return; + } + s1[strlen(s1) - 1] = 0; + bat_val = atoi(s1); + if (!strcmp(s3, "sec")) time_val = atoi(s2); + else if (!strcmp(s3, "min")) time_val = atoi(s2) * 60; + fclose(f); + + if ((bat_flags != 0xff) && (bat_flags & 0x80)) + { + have_battery = 0; + have_power = 0; + battery_full = 100; + time_left = 0; + return; + } + + if (bat_val >= 0) + { + have_battery = 1; + have_power = ac_stat; + battery_full = bat_val; + if (battery_full > 100) battery_full = 100; + if (ac_stat == 1) time_left = -1; + else time_left = time_val; + } + else + { + switch (bat_stat) + { + case 0: /* high */ + have_battery = 1; + have_power = ac_stat; + battery_full = 100; + time_left = -1; + break; + case 1: /* medium */ + have_battery = 1; + have_power = ac_stat; + battery_full = 50; + time_left = -1; + break; + case 2: /* low */ + have_battery = 1; + have_power = ac_stat; + battery_full = 25; + time_left = -1; + break; + case 3: /* charging */ + have_battery = 1; + have_power = ac_stat; + battery_full = 100; + time_left = -1; + break; + } + } +} + + + + + + + + + +/***---***/ +/* for older mac powerbooks. legacy as well like linux_apm_init/check. leave + * it alone unless you have to touch it */ +static void linux_pmu_init(void); +static void linux_pmu_check(void); + +static void +linux_pmu_init(void) +{ + /* nothing to do */ +} + +static void +linux_pmu_check(void) +{ + FILE *f; + char buf[4096]; + Ecore_List *bats; + char *name; + int ac = 0; + int flags = 0; + int charge = 0; + int max_charge = 0; + int current = 0; + int timeleft = 0; + int voltage = 0; + int seconds = 0; + int curcharge = 0; + int curmax = 0; + + f = fopen("/proc/pmu/info", "r"); + if (f) + { + /* Skip driver */ + fgets(buf, sizeof(buf), f); + /* Skip firmware */ + fgets(buf, sizeof(buf), f); + /* Read ac */ + fgets(buf, sizeof(buf), f); buf[sizeof(buf) - 1] = 0; + ac = int_get(buf); + fclose(f); + } + bats = ecore_file_ls("/proc/pmu"); + if (bats) + { + have_battery = 1; + have_power = ac; + while ((name = ecore_list_next(bats))) + { + if (strncmp(name, "battery", 7)) continue; + snprintf(buf, sizeof(buf), "/proc/pmu/%s", name); + f = fopen(buf, "r"); + if (f) + { + int timeleft = 0; + int current = 0; + + while (fgets(buf,sizeof (buf), f)) + { + char *token; + + if ((token = strtok(buf, ":"))) + { + if (!strncmp("flags", token, 5)) + flags = axtoi(strtok (0, ": ")); + else if (!strncmp("charge", token, 6)) + charge = atoi(strtok(0, ": ")); + else if (!strncmp("max_charge", token, 9)) + max_charge = atoi(strtok(0, ": ")); + else if (!strncmp("current", token, 7)) + current = atoi(strtok(0, ": ")); + else if (!strncmp("time rem", token, 8)) + timeleft = atoi(strtok(0, ": ")); + else if (!strncmp("voltage", token, 7)) + voltage = atoi(strtok(0, ": ")); + else + strtok(0, ": "); + } + } + curmax += max_charge; + curcharge += charge; + fclose(f); + if (!current) + { + /* Neither charging nor discharging */ + } + else if (!ac) + { + /* When on dc, we are discharging */ + seconds += timeleft; + } + else + { + /* Charging - works in paralell */ + seconds = MAX(timeleft, seconds); + } + } + } + ecore_list_destroy(bats); + if (max_charge > 0) battery_full = (charge * 100) / max_charge; + else battery_full = 0; + time_left = seconds; + } + else + { + have_power = ac; + have_battery = 0; + battery_full = -1; + time_left = -1; + } +} +#endif + + + + + + + + + + + + + + + + + + + +static void +init(void) +{ +#ifdef __FreeBSD__ + int acline; + size_t len; + + len = sizeof(acline); + if (!sysctlbyname("hw.acpi.acline", &acline, &len, NULL, 0)) + { + int acline_mib[3] = {-1}; + + len = 3; + if (!sysctlnametomib("hw.acpi.acline", acline_mib, &len)) + { + mode = CHECK_ACPI; + bsd_acpi_init(); + } + } + else + { + if (ecore_file_exists("/dev/apm")) + { + mode = CHECK_APM; + bsd_apm_init(); + } + } +#elif defined(HAVE_CFBASE_H) /* OS X */ + darwin_init(); +#else + if (ecore_file_is_dir("/sys/class/power_supply")) /* >= 2.6.24 */ + { + mode = CHECK_SYS_CLASS_POWER_SUPPLY; + linux_sys_class_power_supply_init(); + } + else if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */ + { + mode = CHECK_ACPI; + linux_acpi_init(); + } + else if (ecore_file_exists("/proc/apm")) + { + mode = CHECK_APM; + linux_apm_init(); + } + else if (ecore_file_is_dir("/proc/pmu")) + { + mode = CHECK_PMU; + linux_pmu_init(); + } +#endif +} + +static int +poll_cb(void *data) +{ + int ptime_left; + int pbattery_full; + int phave_battery; + int phave_power; + + ptime_left = time_left; + pbattery_full = battery_full; + phave_battery = have_battery; + phave_power = have_power; + +#ifdef __FreeBSD__ + switch (mode) + { + case CHECK_ACPI: + bsd_acpi_check(); + break; + case CHECK_APM: + bsd_apm_check(); + break; + default: + battery_full = -1; + time_left = -1; + have_battery = 0; + have_power = 0; + break; + } +#elif defined(HAVE_CFBASE_H) /* OS X */ + darwin_check(); + break; +#else + switch (mode) + { + case CHECK_ACPI: + linux_acpi_check(); + break; + case CHECK_APM: + linux_apm_check(); + break; + case CHECK_PMU: + linux_pmu_check(); + break; + case CHECK_SYS_CLASS_POWER_SUPPLY: + linux_sys_class_power_supply_check(); + break; + default: + battery_full = -1; + time_left = -1; + have_battery = 0; + have_power = 0; + break; + } +#endif + if ((ptime_left != time_left) || + (pbattery_full != battery_full) || + (phave_battery != have_battery) || + (phave_power != have_power)) + { + if ((time_left < 0) && + ((have_battery) && (battery_full < 0))) + printf("ERROR\n"); + else + printf("%i %i %i %i\n", + battery_full, time_left, have_battery, have_power); + fflush(stdout); + } + return 1; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) + { + printf("ARGS INCORRECT!\n"); + return 0; + } + poll_interval = atoi(argv[1]); + + ecore_init(); + ecore_file_init(); + ecore_con_init(); + + init(); + poller = ecore_poller_add(ECORE_POLLER_CORE, poll_interval, poll_cb, NULL); + poll_cb(NULL); + + ecore_main_loop_begin(); + + ecore_con_shutdown(); + ecore_file_shutdown(); + ecore_shutdown(); + + return 0; +} diff --git a/src/modules/battery/e_mod_main.c b/src/modules/battery/e_mod_main.c index 71465fd8b..74410bfe1 100644 --- a/src/modules/battery/e_mod_main.c +++ b/src/modules/battery/e_mod_main.c @@ -4,25 +4,6 @@ #include "e.h" #include "e_mod_main.h" -#ifdef __FreeBSD__ -# include -# include -# include -# ifdef __i386__ -# include -# endif -# include -#endif -#ifdef HAVE_CFBASE_H -#include -#include -#include -#include -#include -#include -#include -#endif - /***************************************************************************/ /**/ /* gadcon requirements */ @@ -57,23 +38,11 @@ struct _Instance Evas_Object *o_battery; }; +static int _battery_cb_exe_data(void *data, int type, void *event); +static int _battery_cb_exe_del(void *data, int type, void *event); static void _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _menu_cb_post(void *data, E_Menu *m); -static Status *_battery_linux_acpi_check(void); -static Status *_battery_linux_apm_check(void); -static Status *_battery_linux_powerbook_check(void); -static Status *_battery_linux_sys_acpi_check(void); -#ifdef __FreeBSD__ -static Status *_battery_bsd_acpi_check(void); -static Status *_battery_bsd_apm_check(void); -#endif -#ifdef HAVE_CFBASE_H -static Status *_battery_darwin_check(void); -#endif static void _battery_face_level_set(Instance *inst, double level); -static int _battery_int_get(char *buf); -static char *_battery_string_get(char *buf); -static int _battery_cb_check(void *data); static void _battery_face_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi); static E_Config_DD *conf_edd = NULL; @@ -102,12 +71,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _button_cb_mouse_down, inst); battery_config->instances = evas_list_append(battery_config->instances, inst); - battery_config->battery_check_mode = CHECK_NONE; - battery_config->battery_prev_level = -1; - battery_config->battery_prev_drain = 1; - battery_config->battery_prev_ac = -1; - battery_config->battery_prev_battery = -1; - _battery_cb_check(NULL); return gcc; } @@ -206,1402 +169,6 @@ _menu_cb_post(void *data, E_Menu *m) battery_config->menu = NULL; } -static int -_battery_cb_check(void *data) -{ - Status *ret = NULL; - Evas_List *l; -#ifdef __FreeBSD__ - int acline; - size_t len; - int apm_fd = -1; - int acline_mib[3] = {-1}; -#endif - -#ifdef __FreeBSD__ - if (battery_config->battery_check_mode == 0) - { - len = sizeof(acline); - if (sysctlbyname("hw.acpi.acline", &acline, &len, NULL, 0) == 0) - { - len = 3; - if (sysctlnametomib("hw.acpi.acline", acline_mib, &len) == 0) - battery_config->battery_check_mode = CHECK_ACPI; - } - else - { - apm_fd = open("/dev/apm", O_RDONLY); - if (apm_fd != -1) - battery_config->battery_check_mode = CHECK_APM; - } - } - switch (battery_config->battery_check_mode) - { - case CHECK_ACPI: - ret = _battery_bsd_acpi_check(); - break; - case CHECK_APM: - ret = _battery_bsd_apm_check(); - break; - default: - break; - } -#elif defined(HAVE_CFBASE_H) /* OS X */ - ret = _battery_darwin_check(); -#else - if (battery_config->battery_check_mode == 0) - { - if (ecore_file_is_dir("/sys/class/power_supply")) /* >= 2.6.24 */ - battery_config->battery_check_mode = CHECK_SYS_ACPI; - else if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */ - battery_config->battery_check_mode = CHECK_ACPI; - else if (ecore_file_exists("/proc/apm")) - battery_config->battery_check_mode = CHECK_APM; - else if (ecore_file_is_dir("/proc/pmu")) - battery_config->battery_check_mode = CHECK_PMU; - } - switch (battery_config->battery_check_mode) - { - case CHECK_ACPI: - ret = _battery_linux_acpi_check(); - break; - case CHECK_APM: - ret = _battery_linux_apm_check(); - break; - case CHECK_PMU: - ret = _battery_linux_powerbook_check(); - break; - case CHECK_SYS_ACPI: - ret = _battery_linux_sys_acpi_check(); - break; - default: - break; - } -#endif - for (l = battery_config->instances; l; l = l->next) - { - Instance *inst; - - inst = l->data; - if (ret) - { - if (ret->has_battery) - { - if (ret->state == BATTERY_STATE_CHARGING) - { - if (battery_config->battery_prev_ac != 1) - edje_object_signal_emit(inst->o_battery, "e,state,charging", "e"); - edje_object_signal_emit(inst->o_battery, "e,action,pulse,stop", "e"); - edje_object_part_text_set(inst->o_battery, "e.text.reading", ret->reading); - edje_object_part_text_set(inst->o_battery, "e.text.time", ret->time); - _battery_face_level_set(inst, ret->level); - battery_config->battery_prev_ac = 1; - } - else if (ret->state == BATTERY_STATE_DISCHARGING) - { - if (battery_config->battery_prev_ac != 0) - edje_object_signal_emit(inst->o_battery, "e,state,discharging", "e"); - if (ret->alarm) - { - if (!battery_config->alarm_triggered) - { - E_Dialog *dia; - - dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_e_mod_battery_low_dialog"); - if (!dia) return 0; - e_dialog_title_set(dia, "Enlightenment Battery Module"); - e_dialog_icon_set(dia, "enlightenment/e", 64); - e_dialog_text_set(dia, - _("Battery Running Low
" - "Your battery is running low.
" - "You may wish to switch to an AC source.")); - e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL); - e_win_centered_set(dia->win, 1); - e_dialog_show(dia); - edje_object_signal_emit(inst->o_battery, "e,action,pulse,start", "e"); - } - } - edje_object_part_text_set(inst->o_battery, "e.text.reading", ret->reading); - edje_object_part_text_set(inst->o_battery, "e.text.time", ret->time); - _battery_face_level_set(inst, ret->level); - battery_config->battery_prev_ac = 0; - if (ret->alarm) - battery_config->alarm_triggered = 1; - } - else - { - /* ret->state == BATTERY_STATE_NONE */ - if (battery_config->battery_prev_ac != 1) - edje_object_signal_emit(inst->o_battery, "e,state,charging", "e"); - if (battery_config->battery_prev_battery == 0) - edje_object_signal_emit(inst->o_battery, "e,state,charging", "e"); - edje_object_part_text_set(inst->o_battery, "e.text.reading", ret->reading); - edje_object_part_text_set(inst->o_battery, "e.text.time", ret->time); - _battery_face_level_set(inst, ret->level); - battery_config->battery_prev_ac = 1; - battery_config->battery_prev_battery = 1; - } - } - else - { - /* Hasn't battery */ - if (battery_config->battery_prev_battery != 0) - edje_object_signal_emit(inst->o_battery, "e,state,unknown", "e"); - edje_object_part_text_set(inst->o_battery, "e.text.reading", ret->reading); - edje_object_part_text_set(inst->o_battery, "e.text.time", ret->time); - _battery_face_level_set(inst, ret->level); - battery_config->battery_prev_battery = 0; - } - } - else - { - /* Error reading status */ - if (battery_config->battery_prev_battery != -2) - edje_object_signal_emit(inst->o_battery, "e,state,unknown", "e"); - edje_object_part_text_set(inst->o_battery, "e.text.reading", _("ERROR")); - edje_object_part_text_set(inst->o_battery, "e.text.time", "--:--"); - _battery_face_level_set(inst, (double)(rand() & 0xff) / 255.0); - battery_config->battery_prev_battery = -2; - battery_config->battery_check_mode = CHECK_NONE; - } - } - if (ret) - { - free(ret->reading); - free(ret->time); - free(ret); - } - return 1; -} - -static Status * -_battery_linux_sys_acpi_check(void) -{ - Ecore_List *bats; - char buf[4096], buf2[4096]; - char *name; - int bat_max = 0; - int bat_filled = 0; - int bat_level = 0; - int bat_drain = 1; - int bat_val = 0; - int discharging = 0; - int charging = 0; - int battery = 0; - int design_cap_unknown = 0; - int last_full_unknown = 0; - int rate_unknown = 0; - int level_unknown = 0; - int hours, minutes; - Status *stat; - static double last_poll_time = 0.0; - double poll_time, t; - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - t = ecore_time_get(); - poll_time = t - last_poll_time; - last_poll_time = t; - - /* Read some information on first run. */ - bats = ecore_file_ls("/sys/class/power_supply/"); - if (bats) - { - while ((name = ecore_list_next(bats))) - { - FILE *f; - int design_cap = 0; - int last_full = 0; - int present = 0; - char *charging_state = NULL; - int rate = 1; - int level = 0; - - if (name && strncasecmp("BAT", name, 3)) continue; - - /* present */ - snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/present", name); - f = fopen(buf, "r"); - if (f) - { - fgets(buf2, sizeof(buf2), f); - present = atoi(buf2); - - fclose(f); - } - - /* design capacity */ - snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full_design", name); - f = fopen(buf, "r"); - if (f) - { - fgets(buf2, sizeof(buf2), f); - design_cap = atoi(buf2); - - if(!design_cap) design_cap_unknown++; - - fclose(f); - } - - /* last full capacity */ - snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_full", name); - f = fopen(buf, "r"); - if (f) - { - fgets(buf2, sizeof(buf2), f); - last_full = atoi(buf2); - - if(!last_full) last_full_unknown++; - - fclose(f); - } - - /* charging state */ - snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/status", name); - f = fopen(buf, "r"); - if (f) - { - fgets(buf2, sizeof(buf2), f); - charging_state = strdup(buf2); - - fclose(f); - } - - /* present rate */ - snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/current_now", name); - f = fopen(buf, "r"); - if (f) - { - fgets(buf2, sizeof(buf2), f); - rate = atoi(buf2); - - fclose(f); - } - - /* remaining capacity */ - snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/charge_now", name); - f = fopen(buf, "r"); - if (f) - { - fgets(buf2, sizeof(buf2), f); - level = atoi(buf2); - - if(!level) level_unknown++; - - fclose(f); - } - - if (present) battery++; - - if (charging_state) - { - if (!strncmp(charging_state, "Discharging", strlen("Discharging"))) - { - discharging++; - if ((rate == 0) && (rate_unknown == 0)) rate_unknown++; - } - else if (!strncmp(charging_state, "Charging", strlen("Charging"))) - { - charging++; - if ((rate == 0) && (rate_unknown == 0)) rate_unknown++; - } - else if (!strncmp(charging_state, "Full", strlen("Full"))) - { - rate_unknown--; - } - free(charging_state); - } - - bat_drain += rate; - bat_level += level; - bat_max += design_cap; - bat_filled += last_full; - } - ecore_list_destroy(bats); - } - - - - if ((rate_unknown) && (bat_level != battery_config->battery_prev_level) && - (battery_config->battery_prev_level >= 0) && (poll_time > 0.0)) - { - bat_drain = - ((bat_level - battery_config->battery_prev_level) * 60 * 60) / - poll_time; - if (bat_drain < 0) bat_drain = -bat_drain; - if (bat_drain == 0) bat_drain = 1; - rate_unknown = 0; - } - else - { - if (battery_config->battery_prev_drain < 1) - battery_config->battery_prev_drain = 1; - if (bat_drain < 1) - bat_drain = battery_config->battery_prev_drain; - battery_config->battery_prev_drain = bat_drain; - } - - if (bat_filled > 0) bat_val = (100 * bat_level) / bat_filled; - else bat_val = 100; - - battery_config->battery_prev_level = bat_level; - - if (discharging) minutes = (60 * bat_level) / bat_drain; - else - { - /* FIXME: Batteries charge in paralell! */ - if (bat_filled > 0) - minutes = (60 * (bat_filled - bat_level)) / bat_drain; - else - minutes = 0; - } - hours = minutes / 60; - minutes -= (hours * 60); - - if (hours < 0) hours = 0; - if (minutes < 0) minutes = 0; - - if (!battery) - { - stat->has_battery = 0; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("N/A")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - else if ((charging) || (discharging)) - { - battery_config->battery_prev_battery = 1; - stat->has_battery = 1; - if (charging) - { - stat->state = BATTERY_STATE_CHARGING; - battery_config->alarm_triggered = 0; - } - else if (discharging) - { - stat->state = BATTERY_STATE_DISCHARGING; - if (stat->level < 0.1) - { - if (((hours * 60) + minutes) <= battery_config->alarm) - stat->alarm = 1; - if (bat_val <= battery_config->alarm_p) - stat->alarm = 1; - } - } - - if (level_unknown) - { - stat->reading = strdup(_("BAD DRIVER")); - stat->time = strdup("--:--"); - stat->level = 0.0; - } - else if (rate_unknown) - { - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - stat->time = strdup("--:--"); - stat->level = (double)bat_val / 100.0; - } - else - { - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - stat->level = (double)bat_val / 100.0; - } - } - else - { - stat->has_battery = 1; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("FULL")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - - return stat; -} - -static Status * -_battery_linux_acpi_check(void) -{ - Ecore_List *bats; - char buf[4096], buf2[4096]; - char *name; - int bat_max = 0; - int bat_filled = 0; - int bat_level = 0; - int bat_drain = 1; - int bat_val = 0; - int discharging = 0; - int charging = 0; - int battery = 0; - int design_cap_unknown = 0; - int last_full_unknown = 0; - int rate_unknown = 0; - int level_unknown = 0; - int hours, minutes; - Status *stat; - static double last_poll_time = 0.0; - double poll_time, t; - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - t = ecore_time_get(); - poll_time = t - last_poll_time; - last_poll_time = t; - - /* Read some information on first run. */ - bats = ecore_file_ls("/proc/acpi/battery"); - if (bats) - { - while ((name = ecore_list_next(bats))) - { - FILE *f; - char *tmp; - int design_cap; - int last_full; - - snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/info", name); - f = fopen(buf, "r"); - if (f) - { - design_cap = 0; - last_full = 0; - /* present */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - /* design capacity */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - tmp = _battery_string_get(buf2); - if (tmp) - { - if (!strcmp(tmp, "unknown")) design_cap_unknown = 1; - else design_cap = atoi(tmp); - free(tmp); - } - /* last full capacity */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - tmp = _battery_string_get(buf2); - if (tmp) - { - if (!strcmp(tmp, "unknown")) last_full_unknown = 1; - else last_full = atoi(tmp); - free(tmp); - } - fclose(f); - } - snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name); - f = fopen(buf, "r"); - if (f) - { - char *present; - char *capacity_state; - char *charging_state; - char *tmp; - int rate = 1; - int level = 0; - - /* present */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - present = _battery_string_get(buf2); - /* capacity state */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - capacity_state = _battery_string_get(buf2); - /* charging state */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - charging_state = _battery_string_get(buf2); - /* present rate */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - tmp = _battery_string_get(buf2); - if (tmp) - { - if (!strcmp(tmp, "unknown")) rate_unknown++; - else rate = atoi(tmp); - free(tmp); - } - /* remaining capacity */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - tmp = _battery_string_get(buf2); - if (tmp) - { - if (!strcmp(tmp, "unknown")) level_unknown++; - else level = atoi(tmp); - free(tmp); - } - fclose(f); - if (present) - { - if (!strcmp(present, "yes")) battery++; - free(present); - } - if (charging_state) - { - if (!strcmp(charging_state, "discharging")) - { - discharging++; - if ((rate == 0) && (rate_unknown == 0)) rate_unknown++; - } - else if (!strcmp(charging_state, "charging")) - { - charging++; - if ((rate == 0) && (rate_unknown == 0)) rate_unknown++; - } - else if (!strcmp(charging_state, "charged")) - { - rate_unknown--; - } - free(charging_state); - } - E_FREE(capacity_state); - - bat_drain += rate; - bat_level += level; - } - bat_max += design_cap; - bat_filled += last_full; - } - ecore_list_destroy(bats); - } - - if ((rate_unknown) && (bat_level != battery_config->battery_prev_level) && - (battery_config->battery_prev_level >= 0) && (poll_time > 0.0)) - { - bat_drain = - ((bat_level - battery_config->battery_prev_level) * 60 * 60) / - poll_time; - if (bat_drain < 0) bat_drain = -bat_drain; - if (bat_drain == 0) bat_drain = 1; - rate_unknown = 0; - } - else - { - if (battery_config->battery_prev_drain < 1) - battery_config->battery_prev_drain = 1; - if (bat_drain < 1) - bat_drain = battery_config->battery_prev_drain; - battery_config->battery_prev_drain = bat_drain; - } - - if (bat_filled > 0) bat_val = (100 * bat_level) / bat_filled; - else bat_val = 100; - - battery_config->battery_prev_level = bat_level; - - if (discharging) minutes = (60 * bat_level) / bat_drain; - else - { - /* FIXME: Batteries charge in paralell! */ - if (bat_filled > 0) - minutes = (60 * (bat_filled - bat_level)) / bat_drain; - else - minutes = 0; - } - hours = minutes / 60; - minutes -= (hours * 60); - - if (hours < 0) hours = 0; - if (minutes < 0) minutes = 0; - - if (!battery) - { - stat->has_battery = 0; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("N/A")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - else if ((charging) || (discharging)) - { - battery_config->battery_prev_battery = 1; - stat->has_battery = 1; - if (charging) - { - stat->state = BATTERY_STATE_CHARGING; - battery_config->alarm_triggered = 0; - } - else if (discharging) - { - stat->state = BATTERY_STATE_DISCHARGING; - if (stat->level < 0.1) - { - if (((hours * 60) + minutes) <= battery_config->alarm) - stat->alarm = 1; - if (bat_val <= battery_config->alarm_p) - stat->alarm = 1; - } - } - if (level_unknown) - { - stat->reading = strdup(_("BAD DRIVER")); - stat->time = strdup("--:--"); - stat->level = 0.0; - } - else if (rate_unknown) - { - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - stat->time = strdup("--:--"); - stat->level = (double)bat_val / 100.0; - } - else - { - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - stat->level = (double)bat_val / 100.0; - } - } - else - { - stat->has_battery = 1; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("FULL")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - return stat; -} - -static Status * -_battery_linux_apm_check(void) -{ - FILE *f; - char s[256], s1[32], s2[32], s3[32], buf[4096]; - int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val; - int hours, minutes; - - Status *stat; - - f = fopen("/proc/apm", "r"); - if (!f) return NULL; - - fgets(s, sizeof(s), f); s[sizeof(s) - 1] = 0; - if (sscanf(s, "%*s %*s %x %x %x %x %s %s %s", - &apm_flags, &ac_stat, &bat_stat, &bat_flags, s1, s2, s3) != 7) - { - fclose(f); - return NULL; - } - s1[strlen(s1) - 1] = 0; - bat_val = atoi(s1); - if (!strcmp(s3, "sec")) time_val = atoi(s2); - else if (!strcmp(s3, "min")) time_val = atoi(s2) * 60; - fclose(f); - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - if ((bat_flags != 0xff) && (bat_flags & 0x80)) - { - stat->has_battery = 0; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup("N/A"); - stat->time = strdup("--:--"); - stat->level = 1.0; - return stat; - } - - - battery_config->battery_prev_battery = 1; - stat->has_battery = 1; - if (bat_val >= 0) - { - if (bat_val > 100) bat_val = 100; - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - stat->level = (double)bat_val / 100.0; - } - else - { - switch (bat_stat) - { - case 0: - stat->reading = strdup(_("High")); - stat->level = 1.0; - break; - case 1: - stat->reading = strdup(_("Low")); - stat->level = 0.5; - break; - case 2: - stat->reading = strdup(_("Danger")); - stat->level = 0.25; - break; - case 3: - stat->reading = strdup(_("Charging")); - stat->level = 1.0; - break; - } - } - - if (ac_stat == 1) - { - stat->state = BATTERY_STATE_CHARGING; - stat->time = strdup("--:--"); - } - else - { - /* ac_stat == 0 */ - stat->state = BATTERY_STATE_DISCHARGING; - - hours = time_val / 3600; - minutes = (time_val / 60) % 60; - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - if (stat->level < 0.1) - { - if (((hours * 60) + minutes) <= battery_config->alarm) - stat->alarm = 1; - if (bat_val <= battery_config->alarm_p) - stat->alarm = 1; - } - } - - return stat; -} - - -/* hack for pmu */ - -/* This function converts a string to an integer. Additionally to - * atoi() it converts also hexadecimal values - */ -static int -axtoi(char *arg) -{ - int n, val, pwr=1, m, rc = 0; - char hex[9], c; - - for (n = 0, m = 0; n < strlen(arg); n++) - { - if (arg[n] != ' ') - { - hex[m++] = c = toupper(arg[n]); - if ((m == sizeof(hex)) || (c < '0') || (c > 'F')) - return 0; /* overflow or invalid */ - } - } - hex[m] = '\0'; /* terminate string */ - - for (n = 0; n < m; n++) - { - c = hex[m-n-1]; - if ((c >= 'A') && (c <= 'F')) - val = c -'A' + 10; - else - val = c - '0'; - rc = rc + val * pwr; - pwr *= 16; - } - return rc; -} - -static Status * -_battery_linux_powerbook_check(void) -{ - Ecore_List *bats; - char buf[4096], buf2[4096]; - char *name; - char *token; - FILE *f; - int discharging = 0; - int charging = 0; - int battery = 0; - int ac = 0; - int seconds = 0; - int hours, minutes; - int flags; - int voltage; - int charge; - int max_charge; - double tmp; - Status *stat; - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - /* Read some information. */ - f = fopen("/proc/pmu/info", "r"); - if (f) - { - /* Skip driver */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - /* Skip firmware */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - /* Read ac */ - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - ac = _battery_int_get(buf2); - fclose(f); - } - - bats = ecore_file_ls("/proc/pmu"); - if (bats) - { - while ((name = ecore_list_next(bats))) - { - if (strncmp(name, "battery", 7)) - continue; - - snprintf(buf, sizeof(buf), "/proc/pmu/%s", name); - f = fopen(buf, "r"); - if (f) - { - int time = 0; - int current = 0; - - while (fgets (buf,sizeof (buf), f)) - { - if ((token = strtok (buf, ":"))) - { - if (!strncmp ("flags", token, 5)) - flags = axtoi (strtok (0, ": ")); - else if (!strncmp ("charge", token, 6)) - charge = atoi(strtok(0, ": ")); - else if (!strncmp ("max_charge", token, 9)) - max_charge = atoi (strtok(0,": ")); - else if (!strncmp ("current", token, 7)) - current = atoi (strtok(0, ": ")); - else if (!strncmp ("time rem", token, 8)) - time = atoi (strtok(0, ": ")); - else if (!strncmp ("voltage", token, 7)) - voltage = atoi (strtok(0,": ")); - else - strtok (0,": "); - } - } - /* Skip flag; - int tmp = 0; - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - tmp = _battery_int_get(buf2); - charge += tmp; - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - tmp = _battery_int_get(buf2); - max_charge += tmp; - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - current = _battery_int_get(buf2); - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; - time = _battery_int_get(buf2); - */ - fclose(f); - - battery = 1; - if (!current) - { - /* Neither charging nor discharging */ - } - else if (!ac) - { - /* When on dc, we are discharging */ - discharging = 1; - seconds += time; - } - else - { - /* Charging */ - charging = 1; - /* Charging works in paralell */ - seconds = MAX(time, seconds); - } - - } - } - ecore_list_destroy(bats); - } - hours = seconds / (60 * 60); - seconds -= hours * (60 * 60); - minutes = seconds / 60; - seconds -= minutes * 60; - - if (hours < 0) hours = 0; - if (minutes < 0) minutes = 0; - - - if (!battery) - { - stat->has_battery = 0; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("N/A")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - else if ((charging) || (discharging)) - { - stat->has_battery = 1; - stat->level = (double)charge / (double)max_charge; - if (stat->level > 1.0) stat->level = 1.0; - tmp = (double)max_charge / 100; - tmp = (double)charge / tmp; - stat->level = (double)tmp / 100; - - snprintf(buf, sizeof(buf), "%.0f%%", tmp); - stat->reading = strdup(buf); - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - if (charging) - { - stat->state = BATTERY_STATE_CHARGING; - battery_config->alarm_triggered = 0; - } - else if (discharging) - { - stat->state = BATTERY_STATE_DISCHARGING; - if (stat->level < 0.1) - { - if (((hours * 60) + minutes) <= battery_config->alarm) - stat->alarm = 1; - if (stat->level <= battery_config->alarm_p) - stat->alarm = 1; - } - } - } - else - { - stat->has_battery = 1; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("FULL")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - return stat; -} - -#ifdef __FreeBSD__ -static Status * -_battery_bsd_acpi_check(void) -{ - /* Assumes only a single battery - I don't know how multiple batts - * are represented in sysctl */ - - Ecore_List *bats; - char buf[4096], buf2[4096]; - char *name; - - int bat_max = 0; - int bat_filled = 0; - int bat_level = 0; - int bat_drain = 1; - - int bat_val = 0; - - int discharging = 0; - int charging = 0; - int battery = 0; - - int design_cap_unknown = 0; - int last_full_unknown = 0; - int rate_unknown = 0; - int level_unknown = 0; - - int hours, minutes; - - int mib_state[4]; - int mib_life[4]; - int mib_time[4]; - int mib_units[4]; - size_t len; - int state; - int level; - int time; - int life; - int batteries; - - Status *stat; - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - /* Read some information on first run. */ - len = 4; - sysctlnametomib("hw.acpi.battery.state", mib_state, &len); - len = sizeof(state); - if (sysctl(mib_state, 4, &state, &len, NULL, 0) == -1) - /* ERROR */ - state = -1; - - len = 4; - sysctlnametomib("hw.acpi.battery.life", mib_life, &len); - len = sizeof(life); - if (sysctl(mib_life, 4, &life, &len, NULL, 0) == -1) - /* ERROR */ - level = -1; - - bat_val = life; - - len = 4; - sysctlnametomib("hw.acpi.battery.time", mib_time, &len); - len = sizeof(time); - if (sysctl(mib_time, 4, &time, &len, NULL, 0) == -1) - /* ERROR */ - time = -2; - - len = 4; - sysctlnametomib("hw.acpi.battery.units", mib_units, &len); - len = sizeof(batteries); - if (sysctl(mib_time, 4, &batteries, &len, NULL, 0) == -1) - /* ERROR */ - batteries = 1; - - if (battery_config->battery_prev_drain < 1) - battery_config->battery_prev_drain = 1; - - if (bat_drain < 1) - bat_drain = battery_config->battery_prev_drain; - - battery_config->battery_prev_drain = bat_drain; - - /*if (bat_filled > 0) - bat_val = (100 * bat_level) / bat_filled; - else - bat_val = 100; - - if (state == BATTERY_STATE_DISCHARGING) - minutes = (60 * bat_level) / bat_drain; - else - { - if (bat_filled > 0) - minutes = (60 * (bat_filled - bat_level)) / bat_drain; - else - minutes = 0; - }*/ - minutes = time; - hours = minutes / 60; - minutes -= (hours * 60); - - if (hours < 0) - hours = 0; - if (minutes < 0) - minutes = 0; - - if (batteries == 1) /* hw.acpi.battery.units = 1 means NO BATTS */ - { - stat->has_battery = 0; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("N/A")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - else if ((state == BATTERY_STATE_CHARGING) || - (state == BATTERY_STATE_DISCHARGING)) - { - battery_config->battery_prev_battery = 1; - stat->has_battery = 1; - if (state == BATTERY_STATE_CHARGING) - { - stat->state = BATTERY_STATE_CHARGING; - battery_config->alarm_triggered = 0; - } - else if (state == BATTERY_STATE_DISCHARGING) - { - stat->state = BATTERY_STATE_DISCHARGING; - if (stat->level < 0.1) /* Why this if condition */ - { - if (((hours * 60) + minutes) <= battery_config->alarm) - stat->alarm = 1; - if (bat_val <= battery_config->alarm_p) - stat->alarm = 1; - } - } - if (level == -1) - { - stat->reading = strdup(_("BAD DRIVER")); - stat->time = strdup("--:--"); - stat->level = 0.0; - } - else if (time == -1) - { - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - stat->time = strdup("--:--"); - stat->level = (double)bat_val / 100.0; - } - else - { - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - stat->level = (double)bat_val / 100.0; - } - } - else - { - stat->has_battery = 1; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup(_("FULL")); - stat->time = strdup("--:--"); - stat->level = 1.0; - } - return stat; -} - -static Status * -_battery_bsd_apm_check(void) -{ -#ifdef __i386__ - int ac_stat, bat_stat, bat_val, time_val; - char buf[4096]; - int hours, minutes; - int apm_fd = -1; - struct apm_info info; - - Status *stat; - - apm_fd = open("/dev/apm", O_RDONLY); - - if (apm_fd != -1 && ioctl(apm_fd, APMIO_GETINFO, &info) != -1) - { - /* set values */ - ac_stat = info.ai_acline; - bat_stat = info.ai_batt_stat; - bat_val = info.ai_batt_life; - time_val = info.ai_batt_time; - } - else - { - return NULL; - } - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - if (info.ai_batteries == 1) /* ai_batteries == 1 means NO battery, - ai_batteries == 2 means 1 battery */ - { - stat->has_battery = 0; - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup("N/A"); - stat->time = strdup("--:--"); - stat->level = 1.0; - return stat; - } - - - battery_config->battery_prev_battery = 1; - stat->has_battery = 1; - - if (ac_stat) /* Wallpowered */ - { - stat->state = BATTERY_STATE_CHARGING; - stat->time = strdup("--:--"); - switch (bat_stat) /* On FreeBSD the time_val is -1 when AC ist plugged - in. This means we don't know how long the battery - will recharge */ - { - case 0: - stat->reading = strdup(_("High")); - stat->level = 1.0; - break; - case 1: - stat->reading = strdup(_("Low")); - stat->level = 0.5; - break; - case 2: - stat->reading = strdup(_("Danger")); - stat->level = 0.25; - break; - case 3: - stat->reading = strdup(_("Charging")); - stat->level = 1.0; - break; - } - } - else /* Running on battery */ - { - stat->state = BATTERY_STATE_DISCHARGING; - - snprintf(buf, sizeof(buf), "%i%%", bat_val); - stat->reading = strdup(buf); - stat->level = (double)bat_val / 100.0; - - hours = time_val / 3600; - minutes = (time_val / 60) % 60; - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - - if (stat->level < 0.1) /* Why this if condition? */ - { - if (((hours * 60) + minutes) <= battery_config->alarm) - stat->alarm = 1; - if (bat_val <= battery_config->alarm_p) - stat->alarm = 1; - } - } - - return stat; -#else - return NULL; -#endif -} -#endif - -#ifdef HAVE_CFBASE_H -/* - * There is a good chance this will work with a UPS as well as a battery. - */ -static Status * -_battery_darwin_check(void) -{ - const void *values; - int device_num; - int device_count; - int hours, minutes; - int currentval = 0; - int maxval = 0; - char buf[4096]; - CFTypeRef blob; - CFArrayRef sources; - CFDictionaryRef device_dict; - - Status *stat; - - stat = E_NEW(Status, 1); - if (!stat) return NULL; - - /* - * Retrieve the power source data and the array of sources. - */ - blob = IOPSCopyPowerSourcesInfo(); - sources = IOPSCopyPowerSourcesList(blob); - device_count = CFArrayGetCount(sources); - - for (device_num = 0; device_num < device_count; device_num++) - { - CFTypeRef ps; - - printf("device %d of %d\n", device_num, device_count); - - /* - * Retrieve a dictionary of values for this device and the - * count of keys in the dictionary. - */ - ps = CFArrayGetValueAtIndex(sources, device_num); - device_dict = IOPSGetPowerSourceDescription(blob, ps); - - /* - * Retrieve the charging key and save the present charging value if - * one exists. - */ - if (CFDictionaryGetValueIfPresent(device_dict, CFSTR(kIOPSIsChargingKey), &values)) - { - stat->has_battery = 1; - printf("%s: %d\n", kIOPSIsChargingKey, CFBooleanGetValue(values)); - if (CFBooleanGetValue(values) > 0) - { - stat->state = BATTERY_STATE_CHARGING; - } - else - { - stat->state = BATTERY_STATE_DISCHARGING; - } - /* CFRelease(values); */ - break; - } - - } - - /* - * Check for battery. - */ - if (!stat->has_battery) - { - CFRelease(sources); - CFRelease(blob); - stat->state = BATTERY_STATE_NONE; - stat->reading = strdup("N/A"); - stat->time = strdup("--:--"); - stat->level = 1.0; - return stat; - } - - /* - * A battery was found so move along based on that assumption. - */ - battery_config->battery_prev_battery = 1; - stat->has_battery = 1; - - /* - * Retrieve the current capacity key. - */ - values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey)); - CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); - /* CFRelease(values); */ - - /* - * Retrieve the max capacity key. - */ - values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSMaxCapacityKey)); - CFNumberGetValue(values, kCFNumberSInt32Type, &maxval); - /* CFRelease(values); */ - - /* - * Calculate the percentage charged. - */ - stat->level = (double)currentval / (double)maxval; - printf("Battery charge %g\n", stat->level); - - /* - * Retrieve the remaining battery power or time until charged in minutes. - */ - if (stat->state == BATTERY_STATE_DISCHARGING) - { - values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey)); - CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); - /* CFRelease(values); */ - - /* - * Display remaining battery percentage. - */ - snprintf(buf, sizeof(buf), "%i%%", (int)(stat->level * 100)); - stat->reading = strdup(buf); - - hours = currentval / 60; - minutes = currentval % 60; - - /* - * Check if an alarm should be raised. - */ - if (currentval <= battery_config->alarm) - stat->alarm = 1; - if (stat->level <= battery_config->alarm_p) - stat->alarm = 1; - } - else - { - values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey)); - CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); - /* CFRelease(values); */ - - stat->reading = strdup(_("Charging")); - - hours = currentval / 60; - minutes = currentval % 60; - } - - /* - * Store the time remaining. - */ - if (minutes >= 0) - { - snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes); - stat->time = strdup(buf); - } - else - stat->time = strdup("--:--"); - - CFRelease(sources); - CFRelease(blob); - - return stat; -} -#endif - static void _battery_face_level_set(Instance *inst, double level) { @@ -1613,36 +180,6 @@ _battery_face_level_set(Instance *inst, double level) edje_object_message_send(inst->o_battery, EDJE_MESSAGE_FLOAT, 1, &msg); } -static int -_battery_int_get(char *buf) -{ - char *p, *q; - - p = strchr(buf, ':'); - if (!p) return 0; - p++; - while (*p == ' ') p++; - q = p; - while ((*q != ' ') && (*q != '\n')) q++; - if (q) *q = 0; - return atoi(p); -} - -static char * -_battery_string_get(char *buf) -{ - char *p, *q; - - p = strchr(buf, ':'); - if (!p) return NULL; - p++; - while (*p == ' ') p++; - q = p; - while ((*q) && (*q != ' ') && (*q != '\n')) q++; - if (q) *q = 0; - return strdup(p); -} - static void _battery_face_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi) { @@ -1654,12 +191,19 @@ _battery_face_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi) void _battery_config_updated(void) { + char buf[4096]; + if (!battery_config) return; - ecore_poller_del(battery_config->battery_check_poller); - battery_config->battery_check_poller = - ecore_poller_add(ECORE_POLLER_CORE, battery_config->poll_interval, - _battery_cb_check, NULL); - _battery_cb_check(NULL); + ecore_exe_terminate(battery_config->batget_exe); + ecore_exe_free(battery_config->batget_exe); + snprintf(buf, sizeof(buf), + "%s/%s/batget %i", + e_module_dir_get(battery_config->module), MODULE_ARCH, + battery_config->poll_interval); + battery_config->batget_exe = ecore_exe_pipe_run(buf, + ECORE_EXE_PIPE_READ | + ECORE_EXE_PIPE_READ_LINE_BUFFERED, + NULL); } /***************************************************************************/ @@ -1689,23 +233,38 @@ e_modapi_init(E_Module *m) if (!battery_config) { battery_config = E_NEW(Config, 1); - battery_config->poll_interval = 256; + battery_config->poll_interval = 512; battery_config->alarm = 30; battery_config->alarm_p = 10; } - E_CONFIG_LIMIT(battery_config->poll_interval, 1, 1024); + E_CONFIG_LIMIT(battery_config->poll_interval, 4, 4096); E_CONFIG_LIMIT(battery_config->alarm, 0, 60); E_CONFIG_LIMIT(battery_config->alarm_p, 0, 100); - battery_config->battery_check_mode = CHECK_NONE; - battery_config->battery_prev_drain = 1; - battery_config->battery_prev_ac = -1; - battery_config->battery_prev_battery = -1; - battery_config->battery_check_poller = - ecore_poller_add(ECORE_POLLER_CORE, battery_config->poll_interval, - _battery_cb_check, NULL); battery_config->module = m; + battery_config->full = -2; + battery_config->time_left = -2; + battery_config->have_battery = -2; + battery_config->have_power = -2; + + snprintf(buf, sizeof(buf), + "%s/%s/batget %i", + e_module_dir_get(battery_config->module), MODULE_ARCH, + battery_config->poll_interval); + battery_config->batget_exe = ecore_exe_pipe_run(buf, + ECORE_EXE_PIPE_READ | + ECORE_EXE_PIPE_READ_LINE_BUFFERED, + NULL); + battery_config->batget_data_handler = + ecore_event_handler_add(ECORE_EXE_EVENT_DATA, + _battery_cb_exe_data, + NULL); + battery_config->batget_del_handler = + ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _battery_cb_exe_del, + NULL); + e_gadcon_provider_register(&_gadcon_class); snprintf(buf, sizeof(buf), "%s/e-module-battery.edj", e_module_dir_get(m)); @@ -1723,10 +282,23 @@ e_modapi_shutdown(E_Module *m) e_gadcon_provider_unregister(&_gadcon_class); + ecore_exe_terminate(battery_config->batget_exe); + ecore_exe_free(battery_config->batget_exe); + battery_config->batget_exe = NULL; + + if (battery_config->batget_data_handler) + { + ecore_event_handler_del(battery_config->batget_data_handler); + battery_config->batget_data_handler = NULL; + } + if (battery_config->batget_del_handler) + { + ecore_event_handler_del(battery_config->batget_del_handler); + battery_config->batget_del_handler = NULL; + } + if (battery_config->config_dialog) e_object_del(E_OBJECT(battery_config->config_dialog)); - if (battery_config->battery_check_poller) - ecore_poller_del(battery_config->battery_check_poller); if (battery_config->menu) { e_menu_post_deactivate_callback_set(battery_config->menu, NULL, NULL); @@ -1747,3 +319,104 @@ e_modapi_save(E_Module *m) } /**/ /***************************************************************************/ + +/***************************************************************************/ +/**/ +static int +_battery_cb_exe_data(void *data, int type, void *event) +{ + Ecore_Exe_Event_Data *ev; + + ev = event; + if (ev->exe != battery_config->batget_exe) return 1; + if ((ev->lines) && (ev->lines[0].line)) + { + int i; + + for (i = 0; ev->lines[i].line; i++) + { + if (!strcmp(ev->lines[i].line, "ERROR")) + { + Evas_List *l; + + for (l = battery_config->instances; l; l = l->next) + { + Instance *inst; + + inst = l->data; + edje_object_signal_emit(inst->o_battery, "e,state,unknown", "e"); + edje_object_part_text_set(inst->o_battery, "e.text.reading", _("ERROR")); + edje_object_part_text_set(inst->o_battery, "e.text.time", _("ERROR")); + } + } + else + { + int full = 0; + int time_left = 0; + int have_battery = 0; + int have_power = 0; + Evas_List *l; + + sscanf(ev->lines[i].line, "%i %i %i %i", + &full, &time_left, &have_battery, &have_power); + for (l = battery_config->instances; l; l = l->next) + { + Instance *inst; + + inst = l->data; + if (have_power != battery_config->have_power) + { + if (have_power) + edje_object_signal_emit(inst->o_battery, "e,state,charging", "e"); + else + edje_object_signal_emit(inst->o_battery, "e,state,discharging", "e"); + } + if (have_battery) + { + if (battery_config->full != full) + { + char buf[256]; + + snprintf(buf, sizeof(buf), "%i%%", full); + edje_object_part_text_set(inst->o_battery, "e.text.reading", buf); + _battery_face_level_set(inst, (double)full / 100.0); + } + } + else + { + edje_object_part_text_set(inst->o_battery, "e.text.reading", _("N/A")); + _battery_face_level_set(inst, 0.0); + } + if (time_left != battery_config->time_left) + { + char buf[256]; + int mins, hrs; + + hrs = time_left / 3600; + mins = (time_left) / 60 - (hrs * 60); + snprintf(buf, sizeof(buf), "%i:%02i", hrs, mins); + if (hrs < 0) hrs = 0; + if (mins < 0) mins = 0; + edje_object_part_text_set(inst->o_battery, "e.text.time", buf); + } + } + battery_config->full = full; + battery_config->time_left = time_left; + battery_config->have_battery = have_battery; + battery_config->have_power = have_power; + } + } + } + return 0; +} + +static int +_battery_cb_exe_del(void *data, int type, void *event) +{ + Ecore_Exe_Event_Del *ev; + + ev = event; + if (ev->exe != battery_config->batget_exe) return 1; + battery_config->batget_exe = NULL; + return 0; +} diff --git a/src/modules/battery/e_mod_main.h b/src/modules/battery/e_mod_main.h index 7cb05f0a1..d1b4864db 100644 --- a/src/modules/battery/e_mod_main.h +++ b/src/modules/battery/e_mod_main.h @@ -25,40 +25,13 @@ struct _Config Evas_List *instances; E_Menu *menu; int alarm_triggered; - int battery_check_mode; - Ecore_Poller *battery_check_poller; - int battery_prev_drain; - int battery_prev_ac; - int battery_prev_battery; - int battery_prev_level; -}; - -#ifdef __FreeBSD__ -#define BATTERY_STATE_NONE 0 -#define BATTERY_STATE_DISCHARGING 1 -#define BATTERY_STATE_CHARGING 2 -#define BATTERY_STATE_REMOVED 7 -#else -#define BATTERY_STATE_NONE 0 -#define BATTERY_STATE_CHARGING 1 -#define BATTERY_STATE_DISCHARGING 2 -#endif - -struct _Status -{ - /* Low battery */ - unsigned char alarm; - /* Is there a battery? */ - unsigned char has_battery; - /* charging, discharging, none */ - unsigned char state; - /* Battery level */ - double level; - /* Text */ - /* reading == % left */ - char *reading; - /* time == time left to empty / full */ - char *time; + Ecore_Exe *batget_exe; + Ecore_Event_Handler *batget_data_handler; + Ecore_Event_Handler *batget_del_handler; + int full; + int time_left; + int have_battery; + int have_power; }; EAPI extern E_Module_Api e_modapi;