summaryrefslogtreecommitdiff
path: root/src/modules/battery
diff options
context:
space:
mode:
authorCarsten Haitzler <raster@rasterman.com>2008-03-03 09:48:37 +0000
committerCarsten Haitzler <raster@rasterman.com>2008-03-03 09:48:37 +0000
commit16b851a43cf20ee2375584c3d0036c30cd407574 (patch)
tree7152b752e788be57d8bdaf4bca81f1619c594210 /src/modules/battery
parentb5260fd925f5c1c162af5a852f0896fc3904e8a0 (diff)
downloadenlightenment-16b851a43cf20ee2375584c3d0036c30cd407574.tar.gz
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
Diffstat (limited to 'src/modules/battery')
-rw-r--r--src/modules/battery/Makefile.am13
-rw-r--r--src/modules/battery/batget.c1433
-rw-r--r--src/modules/battery/e_mod_main.c1635
-rw-r--r--src/modules/battery/e_mod_main.h41
4 files changed, 1607 insertions, 1515 deletions
diff --git a/src/modules/battery/Makefile.am b/src/modules/battery/Makefile.am
index c278639d19..fdfa2f7cce 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 0000000000..0847b01dd4
--- /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 <sys/types.h>
+# include <sys/sysctl.h>
+# include <fcntl.h>
+# ifdef __i386__
+# include <machine/apm_bios.h>
+# endif
+# include <stdio.h>
+#endif
+#ifdef HAVE_CFBASE_H
+# include <CFBase.h>
+# include <CFNumber.h>
+# include <CFArray.h>
+# include <CFDictionary.h>
+# include <CFRunLoop.h>
+# include <ps/IOPSKeys.h>
+# include <ps/IOPowerSources.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* 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, &currentval);
+ /* 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, &currentval);
+ time_left = currentval * 60;
+ }
+ else
+ {
+ values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey));
+ CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
+ 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 71465fd8b7..74410bfe1a 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 <sys/types.h>
-# include <sys/sysctl.h>
-# include <fcntl.h>
-# ifdef __i386__
-# include <machine/apm_bios.h>
-# endif
-# include <stdio.h>
-#endif
-#ifdef HAVE_CFBASE_H
-#include <CFBase.h>
-#include <CFNumber.h>
-#include <CFArray.h>
-#include <CFDictionary.h>
-#include <CFRunLoop.h>
-#include <ps/IOPSKeys.h>
-#include <ps/IOPowerSources.h>
-#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<br>"
- "Your battery is running low.<br>"
- "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, &currentval);
- /* 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, &currentval);
- /* 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, &currentval);
- /* 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 7cb05f0a1b..d1b4864dbc 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;