10 #include <sys/types.h>
17 # include <sys/ioctl.h>
18 # include <sys/sysctl.h>
20 # include <machine/apm_bios.h>
25 # include <CFNumber.h>
27 # include <CFDictionary.h>
28 # include <CFRunLoop.h>
29 # include <ps/IOPSKeys.h>
30 # include <ps/IOPowerSources.h>
35 #include <Ecore_File.h>
36 #include <Ecore_Con.h>
38 /* define MAX for all OS, instead of plenty #include */
40 # define MAX(a, b) ((a) < (b) ? (b) : (a))
43 /* supported batery system schemes - irrespective of OS */
48 #define CHECK_SYS_CLASS_POWER_SUPPLY 4
52 static void init(void);
53 static Eina_Bool poll_cb(void *data);
55 static int poll_interval = 512;
56 static Ecore_Poller *poller = NULL;
58 static int mode = CHECK_NONE;
60 static int time_left = -2;
61 static int battery_full = -2;
62 static int have_battery = -2;
63 static int have_power = -2;
65 static const char *sys_power_dir = "/sys/class/power_supply";
69 int_file_get(const char *file)
72 FILE *f = fopen(file, "r");
76 char *str = fgets(buf, sizeof(buf), f);
77 if (str) val = atoi(str);
84 str_file_get(const char *file)
87 FILE *f = fopen(file, "r");
91 char *str = fgets(buf, sizeof(buf), f);
94 size_t len = strlen(str);
95 if ((len > 0) && (str[len - 1] == '\n'))
100 val = malloc(len + 1);
101 if (val) memcpy(val, str, len + 1);
109 int_get(const char *buf)
111 const char *p = strchr(buf, ':');
114 while (*p == ' ') p++;
119 str_get(const char *buf)
121 const char *p = strchr(buf, ':');
127 while (*p == ' ') p++;
129 q = p + strlen(p) - 1;
130 while ((q > p) && ((*q == ' ') || (*q == '\n'))) q--;
132 if (q < p) return NULL;
134 ret = malloc(q - p + 1);
135 if (!ret) return NULL;
136 memcpy(ret, p, q - p);
142 file_str_entry_get(FILE *f,
148 tmp = fgets(buf, sizeof(buf), f);
151 EINA_LOG_ERR("unexpected end of file, expected: '%s'", entry);
154 if (strcmp(tmp, entry) != 0)
156 EINA_LOG_ERR("unexpected file entry, expected: '%s'", entry);
162 EINA_LOG_ERR("unexpected file entry, missing value for '%s'", entry);
170 #define BATTERY_STATE_NONE 0
171 #define BATTERY_STATE_DISCHARGING 1
172 #define BATTERY_STATE_CHARGING 2
173 #define BATTERY_STATE_REMOVED 7
202 /* Read some information on first run. */
204 sysctlnametomib("hw.acpi.battery.state", mib_state, &len);
206 if (sysctl(mib_state, 4, &state, &len, NULL, 0) == -1)
211 sysctlnametomib("hw.acpi.battery.life", mib_life, &len);
213 if (sysctl(mib_life, 4, &life, &len, NULL, 0) == -1)
219 sysctlnametomib("hw.acpi.battery.time", mib_time, &len);
221 if (sysctl(mib_time, 4, &time_min, &len, NULL, 0) == -1)
226 sysctlnametomib("hw.acpi.battery.units", mib_units, &len);
227 len = sizeof(batteries);
228 if (sysctl(mib_time, 4, &batteries, &len, NULL, 0) == -1)
232 if (time_min >= 0) time_left = time_min * 60;
234 if (batteries == 1) /* hw.acpi.battery.units = 1 means NO BATTS */
236 else if ((state == BATTERY_STATE_CHARGING) ||
237 (state == BATTERY_STATE_DISCHARGING))
240 if (state == BATTERY_STATE_CHARGING) have_power = 1;
241 else if (state == BATTERY_STATE_DISCHARGING)
243 if (level == -1) time_left = -1;
244 else if (time_min == -1)
247 battery_full = bat_val;
249 else battery_full = bat_val;
271 int ac_stat, bat_stat, bat_val, time_val;
275 struct apm_info info;
282 apm_fd = open("/dev/apm", O_RDONLY);
283 if ((apm_fd != -1) && (ioctl(apm_fd, APMIO_GETINFO, &info) != -1))
286 ac_stat = info.ai_acline;
287 bat_stat = info.ai_batt_stat;
288 bat_val = info.ai_batt_life;
289 time_val = info.ai_batt_time;
293 if (info.ai_batteries == 1) /* ai_batteries == 1 means NO battery,
294 * ai_batteries == 2 means 1 battery */
300 if (ac_stat) /* Wallpowered */
304 switch (bat_stat) /* On FreeBSD the time_val is -1 when AC ist plugged
305 * in. This means we don't know how long the battery
325 else /* Running on battery */
328 battery_full = bat_val;
329 time_left = time_val;
335 #elif defined(HAVE_CFBASE_H) /* OS X */
337 static void darwin_init(void);
338 static void darwin_check(void);
350 int device_num, device_count;
351 int currentval = 0, maxval = 0;
355 CFDictionaryRef device_dict;
362 /* Retrieve the power source data and the array of sources. */
363 blob = IOPSCopyPowerSourcesInfo();
364 sources = IOPSCopyPowerSourcesList(blob);
365 device_count = CFArrayGetCount(sources);
366 for (device_num = 0; device_num < device_count; device_num++)
370 /* Retrieve a dictionary of values for this device and the count of keys in the dictionary. */
371 ps = CFArrayGetValueAtIndex(sources, device_num);
372 device_dict = IOPSGetPowerSourceDescription(blob, ps);
373 /* Retrieve the charging key and save the present charging value if one exists. */
374 if (CFDictionaryGetValueIfPresent(device_dict,
375 CFSTR(kIOPSIsChargingKey), &values))
378 if (CFBooleanGetValue(values) > 0) have_power = 1;
391 /* Retrieve the current capacity key. */
392 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey));
393 CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval);
394 /* Retrieve the max capacity key. */
395 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSMaxCapacityKey));
396 CFNumberGetValue(values, kCFNumberSInt32Type, &maxval);
397 /* Calculate the percentage charged. */
398 battery_full = (currentval * 100) / maxval;
400 /* Retrieve the remaining battery power or time until charged in minutes. */
403 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey));
404 CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval);
405 time_left = currentval * 60;
409 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey));
410 CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval);
411 time_left = currentval * 60;
420 /* new linux power class api to get power info - brand new and this code
421 * may have bugs, but it is a good attempt to get it right */
423 static Eina_Bool linux_sys_class_power_supply_cb_event_fd_active(void *data,
424 Ecore_Fd_Handler *fd_handler);
425 static void linux_sys_class_power_supply_check(void);
427 static void linux_sys_class_power_supply_init(void);
429 typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent;
431 #define BASIS_CHARGE 1
432 #define BASIS_ENERGY 2
433 #define BASIS_VOLTAGE 3
435 struct _Sys_Class_Power_Supply_Uevent
439 Ecore_Fd_Handler *fd_handler;
447 unsigned char have_current_avg : 1;
448 unsigned char have_current_now : 1;
451 static Eina_List *events = NULL;
454 static Ecore_Timer *sys_class_delay_check = NULL;
457 linux_sys_class_power_supply_cb_delay_check(void *data)
459 linux_sys_class_power_supply_init();
461 sys_class_delay_check = NULL;
462 return ECORE_CALLBACK_CANCEL;
465 static Ecore_Timer *re_init_timer = NULL;
468 linux_sys_class_power_supply_cb_re_init(void *data)
470 Sys_Class_Power_Supply_Uevent *sysev;
474 EINA_LIST_FREE(events, sysev)
476 // if (sysev->fd_handler)
477 // ecore_main_fd_handler_del(sysev->fd_handler);
478 // if (sysev->fd >= 0) close(sysev->fd);
483 linux_sys_class_power_supply_init();
484 re_init_timer = NULL;
485 return ECORE_CALLBACK_CANCEL;
489 linux_sys_class_power_supply_cb_event_fd_active(void *data,
490 Ecore_Fd_Handler *fd_handler)
492 Sys_Class_Power_Supply_Uevent *sysev;
495 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
503 if ((num = read(sysev->fd, buf, sizeof(buf))) < 1)
505 lost = ((errno == EIO) ||
516 events = eina_list_remove(events, sysev);
518 // if (sysev->fd_handler)
519 // ecore_main_fd_handler_del(sysev->fd_handler);
520 // if (sysev->fd >= 0) close(sysev->fd);
524 if (re_init_timer) ecore_timer_del(re_init_timer);
525 re_init_timer = ecore_timer_add(1.0, linux_sys_class_power_supply_cb_re_init, NULL);
529 if (sys_class_delay_check) ecore_timer_del(sys_class_delay_check);
530 sys_class_delay_check = ecore_timer_add(0.2, linux_sys_class_power_supply_cb_delay_check, NULL);
533 return ECORE_CALLBACK_CANCEL;
538 linux_sys_class_power_supply_sysev_init(Sys_Class_Power_Supply_Uevent *sysev)
541 const char *dir = sys_power_dir;
544 sysev->have_current_avg = 0;
545 sysev->have_current_now = 0;
547 snprintf(buf, sizeof(buf), "%s/%s/present", dir, sysev->name);
548 sysev->present = int_file_get(buf);
549 if (!sysev->present) return;
551 snprintf(buf, sizeof(buf), "%s/%s/current_avg", dir, sysev->name);
552 if (ecore_file_exists(buf)) sysev->have_current_avg = 1;
553 snprintf(buf, sizeof(buf), "%s/%s/current_now", dir, sysev->name);
554 if (ecore_file_exists(buf)) sysev->have_current_now = 1;
556 snprintf(buf, sizeof(buf), "%s/%s/voltage_max", dir, sysev->name);
557 if (ecore_file_exists(buf)) sysev->basis = BASIS_VOLTAGE;
558 snprintf(buf, sizeof(buf), "%s/%s/voltage_max_design", dir, sysev->name);
559 if (ecore_file_exists(buf)) sysev->basis = BASIS_VOLTAGE;
561 snprintf(buf, sizeof(buf), "%s/%s/energy_full", dir, sysev->name);
562 if (ecore_file_exists(buf)) sysev->basis = BASIS_ENERGY;
563 snprintf(buf, sizeof(buf), "%s/%s/energy_full_design", dir, sysev->name);
564 if (ecore_file_exists(buf)) sysev->basis = BASIS_ENERGY;
566 snprintf(buf, sizeof(buf), "%s/%s/charge_full", dir, sysev->name);
567 if (ecore_file_exists(buf)) sysev->basis = BASIS_CHARGE;
568 snprintf(buf, sizeof(buf), "%s/%s/charge_full_design", dir, sysev->name);
569 if (ecore_file_exists(buf)) sysev->basis = BASIS_CHARGE;
571 if (sysev->basis == BASIS_CHARGE)
573 snprintf(buf, sizeof(buf), "%s/%s/charge_full", dir, sysev->name);
574 sysev->basis_full = int_file_get(buf);
575 snprintf(buf, sizeof(buf), "%s/%s/charge_empty", dir, sysev->name);
576 sysev->basis_empty = int_file_get(buf);
577 if (sysev->basis_full < 0)
579 snprintf(buf, sizeof(buf), "%s/%s/charge_full_design", dir, sysev->name);
580 sysev->basis_full = int_file_get(buf);
582 if (sysev->basis_empty < 0)
584 snprintf(buf, sizeof(buf), "%s/%s/charge_empty_design", dir, sysev->name);
585 sysev->basis_empty = int_file_get(buf);
588 else if (sysev->basis == BASIS_ENERGY)
590 snprintf(buf, sizeof(buf), "%s/%s/energy_full", dir, sysev->name);
591 sysev->basis_full = int_file_get(buf);
592 snprintf(buf, sizeof(buf), "%s/%s/energy_empty", dir, sysev->name);
593 sysev->basis_empty = int_file_get(buf);
594 if (sysev->basis_full < 0)
596 snprintf(buf, sizeof(buf), "%s/%s/energy_full_design", dir, sysev->name);
597 sysev->basis_full = int_file_get(buf);
599 if (sysev->basis_empty < 0)
601 snprintf(buf, sizeof(buf), "%s/%s/energy_empty_design", dir, sysev->name);
602 sysev->basis_empty = int_file_get(buf);
605 else if (sysev->basis == BASIS_VOLTAGE)
607 snprintf(buf, sizeof(buf), "%s/%s/voltage_max", dir, sysev->name);
608 sysev->basis_full = int_file_get(buf);
609 snprintf(buf, sizeof(buf), "%s/%s/voltage_min", dir, sysev->name);
610 sysev->basis_empty = int_file_get(buf);
611 if (sysev->basis_full < 0)
613 snprintf(buf, sizeof(buf), "%s/%s/voltage_max_design", dir, sysev->name);
614 sysev->basis_full = int_file_get(buf);
616 if (sysev->basis_empty < 0)
618 snprintf(buf, sizeof(buf), "%s/%s/voltage_min_design", dir, sysev->name);
619 sysev->basis_empty = int_file_get(buf);
625 linux_sys_class_power_supply_is_battery(char *name)
630 const char *dir = sys_power_dir;
632 snprintf(buf, sizeof(buf), "%s/%s/type", dir, name);
633 fd = open(buf, O_RDONLY);
639 else if (read(fd, buf, sizeof(buf)) < 1)
641 else if (!strncmp(buf, "Battery", 7))
651 linux_sys_class_power_supply_init(void)
657 Sys_Class_Power_Supply_Uevent *sysev;
659 EINA_LIST_FOREACH(events, l, sysev)
660 linux_sys_class_power_supply_sysev_init(sysev);
668 bats = ecore_file_ls("/sys/class/power_supply/");
669 // bats = ecore_file_ls("./TST");
674 EINA_LIST_FREE(bats, name)
676 Sys_Class_Power_Supply_Uevent *sysev;
678 if (!(linux_sys_class_power_supply_is_battery(name)))
684 sysev = (Sys_Class_Power_Supply_Uevent *)calloc(1, sizeof(Sys_Class_Power_Supply_Uevent));
686 // snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/uevent", name);
687 // sysev->fd = open(buf, O_RDONLY);
688 // if (sysev->fd >= 0)
689 // sysev->fd_handler = ecore_main_fd_handler_add(sysev->fd,
691 // linux_sys_class_power_supply_cb_event_fd_active,
694 events = eina_list_append(events, sysev);
695 linux_sys_class_power_supply_sysev_init(sysev);
702 linux_sys_class_power_supply_check(void)
707 const char *dir = sys_power_dir;
716 Sys_Class_Power_Supply_Uevent *sysev;
724 EINA_LIST_FOREACH(events, l, sysev)
731 int time_to_full = -1;
732 int time_to_empty = -1;
741 /* fetch more generic info */
743 present = sysev->present;
744 if (!present) continue;
746 snprintf(buf, sizeof(buf), "%s/%s/capacity", dir, name);
747 capacity = int_file_get(buf);
748 if (sysev->have_current_avg)
750 snprintf(buf, sizeof(buf), "%s/%s/current_avg", dir, name);
751 current = int_file_get(buf);
753 else if (sysev->have_current_now)
755 snprintf(buf, sizeof(buf), "%s/%s/current_now", dir, name);
756 current = int_file_get(buf);
759 /* FIXME: do we get a uevent on going from charging to full?
760 * if so, move this to init */
761 snprintf(buf, sizeof(buf), "%s/%s/status", dir, name);
762 tmp = str_file_get(buf);
766 if (!strncasecmp("discharging", tmp, 11)) charging = 0;
767 else if (!strncasecmp("unknown", tmp, 7))
769 else if (!strncasecmp("not charging", tmp, 12))
771 else if (!strncasecmp("charging", tmp, 8))
773 else if (!strncasecmp("full", tmp, 4))
780 /* some batteries can/will/want to predict how long they will
781 * last. if so - take what the battery says. too bad if it's
782 * wrong. that's a buggy battery or driver */
788 snprintf(buf, sizeof(buf), "%s/%s/time_to_full_now", dir, name);
789 time_to_full = int_file_get(buf);
793 snprintf(buf, sizeof(buf), "%s/%s/time_to_empty_now", dir, name);
794 time_to_empty = int_file_get(buf);
798 /* now get charge, energy and voltage. take the one that provides
799 * the best info (charge first, then energy, then voltage */
800 if (sysev->basis == BASIS_CHARGE)
801 snprintf(buf, sizeof(buf), "%s/%s/charge_now", dir, name);
802 else if (sysev->basis == BASIS_ENERGY)
803 snprintf(buf, sizeof(buf), "%s/%s/energy_now", dir, name);
804 else if (sysev->basis == BASIS_VOLTAGE)
805 snprintf(buf, sizeof(buf), "%s/%s/voltage_now", dir, name);
806 pwr_now = int_file_get(buf);
807 pwr_empty = sysev->basis_empty;
808 pwr_full = sysev->basis_full;
809 if ((sysev->basis == BASIS_VOLTAGE) &&
812 /* if we use voltage as basis.. we're not very accurate
813 * so we should prefer capacity readings */
819 if (pwr_empty < 0) pwr_empty = 0;
821 if ((pwr_full > 0) && (pwr_full > pwr_empty))
823 if (full) pwr_now = pwr_full;
827 pwr_now = (((long long)capacity * ((long long)pwr_full - (long long)pwr_empty)) / 100) + pwr_empty;
830 if (sysev->present) have_battery = 1;
835 if (time_to_full >= 0)
837 if (time_to_full > time_left)
838 time_left = time_to_full;
842 if (current == 0) time_left = 0;
843 else if (current < 0)
847 pwr = (((long long)pwr_full - (long long)pwr_now) * 3600) / -current;
848 if (pwr > time_left) time_left = pwr;
855 if (time_to_empty >= 0) time_left += time_to_empty;
858 if (time_to_empty < 0)
862 pwr = (((long long)pwr_now - (long long)pwr_empty) * 3600) / current;
868 total_pwr_now += pwr_now - pwr_empty;
869 total_pwr_max += pwr_full - pwr_empty;
871 /* simple current battery fallback */
874 if (sysev->present) have_battery = 1;
875 if (charging) have_power = 1;
877 total_pwr_now = capacity;
878 if (total_pwr_now < 100) nofull = 1;
881 if (total_pwr_max > 0)
882 battery_full = ((long long)total_pwr_now * 100) / total_pwr_max;
889 /* "here and now" ACPI based power checking. is there for linux and most
890 * modern laptops. as of linux 2.6.24 it is replaced with
891 * linux_sys_class_power_supply_init/check() though as this is the new
892 * power class api to poll for power stuff
894 static Eina_Bool linux_acpi_cb_acpid_add(void *data,
897 static Eina_Bool linux_acpi_cb_acpid_del(void *data,
900 static Eina_Bool linux_acpi_cb_acpid_data(void *data,
903 static void linux_acpi_init(void);
904 static void linux_acpi_check(void);
906 static int acpi_max_full = -1;
907 static int acpi_max_design = -1;
908 static Ecore_Con_Server *acpid = NULL;
909 static Ecore_Event_Handler *acpid_handler_add = NULL;
910 static Ecore_Event_Handler *acpid_handler_del = NULL;
911 static Ecore_Event_Handler *acpid_handler_data = NULL;
912 static Ecore_Timer *delay_check = NULL;
913 static int event_fd = -1;
914 static Ecore_Fd_Handler *event_fd_handler = NULL;
917 linux_acpi_cb_delay_check(void *data __UNUSED__)
922 return ECORE_CALLBACK_CANCEL;
926 linux_acpi_cb_acpid_add(void *data __UNUSED__,
928 void *event __UNUSED__)
930 return ECORE_CALLBACK_PASS_ON;
934 linux_acpi_cb_acpid_del(void *data __UNUSED__,
936 void *event __UNUSED__)
938 ecore_con_server_del(acpid);
940 if (acpid_handler_add) ecore_event_handler_del(acpid_handler_add);
941 acpid_handler_add = NULL;
942 if (acpid_handler_del) ecore_event_handler_del(acpid_handler_del);
943 acpid_handler_del = NULL;
944 if (acpid_handler_data) ecore_event_handler_del(acpid_handler_data);
945 acpid_handler_data = NULL;
946 return ECORE_CALLBACK_PASS_ON;
950 linux_acpi_cb_acpid_data(void *data __UNUSED__,
952 void *event __UNUSED__)
954 if (delay_check) ecore_timer_del(delay_check);
955 delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL);
956 return ECORE_CALLBACK_PASS_ON;
960 linux_acpi_cb_event_fd_active(void *data __UNUSED__,
961 Ecore_Fd_Handler *fd_handler)
963 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
971 if ((num = read(event_fd, buf, sizeof(buf))) < 1)
973 lost = ((errno == EIO) ||
983 ecore_main_fd_handler_del(event_fd_handler);
984 event_fd_handler = NULL;
990 if (delay_check) ecore_timer_del(delay_check);
991 delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL);
994 return ECORE_CALLBACK_RENEW;
998 linux_acpi_init(void)
1003 bats = ecore_file_ls("/proc/acpi/battery");
1009 powers = ecore_file_ls("/proc/acpi/ac_adapter");
1014 EINA_LIST_FREE(powers, name)
1019 snprintf(buf, sizeof(buf), "/proc/acpi/ac_adapter/%s/state", name);
1020 f = fopen(buf, "r");
1026 tmp = fgets(buf, sizeof(buf), f);
1027 if (tmp) tmp = str_get(tmp);
1030 if (!strcmp(tmp, "on-line")) have_power = 1;
1041 acpi_max_design = 0;
1042 EINA_LIST_FREE(bats, name)
1047 snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/info", name);
1048 f = fopen(buf, "r");
1054 tmp = fgets(buf, sizeof(buf), f);
1055 if (tmp) tmp = str_get(tmp);
1058 if (!strcmp(tmp, "yes")) have_battery = 1;
1062 tmp = fgets(buf, sizeof(buf), f);
1063 if (tmp) tmp = str_get(tmp);
1066 if (strcmp(tmp, "unknown")) acpi_max_design += atoi(tmp);
1070 tmp = fgets(buf, sizeof(buf), f);
1071 if (tmp) tmp = str_get(tmp);
1074 if (strcmp(tmp, "unknown")) acpi_max_full += atoi(tmp);
1085 acpid = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM,
1086 "/var/run/acpid.socket", -1, NULL);
1089 acpid_handler_add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
1090 linux_acpi_cb_acpid_add, NULL);
1091 acpid_handler_del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
1092 linux_acpi_cb_acpid_del, NULL);
1093 acpid_handler_data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
1094 linux_acpi_cb_acpid_data, NULL);
1100 event_fd = open("/proc/acpi/event", O_RDONLY);
1102 event_fd_handler = ecore_main_fd_handler_add(event_fd,
1104 linux_acpi_cb_event_fd_active,
1113 linux_acpi_check(void)
1122 bats = ecore_file_ls("/proc/acpi/battery");
1129 EINA_LIST_FREE(bats, name)
1135 snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name);
1137 f = fopen(buf, "r");
1140 tmp = file_str_entry_get(f, "present:");
1141 if (!tmp) goto fclose_and_continue;
1142 if (!strcasecmp(tmp, "yes")) have_battery = 1;
1145 tmp = file_str_entry_get(f, "capacity state:");
1146 if (!tmp) goto fclose_and_continue;
1149 tmp = file_str_entry_get(f, "charging state:");
1150 if (!tmp) goto fclose_and_continue;
1151 if ((have_power == 0) && (!strcasecmp(tmp, "charging")))
1155 tmp = file_str_entry_get(f, "present rate:");
1156 if (!tmp) goto fclose_and_continue;
1157 if (strcasecmp(tmp, "unknown")) rate += atoi(tmp);
1160 tmp = file_str_entry_get(f, "remaining capacity:");
1161 if (!tmp) goto fclose_and_continue;
1162 if (strcasecmp(tmp, "unknown")) capacity += atoi(tmp);
1165 fclose_and_continue:
1169 if (acpi_max_full > 0)
1170 battery_full = 100 * (long long)capacity / acpi_max_full;
1171 else if (acpi_max_design > 0)
1172 battery_full = 100 * (long long)capacity / acpi_max_design;
1175 if (rate <= 0) time_left = -1;
1179 time_left = (3600 * ((long long)acpi_max_full - (long long)capacity)) / rate;
1181 time_left = (3600 * (long long)capacity) / rate;
1187 /* old school apm support - very old laptops and some devices support this.
1188 * this is here for legacy support and i wouldn't suggest spending any
1189 * effort on it as it is complete below as best i know, but could have missed
1190 * one or 2 things, but not worth fixing */
1191 static void linux_apm_init(void);
1192 static void linux_apm_check(void);
1195 linux_apm_init(void)
1201 linux_apm_check(void)
1204 char s1[32], s2[32], s3[32], *endptr;
1205 int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val;
1212 f = fopen("/proc/apm", "r");
1215 if (fscanf(f, "%*s %*s %x %x %x %x %31s %31s %31s",
1216 &apm_flags, &ac_stat, &bat_stat, &bat_flags, s1, s2, s3) != 7)
1223 bat_val = strtol(s1, &endptr, 10);
1224 if (*endptr != '%') return;
1226 if (!strcmp(s3, "sec")) time_val = atoi(s2);
1227 else if (!strcmp(s3, "min"))
1228 time_val = atoi(s2) * 60;
1231 if ((bat_flags != 0xff) && (bat_flags & 0x80))
1243 have_power = ac_stat;
1244 battery_full = bat_val;
1245 if (battery_full > 100) battery_full = 100;
1246 if (ac_stat == 1) time_left = -1;
1247 else time_left = time_val;
1255 have_power = ac_stat;
1260 case 1: /* medium */
1262 have_power = ac_stat;
1269 have_power = ac_stat;
1274 case 3: /* charging */
1276 have_power = ac_stat;
1285 /* for older mac powerbooks. legacy as well like linux_apm_init/check. leave
1286 * it alone unless you have to touch it */
1287 static void linux_pmu_init(void);
1288 static void linux_pmu_check(void);
1291 linux_pmu_init(void)
1297 linux_pmu_check(void)
1310 f = fopen("/proc/pmu/info", "r");
1315 tmp = fgets(buf, sizeof(buf), f);
1318 EINA_LOG_ERR("no driver info in /proc/pmu/info");
1319 goto fclose_and_continue;
1322 tmp = fgets(buf, sizeof(buf), f);
1325 EINA_LOG_ERR("no firmware info in /proc/pmu/info");
1326 goto fclose_and_continue;
1329 tmp = fgets(buf, sizeof(buf), f);
1332 EINA_LOG_ERR("no AC info in /proc/pmu/info");
1333 goto fclose_and_continue;
1336 fclose_and_continue:
1339 bats = ecore_file_ls("/proc/pmu");
1344 EINA_LIST_FREE(bats, name)
1346 if (strncmp(name, "battery", 7)) continue;
1347 snprintf(buf, sizeof(buf), "/proc/pmu/%s", name);
1348 f = fopen(buf, "r");
1354 while (fgets(buf, sizeof (buf), f))
1358 if ((token = strtok(buf, ":")))
1360 if (!strncmp("charge", token, 6))
1361 charge = atoi(strtok(0, ": "));
1362 else if (!strncmp("max_charge", token, 9))
1363 max_charge = atoi(strtok(0, ": "));
1364 else if (!strncmp("current", token, 7))
1365 current = atoi(strtok(0, ": "));
1366 else if (!strncmp("time rem", token, 8))
1367 timeleft = atoi(strtok(0, ": "));
1372 curmax += max_charge;
1373 curcharge += charge;
1377 /* Neither charging nor discharging */
1381 /* When on dc, we are discharging */
1382 seconds += timeleft;
1386 /* Charging - works in parallel */
1387 seconds = MAX(timeleft, seconds);
1393 if (max_charge > 0) battery_full = ((long long)charge * 100) / max_charge;
1394 else battery_full = 0;
1395 time_left = seconds;
1409 dir_has_contents(const char *dir)
1415 bats = ecore_file_ls(dir);
1417 count = eina_list_count(bats);
1418 EINA_LIST_FREE(bats, file)
1420 if (count > 0) return 1;
1431 len = sizeof(acline);
1432 if (!sysctlbyname("hw.acpi.acline", &acline, &len, NULL, 0))
1434 int acline_mib[3] = {-1};
1437 if (!sysctlnametomib("hw.acpi.acline", acline_mib, &len))
1446 if (ecore_file_exists("/dev/apm"))
1453 #elif defined(HAVE_CFBASE_H) /* OS X */
1456 if ((ecore_file_is_dir(sys_power_dir)) && (dir_has_contents(sys_power_dir)))
1458 mode = CHECK_SYS_CLASS_POWER_SUPPLY;
1459 linux_sys_class_power_supply_init();
1461 else if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */
1466 else if (ecore_file_exists("/proc/apm"))
1471 else if (ecore_file_is_dir("/proc/pmu"))
1480 poll_cb(void *data __UNUSED__)
1487 ptime_left = time_left;
1488 pbattery_full = battery_full;
1489 phave_battery = have_battery;
1490 phave_power = have_power;
1512 #elif defined(HAVE_CFBASE_H) /* OS X */
1514 return ECORE_CALLBACK_RENEW;
1530 case CHECK_SYS_CLASS_POWER_SUPPLY:
1531 linux_sys_class_power_supply_check();
1542 if ((ptime_left != time_left) ||
1543 (pbattery_full != battery_full) ||
1544 (phave_battery != have_battery) ||
1545 (phave_power != have_power))
1547 if ((time_left < 0) &&
1548 ((have_battery) && (battery_full < 0)))
1551 printf("%i %i %i %i %i\n",
1552 battery_full, time_left, time_left, have_battery, have_power);
1555 return ECORE_CALLBACK_RENEW;
1564 printf("ARGS INCORRECT!\n");
1567 poll_interval = atoi(argv[1]);
1574 poller = ecore_poller_add(ECORE_POLLER_CORE, poll_interval, poll_cb, NULL);
1577 ecore_main_loop_begin();
1579 ecore_con_shutdown();
1580 ecore_file_shutdown();