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, ':');
120 str_get(const char *buf)
122 const char *p = strchr(buf, ':');
131 q = p + strlen(p) - 1;
132 while ((q > p) && ((*q == ' ') || (*q == '\n')))
135 if (q < p) return NULL;
137 ret = malloc(q - p + 1);
138 if (!ret) return NULL;
139 memcpy(ret, p, q - p);
145 file_str_entry_get(FILE *f,
151 tmp = fgets(buf, sizeof(buf), f);
154 EINA_LOG_ERR("unexpected end of file, expected: '%s'", entry);
157 if (strcmp(tmp, entry) != 0)
159 EINA_LOG_ERR("unexpected file entry, expected: '%s'", entry);
165 EINA_LOG_ERR("unexpected file entry, missing value for '%s'", entry);
173 #define BATTERY_STATE_NONE 0
174 #define BATTERY_STATE_DISCHARGING 1
175 #define BATTERY_STATE_CHARGING 2
176 #define BATTERY_STATE_REMOVED 7
205 /* Read some information on first run. */
207 sysctlnametomib("hw.acpi.battery.state", mib_state, &len);
209 if (sysctl(mib_state, 4, &state, &len, NULL, 0) == -1)
214 sysctlnametomib("hw.acpi.battery.life", mib_life, &len);
216 if (sysctl(mib_life, 4, &life, &len, NULL, 0) == -1)
222 sysctlnametomib("hw.acpi.battery.time", mib_time, &len);
224 if (sysctl(mib_time, 4, &time_min, &len, NULL, 0) == -1)
229 sysctlnametomib("hw.acpi.battery.units", mib_units, &len);
230 len = sizeof(batteries);
231 if (sysctl(mib_time, 4, &batteries, &len, NULL, 0) == -1)
235 if (time_min >= 0) time_left = time_min * 60;
237 if (batteries == 1) /* hw.acpi.battery.units = 1 means NO BATTS */
239 else if ((state == BATTERY_STATE_CHARGING) ||
240 (state == BATTERY_STATE_DISCHARGING))
243 if (state == BATTERY_STATE_CHARGING) have_power = 1;
244 else if (state == BATTERY_STATE_DISCHARGING)
246 if (level == -1) time_left = -1;
247 else if (time_min == -1)
250 battery_full = bat_val;
252 else battery_full = bat_val;
274 int ac_stat, bat_stat, bat_val, time_val;
278 struct apm_info info;
285 apm_fd = open("/dev/apm", O_RDONLY);
286 if ((apm_fd != -1) && (ioctl(apm_fd, APMIO_GETINFO, &info) != -1))
289 ac_stat = info.ai_acline;
290 bat_stat = info.ai_batt_stat;
291 bat_val = info.ai_batt_life;
292 time_val = info.ai_batt_time;
296 if (apm_fd != -1) close(apm_fd);
301 if (info.ai_batteries == 1) /* ai_batteries == 1 means NO battery,
302 * ai_batteries == 2 means 1 battery */
308 if (ac_stat) /* Wallpowered */
312 switch (bat_stat) /* On FreeBSD the time_val is -1 when AC ist plugged
313 * in. This means we don't know how long the battery
333 else /* Running on battery */
336 battery_full = bat_val;
337 time_left = time_val;
343 #elif defined(HAVE_CFBASE_H) /* OS X */
345 static void darwin_init(void);
346 static void darwin_check(void);
358 int device_num, device_count;
359 int currentval = 0, maxval = 0;
363 CFDictionaryRef device_dict;
370 /* Retrieve the power source data and the array of sources. */
371 blob = IOPSCopyPowerSourcesInfo();
372 sources = IOPSCopyPowerSourcesList(blob);
373 device_count = CFArrayGetCount(sources);
374 for (device_num = 0; device_num < device_count; device_num++)
378 /* Retrieve a dictionary of values for this device and the count of keys in the dictionary. */
379 ps = CFArrayGetValueAtIndex(sources, device_num);
380 device_dict = IOPSGetPowerSourceDescription(blob, ps);
381 /* Retrieve the charging key and save the present charging value if one exists. */
382 if (CFDictionaryGetValueIfPresent(device_dict,
383 CFSTR(kIOPSIsChargingKey), &values))
386 if (CFBooleanGetValue(values) > 0) have_power = 1;
399 /* Retrieve the current capacity key. */
400 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey));
401 CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval);
402 /* Retrieve the max capacity key. */
403 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSMaxCapacityKey));
404 CFNumberGetValue(values, kCFNumberSInt32Type, &maxval);
405 /* Calculate the percentage charged. */
406 battery_full = (currentval * 100) / maxval;
408 /* Retrieve the remaining battery power or time until charged in minutes. */
411 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey));
412 CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval);
413 time_left = currentval * 60;
417 values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey));
418 CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval);
419 time_left = currentval * 60;
428 /* new linux power class api to get power info - brand new and this code
429 * may have bugs, but it is a good attempt to get it right */
431 static Eina_Bool linux_sys_class_power_supply_cb_event_fd_active(void *data,
432 Ecore_Fd_Handler *fd_handler);
433 static void linux_sys_class_power_supply_check(void);
435 static void linux_sys_class_power_supply_init(void);
437 typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent;
439 #define BASIS_CHARGE 1
440 #define BASIS_ENERGY 2
441 #define BASIS_VOLTAGE 3
443 struct _Sys_Class_Power_Supply_Uevent
447 Ecore_Fd_Handler *fd_handler;
455 unsigned char have_current_avg : 1;
456 unsigned char have_current_now : 1;
459 static Eina_List *events = NULL;
462 static Ecore_Timer *sys_class_delay_check = NULL;
465 linux_sys_class_power_supply_cb_delay_check(void *data)
467 linux_sys_class_power_supply_init();
469 sys_class_delay_check = NULL;
470 return ECORE_CALLBACK_CANCEL;
473 static Ecore_Timer *re_init_timer = NULL;
476 linux_sys_class_power_supply_cb_re_init(void *data)
478 Sys_Class_Power_Supply_Uevent *sysev;
482 EINA_LIST_FREE(events, sysev)
484 // if (sysev->fd_handler)
485 // ecore_main_fd_handler_del(sysev->fd_handler);
486 // if (sysev->fd >= 0) close(sysev->fd);
491 linux_sys_class_power_supply_init();
492 re_init_timer = NULL;
493 return ECORE_CALLBACK_CANCEL;
497 linux_sys_class_power_supply_cb_event_fd_active(void *data,
498 Ecore_Fd_Handler *fd_handler)
500 Sys_Class_Power_Supply_Uevent *sysev;
503 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
511 if ((num = read(sysev->fd, buf, sizeof(buf))) < 1)
513 lost = ((errno == EIO) ||
524 events = eina_list_remove(events, sysev);
526 // if (sysev->fd_handler)
527 // ecore_main_fd_handler_del(sysev->fd_handler);
528 // if (sysev->fd >= 0) close(sysev->fd);
532 if (re_init_timer) ecore_timer_del(re_init_timer);
533 re_init_timer = ecore_timer_add(1.0, linux_sys_class_power_supply_cb_re_init, NULL);
537 if (sys_class_delay_check) ecore_timer_del(sys_class_delay_check);
538 sys_class_delay_check = ecore_timer_add(0.2, linux_sys_class_power_supply_cb_delay_check, NULL);
541 return ECORE_CALLBACK_CANCEL;
546 linux_sys_class_power_supply_sysev_init(Sys_Class_Power_Supply_Uevent *sysev)
549 const char *dir = sys_power_dir;
552 sysev->have_current_avg = 0;
553 sysev->have_current_now = 0;
555 snprintf(buf, sizeof(buf), "%s/%s/present", dir, sysev->name);
556 sysev->present = int_file_get(buf);
557 if (!sysev->present) return;
559 snprintf(buf, sizeof(buf), "%s/%s/current_avg", dir, sysev->name);
560 if (ecore_file_exists(buf)) sysev->have_current_avg = 1;
561 snprintf(buf, sizeof(buf), "%s/%s/current_now", dir, sysev->name);
562 if (ecore_file_exists(buf)) sysev->have_current_now = 1;
564 snprintf(buf, sizeof(buf), "%s/%s/voltage_max", dir, sysev->name);
565 if (ecore_file_exists(buf)) sysev->basis = BASIS_VOLTAGE;
566 snprintf(buf, sizeof(buf), "%s/%s/voltage_max_design", dir, sysev->name);
567 if (ecore_file_exists(buf)) sysev->basis = BASIS_VOLTAGE;
569 snprintf(buf, sizeof(buf), "%s/%s/energy_full", dir, sysev->name);
570 if (ecore_file_exists(buf)) sysev->basis = BASIS_ENERGY;
571 snprintf(buf, sizeof(buf), "%s/%s/energy_full_design", dir, sysev->name);
572 if (ecore_file_exists(buf)) sysev->basis = BASIS_ENERGY;
574 snprintf(buf, sizeof(buf), "%s/%s/charge_full", dir, sysev->name);
575 if (ecore_file_exists(buf)) sysev->basis = BASIS_CHARGE;
576 snprintf(buf, sizeof(buf), "%s/%s/charge_full_design", dir, sysev->name);
577 if (ecore_file_exists(buf)) sysev->basis = BASIS_CHARGE;
579 if (sysev->basis == BASIS_CHARGE)
581 snprintf(buf, sizeof(buf), "%s/%s/charge_full", dir, sysev->name);
582 sysev->basis_full = int_file_get(buf);
583 snprintf(buf, sizeof(buf), "%s/%s/charge_empty", dir, sysev->name);
584 sysev->basis_empty = int_file_get(buf);
585 if (sysev->basis_full < 0)
587 snprintf(buf, sizeof(buf), "%s/%s/charge_full_design", dir, sysev->name);
588 sysev->basis_full = int_file_get(buf);
590 if (sysev->basis_empty < 0)
592 snprintf(buf, sizeof(buf), "%s/%s/charge_empty_design", dir, sysev->name);
593 sysev->basis_empty = int_file_get(buf);
596 else if (sysev->basis == BASIS_ENERGY)
598 snprintf(buf, sizeof(buf), "%s/%s/energy_full", dir, sysev->name);
599 sysev->basis_full = int_file_get(buf);
600 snprintf(buf, sizeof(buf), "%s/%s/energy_empty", dir, sysev->name);
601 sysev->basis_empty = int_file_get(buf);
602 if (sysev->basis_full < 0)
604 snprintf(buf, sizeof(buf), "%s/%s/energy_full_design", dir, sysev->name);
605 sysev->basis_full = int_file_get(buf);
607 if (sysev->basis_empty < 0)
609 snprintf(buf, sizeof(buf), "%s/%s/energy_empty_design", dir, sysev->name);
610 sysev->basis_empty = int_file_get(buf);
613 else if (sysev->basis == BASIS_VOLTAGE)
615 snprintf(buf, sizeof(buf), "%s/%s/voltage_max", dir, sysev->name);
616 sysev->basis_full = int_file_get(buf);
617 snprintf(buf, sizeof(buf), "%s/%s/voltage_min", dir, sysev->name);
618 sysev->basis_empty = int_file_get(buf);
619 if (sysev->basis_full < 0)
621 snprintf(buf, sizeof(buf), "%s/%s/voltage_max_design", dir, sysev->name);
622 sysev->basis_full = int_file_get(buf);
624 if (sysev->basis_empty < 0)
626 snprintf(buf, sizeof(buf), "%s/%s/voltage_min_design", dir, sysev->name);
627 sysev->basis_empty = int_file_get(buf);
633 linux_sys_class_power_supply_is_battery(char *name)
638 const char *dir = sys_power_dir;
640 snprintf(buf, sizeof(buf), "%s/%s/type", dir, name);
641 fd = open(buf, O_RDONLY);
647 else if (read(fd, buf, sizeof(buf)) < 1)
649 else if (!strncmp(buf, "Battery", 7))
659 linux_sys_class_power_supply_init(void)
665 Sys_Class_Power_Supply_Uevent *sysev;
667 EINA_LIST_FOREACH(events, l, sysev)
668 linux_sys_class_power_supply_sysev_init(sysev);
676 bats = ecore_file_ls("/sys/class/power_supply/");
677 // bats = ecore_file_ls("./TST");
682 EINA_LIST_FREE(bats, name)
684 Sys_Class_Power_Supply_Uevent *sysev;
686 if (!(linux_sys_class_power_supply_is_battery(name)))
692 sysev = (Sys_Class_Power_Supply_Uevent *)calloc(1, sizeof(Sys_Class_Power_Supply_Uevent));
694 // snprintf(buf, sizeof(buf), "/sys/class/power_supply/%s/uevent", name);
695 // sysev->fd = open(buf, O_RDONLY);
696 // if (sysev->fd >= 0)
697 // sysev->fd_handler = ecore_main_fd_handler_add(sysev->fd,
699 // linux_sys_class_power_supply_cb_event_fd_active,
702 events = eina_list_append(events, sysev);
703 linux_sys_class_power_supply_sysev_init(sysev);
710 linux_sys_class_power_supply_check(void)
715 const char *dir = sys_power_dir;
724 Sys_Class_Power_Supply_Uevent *sysev;
732 EINA_LIST_FOREACH(events, l, sysev)
739 int time_to_full = -1;
740 int time_to_empty = -1;
749 /* fetch more generic info */
751 present = sysev->present;
752 if (!present) continue;
754 snprintf(buf, sizeof(buf), "%s/%s/capacity", dir, name);
755 capacity = int_file_get(buf);
756 if (sysev->have_current_avg)
758 snprintf(buf, sizeof(buf), "%s/%s/current_avg", dir, name);
759 current = int_file_get(buf);
761 else if (sysev->have_current_now)
763 snprintf(buf, sizeof(buf), "%s/%s/current_now", dir, name);
764 current = int_file_get(buf);
767 /* FIXME: do we get a uevent on going from charging to full?
768 * if so, move this to init */
769 snprintf(buf, sizeof(buf), "%s/%s/status", dir, name);
770 tmp = str_file_get(buf);
774 if (!strncasecmp("discharging", tmp, 11)) charging = 0;
775 else if (!strncasecmp("unknown", tmp, 7))
777 else if (!strncasecmp("not charging", tmp, 12))
779 else if (!strncasecmp("charging", tmp, 8))
781 else if (!strncasecmp("full", tmp, 4))
788 /* some batteries can/will/want to predict how long they will
789 * last. if so - take what the battery says. too bad if it's
790 * wrong. that's a buggy battery or driver */
796 snprintf(buf, sizeof(buf), "%s/%s/time_to_full_now", dir, name);
797 time_to_full = int_file_get(buf);
801 snprintf(buf, sizeof(buf), "%s/%s/time_to_empty_now", dir, name);
802 time_to_empty = int_file_get(buf);
806 /* now get charge, energy and voltage. take the one that provides
807 * the best info (charge first, then energy, then voltage */
808 if (sysev->basis == BASIS_CHARGE)
809 snprintf(buf, sizeof(buf), "%s/%s/charge_now", dir, name);
810 else if (sysev->basis == BASIS_ENERGY)
811 snprintf(buf, sizeof(buf), "%s/%s/energy_now", dir, name);
812 else if (sysev->basis == BASIS_VOLTAGE)
813 snprintf(buf, sizeof(buf), "%s/%s/voltage_now", dir, name);
814 pwr_now = int_file_get(buf);
815 pwr_empty = sysev->basis_empty;
816 pwr_full = sysev->basis_full;
817 if ((sysev->basis == BASIS_VOLTAGE) &&
820 /* if we use voltage as basis.. we're not very accurate
821 * so we should prefer capacity readings */
827 if (pwr_empty < 0) pwr_empty = 0;
829 if ((pwr_full > 0) && (pwr_full > pwr_empty))
831 if (full) pwr_now = pwr_full;
835 pwr_now = (((long long)capacity * ((long long)pwr_full - (long long)pwr_empty)) / 100) + pwr_empty;
838 if (sysev->present) have_battery = 1;
843 if (time_to_full >= 0)
845 if (time_to_full > time_left)
846 time_left = time_to_full;
850 if (current == 0) time_left = 0;
851 else if (current < 0)
855 pwr = (((long long)pwr_full - (long long)pwr_now) * 3600) / -current;
856 if (pwr > time_left) time_left = pwr;
863 if (time_to_empty >= 0) time_left += time_to_empty;
866 if (time_to_empty < 0)
870 pwr = (((long long)pwr_now - (long long)pwr_empty) * 3600) / current;
876 total_pwr_now += pwr_now - pwr_empty;
877 total_pwr_max += pwr_full - pwr_empty;
879 /* simple current battery fallback */
882 if (sysev->present) have_battery = 1;
883 if (charging) have_power = 1;
885 total_pwr_now = capacity;
886 if (total_pwr_now < 100) nofull = 1;
889 if (total_pwr_max > 0)
890 battery_full = ((long long)total_pwr_now * 100) / total_pwr_max;
897 /* "here and now" ACPI based power checking. is there for linux and most
898 * modern laptops. as of linux 2.6.24 it is replaced with
899 * linux_sys_class_power_supply_init/check() though as this is the new
900 * power class api to poll for power stuff
902 static Eina_Bool linux_acpi_cb_acpid_add(void *data,
905 static Eina_Bool linux_acpi_cb_acpid_del(void *data,
908 static Eina_Bool linux_acpi_cb_acpid_data(void *data,
911 static void linux_acpi_init(void);
912 static void linux_acpi_check(void);
914 static int acpi_max_full = -1;
915 static int acpi_max_design = -1;
916 static Ecore_Con_Server *acpid = NULL;
917 static Ecore_Event_Handler *acpid_handler_add = NULL;
918 static Ecore_Event_Handler *acpid_handler_del = NULL;
919 static Ecore_Event_Handler *acpid_handler_data = NULL;
920 static Ecore_Timer *delay_check = NULL;
921 static int event_fd = -1;
922 static Ecore_Fd_Handler *event_fd_handler = NULL;
925 linux_acpi_cb_delay_check(void *data __UNUSED__)
930 return ECORE_CALLBACK_CANCEL;
934 linux_acpi_cb_acpid_add(void *data __UNUSED__,
936 void *event __UNUSED__)
938 return ECORE_CALLBACK_PASS_ON;
942 linux_acpi_cb_acpid_del(void *data __UNUSED__,
944 void *event __UNUSED__)
946 ecore_con_server_del(acpid);
948 if (acpid_handler_add) ecore_event_handler_del(acpid_handler_add);
949 acpid_handler_add = NULL;
950 if (acpid_handler_del) ecore_event_handler_del(acpid_handler_del);
951 acpid_handler_del = NULL;
952 if (acpid_handler_data) ecore_event_handler_del(acpid_handler_data);
953 acpid_handler_data = NULL;
954 return ECORE_CALLBACK_PASS_ON;
958 linux_acpi_cb_acpid_data(void *data __UNUSED__,
960 void *event __UNUSED__)
962 if (delay_check) ecore_timer_del(delay_check);
963 delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL);
964 return ECORE_CALLBACK_PASS_ON;
968 linux_acpi_cb_event_fd_active(void *data __UNUSED__,
969 Ecore_Fd_Handler *fd_handler)
971 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
979 if ((num = read(event_fd, buf, sizeof(buf))) < 1)
981 lost = ((errno == EIO) ||
991 ecore_main_fd_handler_del(event_fd_handler);
992 event_fd_handler = NULL;
998 if (delay_check) ecore_timer_del(delay_check);
999 delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL);
1002 return ECORE_CALLBACK_RENEW;
1006 linux_acpi_init(void)
1008 Eina_Iterator *powers;
1009 Eina_Iterator *bats;
1011 bats = eina_file_direct_ls("/proc/acpi/battery");
1014 Eina_File_Direct_Info *info;
1017 powers = eina_file_direct_ls("/proc/acpi/ac_adapter");
1020 EINA_ITERATOR_FOREACH(powers, info)
1025 strcpy(buf, info->path);
1026 strcat(buf, "/state");
1027 f = fopen(buf, "r");
1033 tmp = fgets(buf, sizeof(buf), f);
1034 if (tmp) tmp = str_get(tmp);
1037 if (!strcmp(tmp, "on-line")) have_power = 1;
1043 eina_iterator_free(powers);
1048 acpi_max_design = 0;
1049 EINA_ITERATOR_FOREACH(bats, info)
1054 strcpy(buf, info->path);
1055 strcat(buf, "/info");
1056 f = fopen(buf, "r");
1062 tmp = fgets(buf, sizeof(buf), f);
1063 if (tmp) tmp = str_get(tmp);
1066 if (!strcmp(tmp, "yes")) have_battery = 1;
1070 tmp = fgets(buf, sizeof(buf), f);
1071 if (tmp) tmp = str_get(tmp);
1074 if (strcmp(tmp, "unknown")) acpi_max_design += atoi(tmp);
1078 tmp = fgets(buf, sizeof(buf), f);
1079 if (tmp) tmp = str_get(tmp);
1082 if (strcmp(tmp, "unknown")) acpi_max_full += atoi(tmp);
1089 eina_iterator_free(bats);
1093 acpid = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM,
1094 "/var/run/acpid.socket", -1, NULL);
1097 acpid_handler_add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
1098 linux_acpi_cb_acpid_add, NULL);
1099 acpid_handler_del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
1100 linux_acpi_cb_acpid_del, NULL);
1101 acpid_handler_data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
1102 linux_acpi_cb_acpid_data, NULL);
1108 event_fd = open("/proc/acpi/event", O_RDONLY);
1110 event_fd_handler = ecore_main_fd_handler_add(event_fd,
1112 linux_acpi_cb_event_fd_active,
1121 linux_acpi_check(void)
1130 bats = ecore_file_ls("/proc/acpi/battery");
1137 EINA_LIST_FREE(bats, name)
1143 snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name);
1145 f = fopen(buf, "r");
1148 tmp = file_str_entry_get(f, "present:");
1149 if (!tmp) goto fclose_and_continue;
1150 if (!strcasecmp(tmp, "yes")) have_battery = 1;
1153 tmp = file_str_entry_get(f, "capacity state:");
1154 if (!tmp) goto fclose_and_continue;
1157 tmp = file_str_entry_get(f, "charging state:");
1158 if (!tmp) goto fclose_and_continue;
1159 if ((have_power == 0) && (!strcasecmp(tmp, "charging")))
1163 tmp = file_str_entry_get(f, "present rate:");
1164 if (!tmp) goto fclose_and_continue;
1165 if (strcasecmp(tmp, "unknown")) rate += atoi(tmp);
1168 tmp = file_str_entry_get(f, "remaining capacity:");
1169 if (!tmp) goto fclose_and_continue;
1170 if (strcasecmp(tmp, "unknown")) capacity += atoi(tmp);
1173 fclose_and_continue:
1177 if (acpi_max_full > 0)
1178 battery_full = 100 * (long long)capacity / acpi_max_full;
1179 else if (acpi_max_design > 0)
1180 battery_full = 100 * (long long)capacity / acpi_max_design;
1183 if (rate <= 0) time_left = -1;
1187 time_left = (3600 * ((long long)acpi_max_full - (long long)capacity)) / rate;
1189 time_left = (3600 * (long long)capacity) / rate;
1195 /* old school apm support - very old laptops and some devices support this.
1196 * this is here for legacy support and i wouldn't suggest spending any
1197 * effort on it as it is complete below as best i know, but could have missed
1198 * one or 2 things, but not worth fixing */
1199 static void linux_apm_init(void);
1200 static void linux_apm_check(void);
1203 linux_apm_init(void)
1209 linux_apm_check(void)
1212 char s1[32], s2[32], s3[32], *endptr;
1213 int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val;
1220 f = fopen("/proc/apm", "r");
1223 if (fscanf(f, "%*s %*s %x %x %x %x %31s %31s %31s",
1224 &apm_flags, &ac_stat, &bat_stat, &bat_flags, s1, s2, s3) != 7)
1231 bat_val = strtol(s1, &endptr, 10);
1232 if (*endptr != '%') return;
1234 if (!strcmp(s3, "sec")) time_val = atoi(s2);
1235 else if (!strcmp(s3, "min"))
1236 time_val = atoi(s2) * 60;
1239 if ((bat_flags != 0xff) && (bat_flags & 0x80))
1251 have_power = ac_stat;
1252 battery_full = bat_val;
1253 if (battery_full > 100) battery_full = 100;
1254 if (ac_stat == 1) time_left = -1;
1255 else time_left = time_val;
1263 have_power = ac_stat;
1268 case 1: /* medium */
1270 have_power = ac_stat;
1277 have_power = ac_stat;
1282 case 3: /* charging */
1284 have_power = ac_stat;
1293 /* for older mac powerbooks. legacy as well like linux_apm_init/check. leave
1294 * it alone unless you have to touch it */
1295 static void linux_pmu_init(void);
1296 static void linux_pmu_check(void);
1299 linux_pmu_init(void)
1305 linux_pmu_check(void)
1318 f = fopen("/proc/pmu/info", "r");
1323 tmp = fgets(buf, sizeof(buf), f);
1326 EINA_LOG_ERR("no driver info in /proc/pmu/info");
1327 goto fclose_and_continue;
1330 tmp = fgets(buf, sizeof(buf), f);
1333 EINA_LOG_ERR("no firmware info in /proc/pmu/info");
1334 goto fclose_and_continue;
1337 tmp = fgets(buf, sizeof(buf), f);
1340 EINA_LOG_ERR("no AC info in /proc/pmu/info");
1341 goto fclose_and_continue;
1344 fclose_and_continue:
1347 bats = ecore_file_ls("/proc/pmu");
1352 EINA_LIST_FREE(bats, name)
1354 if (strncmp(name, "battery", 7)) continue;
1355 snprintf(buf, sizeof(buf), "/proc/pmu/%s", name);
1356 f = fopen(buf, "r");
1362 while (fgets(buf, sizeof (buf), f))
1366 if ((token = strtok(buf, ":")))
1368 if (!strncmp("charge", token, 6))
1369 charge = atoi(strtok(0, ": "));
1370 else if (!strncmp("max_charge", token, 9))
1371 max_charge = atoi(strtok(0, ": "));
1372 else if (!strncmp("current", token, 7))
1373 current = atoi(strtok(0, ": "));
1374 else if (!strncmp("time rem", token, 8))
1375 timeleft = atoi(strtok(0, ": "));
1380 curmax += max_charge;
1381 curcharge += charge;
1385 /* Neither charging nor discharging */
1389 /* When on dc, we are discharging */
1390 seconds += timeleft;
1394 /* Charging - works in parallel */
1395 seconds = MAX(timeleft, seconds);
1401 if (max_charge > 0) battery_full = ((long long)charge * 100) / max_charge;
1402 else battery_full = 0;
1403 time_left = seconds;
1417 dir_has_contents(const char *dir)
1423 bats = ecore_file_ls(dir);
1425 count = eina_list_count(bats);
1426 EINA_LIST_FREE(bats, file)
1428 if (count > 0) return 1;
1439 len = sizeof(acline);
1440 if (!sysctlbyname("hw.acpi.acline", &acline, &len, NULL, 0))
1442 int acline_mib[3] = {-1};
1445 if (!sysctlnametomib("hw.acpi.acline", acline_mib, &len))
1454 if (ecore_file_exists("/dev/apm"))
1461 #elif defined(HAVE_CFBASE_H) /* OS X */
1464 if ((ecore_file_is_dir(sys_power_dir)) && (dir_has_contents(sys_power_dir)))
1466 mode = CHECK_SYS_CLASS_POWER_SUPPLY;
1467 linux_sys_class_power_supply_init();
1469 else if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */
1474 else if (ecore_file_exists("/proc/apm"))
1479 else if (ecore_file_is_dir("/proc/pmu"))
1488 poll_cb(void *data __UNUSED__)
1495 ptime_left = time_left;
1496 pbattery_full = battery_full;
1497 phave_battery = have_battery;
1498 phave_power = have_power;
1520 #elif defined(HAVE_CFBASE_H) /* OS X */
1522 return ECORE_CALLBACK_RENEW;
1538 case CHECK_SYS_CLASS_POWER_SUPPLY:
1539 linux_sys_class_power_supply_check();
1550 if ((ptime_left != time_left) ||
1551 (pbattery_full != battery_full) ||
1552 (phave_battery != have_battery) ||
1553 (phave_power != have_power))
1555 if ((time_left < 0) &&
1556 ((have_battery) && (battery_full < 0)))
1559 printf("%i %i %i %i %i\n",
1560 battery_full, time_left, time_left, have_battery, have_power);
1563 return ECORE_CALLBACK_RENEW;
1572 printf("ARGS INCORRECT!\n");
1575 poll_interval = atoi(argv[1]);
1582 poller = ecore_poller_add(ECORE_POLLER_CORE, poll_interval, poll_cb, NULL);
1585 ecore_main_loop_begin();
1587 ecore_con_shutdown();
1588 ecore_file_shutdown();