Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / battery / batget.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <limits.h>
15
16 #ifdef __FreeBSD__
17 # include <sys/ioctl.h>
18 # include <sys/sysctl.h>
19 # ifdef __i386__
20 #  include <machine/apm_bios.h>
21 # endif
22 #endif
23 #ifdef HAVE_CFBASE_H
24 # include <CFBase.h>
25 # include <CFNumber.h>
26 # include <CFArray.h>
27 # include <CFDictionary.h>
28 # include <CFRunLoop.h>
29 # include <ps/IOPSKeys.h>
30 # include <ps/IOPowerSources.h>
31 #endif
32
33 #include <Eina.h>
34 #include <Ecore.h>
35 #include <Ecore_File.h>
36 #include <Ecore_Con.h>
37
38 /* define MAX for all OS, instead of plenty #include */
39 #ifndef MAX
40 # define MAX(a, b) ((a) < (b) ? (b) : (a))
41 #endif
42
43 /* supported batery system schemes - irrespective of OS */
44 #define CHECK_NONE                   0
45 #define CHECK_ACPI                   1
46 #define CHECK_APM                    2
47 #define CHECK_PMU                    3
48 #define CHECK_SYS_CLASS_POWER_SUPPLY 4
49
50 #define SYS_PWR
51
52 static void      init(void);
53 static Eina_Bool poll_cb(void *data);
54
55 static int poll_interval = 512;
56 static Ecore_Poller *poller = NULL;
57
58 static int mode = CHECK_NONE;
59
60 static int time_left = -2;
61 static int battery_full = -2;
62 static int have_battery = -2;
63 static int have_power = -2;
64
65 static const char *sys_power_dir = "/sys/class/power_supply";
66
67 /* UTILS */
68 static int
69 int_file_get(const char *file)
70 {
71    int val = -1;
72    FILE *f = fopen(file, "r");
73    if (f)
74      {
75         char buf[256];
76         char *str = fgets(buf, sizeof(buf), f);
77         if (str) val = atoi(str);
78         fclose(f);
79      }
80    return val;
81 }
82
83 static char *
84 str_file_get(const char *file)
85 {
86    char *val = NULL;
87    FILE *f = fopen(file, "r");
88    if (f)
89      {
90         char buf[4096];
91         char *str = fgets(buf, sizeof(buf), f);
92         if (str)
93           {
94              size_t len = strlen(str);
95              if ((len > 0) && (str[len - 1] == '\n'))
96                {
97                   len--;
98                   str[len] = 0;
99                }
100              val = malloc(len + 1);
101              if (val) memcpy(val, str, len + 1);
102           }
103         fclose(f);
104      }
105    return val;
106 }
107
108 static int
109 int_get(const char *buf)
110 {
111    const char *p = strchr(buf, ':');
112    if (!p) return 0;
113    p++;
114    while (*p == ' ')
115      p++;
116    return atoi(p);
117 }
118
119 static char *
120 str_get(const char *buf)
121 {
122    const char *p = strchr(buf, ':');
123    const char *q;
124    char *ret;
125
126    if (!p) return NULL;
127    p++;
128    while (*p == ' ')
129      p++;
130
131    q = p + strlen(p) - 1;
132    while ((q > p) && ((*q == ' ') || (*q == '\n')))
133      q--;
134
135    if (q < p) return NULL;
136    q++;
137    ret = malloc(q - p + 1);
138    if (!ret) return NULL;
139    memcpy(ret, p, q - p);
140    ret[q - p] = '\0';
141    return ret;
142 }
143
144 static char *
145 file_str_entry_get(FILE *f,
146                    const char *entry)
147 {
148    char buf[4096];
149    char *tmp;
150
151    tmp = fgets(buf, sizeof(buf), f);
152    if (!tmp)
153      {
154         EINA_LOG_ERR("unexpected end of file, expected: '%s'", entry);
155         return NULL;
156      }
157    if (strcmp(tmp, entry) != 0)
158      {
159         EINA_LOG_ERR("unexpected file entry, expected: '%s'", entry);
160         return NULL;
161      }
162    tmp = str_get(tmp);
163    if (!tmp)
164      {
165         EINA_LOG_ERR("unexpected file entry, missing value for '%s'", entry);
166         return NULL;
167      }
168    return tmp;
169 }
170
171 #ifdef __FreeBSD__
172
173 #define BATTERY_STATE_NONE        0
174 #define BATTERY_STATE_DISCHARGING 1
175 #define BATTERY_STATE_CHARGING    2
176 #define BATTERY_STATE_REMOVED     7
177
178 /***---***/
179 static void
180 bsd_acpi_init(void)
181 {
182    /* nothing to do */
183 }
184
185 static void
186 bsd_acpi_check(void)
187 {
188    int bat_val = 0;
189    int mib_state[4];
190    int mib_life[4];
191    int mib_time[4];
192    int mib_units[4];
193    size_t len;
194    int state = 0;
195    int level = 0;
196    int time_min = 0;
197    int life = 0;
198    int batteries = 0;
199
200    time_left = -1;
201    battery_full = -1;
202    have_battery = 0;
203    have_power = 0;
204
205    /* Read some information on first run. */
206    len = 4;
207    sysctlnametomib("hw.acpi.battery.state", mib_state, &len);
208    len = sizeof(state);
209    if (sysctl(mib_state, 4, &state, &len, NULL, 0) == -1)
210      /* ERROR */
211      state = -1;
212
213    len = 4;
214    sysctlnametomib("hw.acpi.battery.life", mib_life, &len);
215    len = sizeof(life);
216    if (sysctl(mib_life, 4, &life, &len, NULL, 0) == -1)
217      /* ERROR */
218      level = -1;
219    bat_val = life;
220
221    len = 4;
222    sysctlnametomib("hw.acpi.battery.time", mib_time, &len);
223    len = sizeof(time);
224    if (sysctl(mib_time, 4, &time_min, &len, NULL, 0) == -1)
225      /* ERROR */
226      time_min = -1;
227
228    len = 4;
229    sysctlnametomib("hw.acpi.battery.units", mib_units, &len);
230    len = sizeof(batteries);
231    if (sysctl(mib_time, 4, &batteries, &len, NULL, 0) == -1)
232      /* ERROR */
233      batteries = 1;
234
235    if (time_min >= 0) time_left = time_min * 60;
236
237    if (batteries == 1) /* hw.acpi.battery.units = 1 means NO BATTS */
238      time_left = -1;
239    else if ((state == BATTERY_STATE_CHARGING) ||
240             (state == BATTERY_STATE_DISCHARGING))
241      {
242         have_battery = 1;
243         if (state == BATTERY_STATE_CHARGING) have_power = 1;
244         else if (state == BATTERY_STATE_DISCHARGING)
245           have_power = 0;
246         if (level == -1) time_left = -1;
247         else if (time_min == -1)
248           {
249              time_left = -1;
250              battery_full = bat_val;
251           }
252         else battery_full = bat_val;
253      }
254    else
255      {
256         have_battery = 1;
257         battery_full = 100;
258         time_left = -1;
259         have_power = 1;
260      }
261 }
262
263 /***---***/
264 # ifdef __i386__
265 static void
266 bsd_apm_init(void)
267 {
268    /* nothing to do */
269 }
270
271 static void
272 bsd_apm_check(void)
273 {
274    int ac_stat, bat_stat, bat_val, time_val;
275    char buf[4096];
276    int hours, minutes;
277    int apm_fd = -1;
278    struct apm_info info;
279
280    time_left = -1;
281    battery_full = -1;
282    have_battery = 0;
283    have_power = 0;
284
285    apm_fd = open("/dev/apm", O_RDONLY);
286    if ((apm_fd != -1) && (ioctl(apm_fd, APMIO_GETINFO, &info) != -1))
287      {
288         /* set values */
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;
293      }
294    else
295      {
296         if (apm_fd != -1) close(apm_fd);
297         return;
298      }
299
300    close(apm_fd);
301    if (info.ai_batteries == 1) /* ai_batteries == 1 means NO battery,
302                                * ai_batteries == 2 means 1 battery */
303      {
304         have_power = 1;
305         return;
306      }
307
308    if (ac_stat) /* Wallpowered */
309      {
310         have_power = 1;
311         have_battery = 1;
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
314                            * will recharge */
315           {
316            case 0:
317              battery_full = 100;
318              break;
319
320            case 1:
321              battery_full = 50;
322              break;
323
324            case 2:
325              battery_full = 25;
326              break;
327
328            case 3:
329              battery_full = 100;
330              break;
331           }
332      }
333    else /* Running on battery */
334      {
335         have_battery = 1;
336         battery_full = bat_val;
337         time_left = time_val;
338      }
339 }
340
341 # endif
342
343 #elif defined(HAVE_CFBASE_H) /* OS X */
344 /***---***/
345 static void darwin_init(void);
346 static void darwin_check(void);
347
348 static void
349 darwin_init(void)
350 {
351    /* nothing to do */
352 }
353
354 static void
355 darwin_check(void)
356 {
357    const void *values;
358    int device_num, device_count;
359    int currentval = 0, maxval = 0;
360    char buf[4096];
361    CFTypeRef blob;
362    CFArrayRef sources;
363    CFDictionaryRef device_dict;
364
365    time_left = -1;
366    battery_full = -1;
367    have_battery = 0;
368    have_power = 0;
369
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++)
375      {
376         CFTypeRef ps;
377
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))
384           {
385              have_battery = 1;
386              if (CFBooleanGetValue(values) > 0) have_power = 1;
387              break;
388           }
389      }
390
391    if (!have_battery)
392      {
393         CFRelease(sources);
394         CFRelease(blob);
395         have_power = 1;
396         return;
397      }
398
399    /* Retrieve the current capacity key. */
400    values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey));
401    CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
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;
407
408    /* Retrieve the remaining battery power or time until charged in minutes. */
409    if (!have_power)
410      {
411         values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey));
412         CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
413         time_left = currentval * 60;
414      }
415    else
416      {
417         values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey));
418         CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
419         time_left = currentval * 60;
420      }
421    CFRelease(sources);
422    CFRelease(blob);
423 }
424
425 #else
426
427 /***---***/
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 */
430 #if 0
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);
434 #endif
435 static void      linux_sys_class_power_supply_init(void);
436
437 typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent;
438
439 #define BASIS_CHARGE  1
440 #define BASIS_ENERGY  2
441 #define BASIS_VOLTAGE 3
442
443 struct _Sys_Class_Power_Supply_Uevent
444 {
445    char             *name;
446    int               fd;
447    Ecore_Fd_Handler *fd_handler;
448
449    int               present;
450
451    int               basis;
452    int               basis_empty;
453    int               basis_full;
454
455    unsigned char     have_current_avg : 1;
456    unsigned char     have_current_now : 1;
457 };
458
459 static Eina_List *events = NULL;
460
461 #if 0
462 static Ecore_Timer *sys_class_delay_check = NULL;
463
464 static Eina_Bool
465 linux_sys_class_power_supply_cb_delay_check(void *data)
466 {
467    linux_sys_class_power_supply_init();
468    poll_cb(NULL);
469    sys_class_delay_check = NULL;
470    return ECORE_CALLBACK_CANCEL;
471 }
472
473 static Ecore_Timer *re_init_timer = NULL;
474
475 static Eina_Bool
476 linux_sys_class_power_supply_cb_re_init(void *data)
477 {
478    Sys_Class_Power_Supply_Uevent *sysev;
479
480    if (events)
481      {
482         EINA_LIST_FREE(events, sysev)
483           {
484 //           if (sysev->fd_handler)
485 //             ecore_main_fd_handler_del(sysev->fd_handler);
486 //           if (sysev->fd >= 0) close(sysev->fd);
487              free(sysev->name);
488              free(sysev);
489           }
490      }
491    linux_sys_class_power_supply_init();
492    re_init_timer = NULL;
493    return ECORE_CALLBACK_CANCEL;
494 }
495
496 static Eina_Bool
497 linux_sys_class_power_supply_cb_event_fd_active(void *data,
498                                                 Ecore_Fd_Handler *fd_handler)
499 {
500    Sys_Class_Power_Supply_Uevent *sysev;
501
502    sysev = data;
503    if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
504      {
505         int lost = 0;
506         for (;; )
507           {
508              char buf[1024];
509              int num;
510
511              if ((num = read(sysev->fd, buf, sizeof(buf))) < 1)
512                {
513                   lost = ((errno == EIO) ||
514                           (errno == EBADF) ||
515                           (errno == EPIPE) ||
516                           (errno == EINVAL) ||
517                           (errno == ENOSPC) ||
518                           (errno == ENODEV));
519                   if (num <= 0) break;
520                }
521           }
522         if (lost)
523           {
524              events = eina_list_remove(events, sysev);
525
526 //           if (sysev->fd_handler)
527 //             ecore_main_fd_handler_del(sysev->fd_handler);
528 //           if (sysev->fd >= 0) close(sysev->fd);
529              free(sysev->name);
530              free(sysev);
531
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);
534           }
535         else
536           {
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);
539           }
540      }
541    return ECORE_CALLBACK_CANCEL;
542 }
543
544 #endif
545 static void
546 linux_sys_class_power_supply_sysev_init(Sys_Class_Power_Supply_Uevent *sysev)
547 {
548    char buf[4096];
549    const char *dir = sys_power_dir;
550
551    sysev->basis = 0;
552    sysev->have_current_avg = 0;
553    sysev->have_current_now = 0;
554
555    snprintf(buf, sizeof(buf), "%s/%s/present", dir, sysev->name);
556    sysev->present = int_file_get(buf);
557    if (!sysev->present) return;
558
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;
563
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;
568
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;
573
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;
578
579    if (sysev->basis == BASIS_CHARGE)
580      {
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)
586           {
587              snprintf(buf, sizeof(buf), "%s/%s/charge_full_design", dir, sysev->name);
588              sysev->basis_full = int_file_get(buf);
589           }
590         if (sysev->basis_empty < 0)
591           {
592              snprintf(buf, sizeof(buf), "%s/%s/charge_empty_design", dir, sysev->name);
593              sysev->basis_empty = int_file_get(buf);
594           }
595      }
596    else if (sysev->basis == BASIS_ENERGY)
597      {
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)
603           {
604              snprintf(buf, sizeof(buf), "%s/%s/energy_full_design", dir, sysev->name);
605              sysev->basis_full = int_file_get(buf);
606           }
607         if (sysev->basis_empty < 0)
608           {
609              snprintf(buf, sizeof(buf), "%s/%s/energy_empty_design", dir, sysev->name);
610              sysev->basis_empty = int_file_get(buf);
611           }
612      }
613    else if (sysev->basis == BASIS_VOLTAGE)
614      {
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)
620           {
621              snprintf(buf, sizeof(buf), "%s/%s/voltage_max_design", dir, sysev->name);
622              sysev->basis_full = int_file_get(buf);
623           }
624         if (sysev->basis_empty < 0)
625           {
626              snprintf(buf, sizeof(buf), "%s/%s/voltage_min_design", dir, sysev->name);
627              sysev->basis_empty = int_file_get(buf);
628           }
629      }
630 }
631
632 static int
633 linux_sys_class_power_supply_is_battery(char *name)
634 {
635    int fd;
636    int ret = 0;
637    char buf[256];
638    const char *dir = sys_power_dir;
639
640    snprintf(buf, sizeof(buf), "%s/%s/type", dir, name);
641    fd = open(buf, O_RDONLY);
642    if (fd < 0)
643      {
644         ret = 0;
645         goto NO_OPEN;
646      }
647    else if (read(fd, buf, sizeof(buf)) < 1)
648      ret = 0;
649    else if (!strncmp(buf, "Battery", 7))
650      ret = 1;
651
652    close(fd);
653
654 NO_OPEN:
655    return ret;
656 }
657
658 static void
659 linux_sys_class_power_supply_init(void)
660 {
661    Eina_List *l;
662
663    if (events)
664      {
665         Sys_Class_Power_Supply_Uevent *sysev;
666
667         EINA_LIST_FOREACH(events, l, sysev)
668           linux_sys_class_power_supply_sysev_init(sysev);
669      }
670    else
671      {
672         Eina_List *bats;
673         char *name;
674 //      char buf[4096];
675
676         bats = ecore_file_ls("/sys/class/power_supply/");
677 //        bats = ecore_file_ls("./TST");
678         if (bats)
679           {
680              events = NULL;
681
682              EINA_LIST_FREE(bats, name)
683                {
684                   Sys_Class_Power_Supply_Uevent *sysev;
685
686                   if (!(linux_sys_class_power_supply_is_battery(name)))
687                     {
688                        free(name);
689                        continue;
690                     }
691
692                   sysev = (Sys_Class_Power_Supply_Uevent *)calloc(1, sizeof(Sys_Class_Power_Supply_Uevent));
693                   sysev->name = name;
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,
698 //                                                                ECORE_FD_READ,
699 //                                                                linux_sys_class_power_supply_cb_event_fd_active,
700 //                                                                sysev,
701 //                                                                NULL, NULL);
702                   events = eina_list_append(events, sysev);
703                   linux_sys_class_power_supply_sysev_init(sysev);
704                }
705           }
706      }
707 }
708
709 static void
710 linux_sys_class_power_supply_check(void)
711 {
712    Eina_List *l;
713    char *name;
714    char buf[4096];
715    const char *dir = sys_power_dir;
716
717    battery_full = -1;
718    time_left = -1;
719    have_battery = 0;
720    have_power = 0;
721
722    if (events)
723      {
724         Sys_Class_Power_Supply_Uevent *sysev;
725         int total_pwr_now;
726         int total_pwr_max;
727         int nofull = 0;
728
729         total_pwr_now = 0;
730         total_pwr_max = 0;
731         time_left = 0;
732         EINA_LIST_FOREACH(events, l, sysev)
733           {
734              char *tmp;
735              int present = 0;
736              int charging = -1;
737              int capacity = -1;
738              int current = -1;
739              int time_to_full = -1;
740              int time_to_empty = -1;
741              int full = -1;
742              int pwr_now = -1;
743              int pwr_empty = -1;
744              int pwr_full = -1;
745              int pwr = 0;
746
747              name = sysev->name;
748
749              /* fetch more generic info */
750              // init
751              present = sysev->present;
752              if (!present) continue;
753
754              snprintf(buf, sizeof(buf), "%s/%s/capacity", dir, name);
755              capacity = int_file_get(buf);
756              if (sysev->have_current_avg)
757                {
758                   snprintf(buf, sizeof(buf), "%s/%s/current_avg", dir, name);
759                   current = int_file_get(buf);
760                }
761              else if (sysev->have_current_now)
762                {
763                   snprintf(buf, sizeof(buf), "%s/%s/current_now", dir, name);
764                   current = int_file_get(buf);
765                }
766
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);
771              if (tmp)
772                {
773                   full = 0;
774                   if (!strncasecmp("discharging", tmp, 11)) charging = 0;
775                   else if (!strncasecmp("unknown", tmp, 7))
776                     charging = 0;
777                   else if (!strncasecmp("not charging", tmp, 12))
778                     charging = 0;
779                   else if (!strncasecmp("charging", tmp, 8))
780                     charging = 1;
781                   else if (!strncasecmp("full", tmp, 4))
782                     {
783                        full = 1;
784                        charging = 0;
785                     }
786                   free(tmp);
787                }
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 */
791              if (!full)
792                {
793                   nofull++;
794                   if (charging)
795                     {
796                        snprintf(buf, sizeof(buf), "%s/%s/time_to_full_now", dir, name);
797                        time_to_full = int_file_get(buf);
798                     }
799                   else
800                     {
801                        snprintf(buf, sizeof(buf), "%s/%s/time_to_empty_now", dir, name);
802                        time_to_empty = int_file_get(buf);
803                     }
804                }
805
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) &&
818                  (capacity >= 0))
819                {
820                   /* if we use voltage as basis.. we're not very accurate
821                    * so we should prefer capacity readings */
822                   pwr_empty = -1;
823                   pwr_full = -1;
824                   pwr_now = -1;
825                }
826
827              if (pwr_empty < 0) pwr_empty = 0;
828
829              if ((pwr_full > 0) && (pwr_full > pwr_empty))
830                {
831                   if (full) pwr_now = pwr_full;
832                   else
833                     {
834                        if (pwr_now < 0)
835                          pwr_now = (((long long)capacity * ((long long)pwr_full - (long long)pwr_empty)) / 100) + pwr_empty;
836                     }
837
838                   if (sysev->present) have_battery = 1;
839                   if (charging)
840                     {
841                        pwr_now = pwr_now;
842                        have_power = 1;
843                        if (time_to_full >= 0)
844                          {
845                             if (time_to_full > time_left)
846                               time_left = time_to_full;
847                          }
848                        else
849                          {
850                             if (current == 0) time_left = 0;
851                             else if (current < 0)
852                               time_left = -1;
853                             else
854                               {
855                                  pwr = (((long long)pwr_full - (long long)pwr_now) * 3600) / -current;
856                                  if (pwr > time_left) time_left = pwr;
857                               }
858                          }
859                     }
860                   else
861                     {
862                        have_power = 0;
863                        if (time_to_empty >= 0) time_left += time_to_empty;
864                        else
865                          {
866                             if (time_to_empty < 0)
867                               {
868                                  if (current > 0)
869                                    {
870                                       pwr = (((long long)pwr_now - (long long)pwr_empty) * 3600) / current;
871                                       time_left += pwr;
872                                    }
873                               }
874                          }
875                     }
876                   total_pwr_now += pwr_now - pwr_empty;
877                   total_pwr_max += pwr_full - pwr_empty;
878                }
879              /* simple current battery fallback */
880              else
881                {
882                   if (sysev->present) have_battery = 1;
883                   if (charging) have_power = 1;
884                   total_pwr_max = 100;
885                   total_pwr_now = capacity;
886                   if (total_pwr_now < 100) nofull = 1;
887                }
888           }
889         if (total_pwr_max > 0)
890           battery_full = ((long long)total_pwr_now * 100) / total_pwr_max;
891         if (nofull == 0)
892           time_left = -1;
893      }
894 }
895
896 /***---***/
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
901  */
902 static Eina_Bool linux_acpi_cb_acpid_add(void *data,
903                                          int type,
904                                          void *event);
905 static Eina_Bool linux_acpi_cb_acpid_del(void *data,
906                                          int type,
907                                          void *event);
908 static Eina_Bool linux_acpi_cb_acpid_data(void *data,
909                                           int type,
910                                           void *event);
911 static void      linux_acpi_init(void);
912 static void      linux_acpi_check(void);
913
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;
923
924 static Eina_Bool
925 linux_acpi_cb_delay_check(void *data __UNUSED__)
926 {
927    linux_acpi_init();
928    poll_cb(NULL);
929    delay_check = NULL;
930    return ECORE_CALLBACK_CANCEL;
931 }
932
933 static Eina_Bool
934 linux_acpi_cb_acpid_add(void *data  __UNUSED__,
935                         int type    __UNUSED__,
936                         void *event __UNUSED__)
937 {
938    return ECORE_CALLBACK_PASS_ON;
939 }
940
941 static Eina_Bool
942 linux_acpi_cb_acpid_del(void *data  __UNUSED__,
943                         int type    __UNUSED__,
944                         void *event __UNUSED__)
945 {
946    ecore_con_server_del(acpid);
947    acpid = NULL;
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;
955 }
956
957 static Eina_Bool
958 linux_acpi_cb_acpid_data(void *data  __UNUSED__,
959                          int type    __UNUSED__,
960                          void *event __UNUSED__)
961 {
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;
965 }
966
967 static Eina_Bool
968 linux_acpi_cb_event_fd_active(void *data        __UNUSED__,
969                               Ecore_Fd_Handler *fd_handler)
970 {
971    if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
972      {
973         int lost = 0;
974         for (;; )
975           {
976              char buf[1024];
977              int num;
978
979              if ((num = read(event_fd, buf, sizeof(buf))) < 1)
980                {
981                   lost = ((errno == EIO) ||
982                           (errno == EBADF) ||
983                           (errno == EPIPE) ||
984                           (errno == EINVAL) ||
985                           (errno == ENOSPC));
986                   if (num == 0) break;
987                }
988           }
989         if (lost)
990           {
991              ecore_main_fd_handler_del(event_fd_handler);
992              event_fd_handler = NULL;
993              close(event_fd);
994              event_fd = -1;
995           }
996         else
997           {
998              if (delay_check) ecore_timer_del(delay_check);
999              delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL);
1000           }
1001      }
1002    return ECORE_CALLBACK_RENEW;
1003 }
1004
1005 static void
1006 linux_acpi_init(void)
1007 {
1008    Eina_Iterator *powers;
1009    Eina_Iterator *bats;
1010
1011    bats = eina_file_direct_ls("/proc/acpi/battery");
1012    if (bats)
1013      {
1014         Eina_File_Direct_Info *info;
1015
1016         have_power = 0;
1017         powers = eina_file_direct_ls("/proc/acpi/ac_adapter");
1018         if (powers)
1019           {
1020              EINA_ITERATOR_FOREACH(powers, info)
1021                {
1022                   char buf[4096];
1023                   FILE *f;
1024
1025                   strcpy(buf, info->path);
1026                   strcat(buf, "/state");
1027                   f = fopen(buf, "r");
1028                   if (f)
1029                     {
1030                        char *tmp;
1031
1032                        /* state */
1033                        tmp = fgets(buf, sizeof(buf), f);
1034                        if (tmp) tmp = str_get(tmp);
1035                        if (tmp)
1036                          {
1037                             if (!strcmp(tmp, "on-line")) have_power = 1;
1038                             free(tmp);
1039                          }
1040                        fclose(f);
1041                     }
1042                }
1043              eina_iterator_free(powers);
1044           }
1045
1046         have_battery = 0;
1047         acpi_max_full = 0;
1048         acpi_max_design = 0;
1049         EINA_ITERATOR_FOREACH(bats, info)
1050           {
1051              char buf[4096];
1052              FILE *f;
1053
1054              strcpy(buf, info->path);
1055              strcat(buf, "/info");
1056              f = fopen(buf, "r");
1057              if (f)
1058                {
1059                   char *tmp;
1060
1061                   /* present */
1062                   tmp = fgets(buf, sizeof(buf), f);
1063                   if (tmp) tmp = str_get(tmp);
1064                   if (tmp)
1065                     {
1066                        if (!strcmp(tmp, "yes")) have_battery = 1;
1067                        free(tmp);
1068                     }
1069                   /* design cap */
1070                   tmp = fgets(buf, sizeof(buf), f);
1071                   if (tmp) tmp = str_get(tmp);
1072                   if (tmp)
1073                     {
1074                        if (strcmp(tmp, "unknown")) acpi_max_design += atoi(tmp);
1075                        free(tmp);
1076                     }
1077                   /* last full cap */
1078                   tmp = fgets(buf, sizeof(buf), f);
1079                   if (tmp) tmp = str_get(tmp);
1080                   if (tmp)
1081                     {
1082                        if (strcmp(tmp, "unknown")) acpi_max_full += atoi(tmp);
1083                        free(tmp);
1084                     }
1085                   fclose(f);
1086                }
1087           }
1088
1089         eina_iterator_free(bats);
1090      }
1091    if (!acpid)
1092      {
1093         acpid = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM,
1094                                          "/var/run/acpid.socket", -1, NULL);
1095         if (acpid)
1096           {
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);
1103           }
1104         else
1105           {
1106              if (event_fd < 0)
1107                {
1108                   event_fd = open("/proc/acpi/event", O_RDONLY);
1109                   if (event_fd >= 0)
1110                     event_fd_handler = ecore_main_fd_handler_add(event_fd,
1111                                                                  ECORE_FD_READ,
1112                                                                  linux_acpi_cb_event_fd_active,
1113                                                                  NULL,
1114                                                                  NULL, NULL);
1115                }
1116           }
1117      }
1118 }
1119
1120 static void
1121 linux_acpi_check(void)
1122 {
1123    Eina_List *bats;
1124
1125    battery_full = -1;
1126    time_left = -1;
1127    have_battery = 0;
1128    have_power = 0;
1129
1130    bats = ecore_file_ls("/proc/acpi/battery");
1131    if (bats)
1132      {
1133         char *name;
1134         int rate = 0;
1135         int capacity = 0;
1136
1137         EINA_LIST_FREE(bats, name)
1138           {
1139              char buf[4096];
1140              char *tmp;
1141              FILE *f;
1142
1143              snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name);
1144              free(name);
1145              f = fopen(buf, "r");
1146              if (!f) continue;
1147
1148              tmp = file_str_entry_get(f, "present:");
1149              if (!tmp) goto fclose_and_continue;
1150              if (!strcasecmp(tmp, "yes")) have_battery = 1;
1151              free(tmp);
1152
1153              tmp = file_str_entry_get(f, "capacity state:");
1154              if (!tmp) goto fclose_and_continue;
1155              free(tmp);
1156
1157              tmp = file_str_entry_get(f, "charging state:");
1158              if (!tmp) goto fclose_and_continue;
1159              if ((have_power == 0) && (!strcasecmp(tmp, "charging")))
1160                have_power = 1;
1161              free(tmp);
1162
1163              tmp = file_str_entry_get(f, "present rate:");
1164              if (!tmp) goto fclose_and_continue;
1165              if (strcasecmp(tmp, "unknown")) rate += atoi(tmp);
1166              free(tmp);
1167
1168              tmp = file_str_entry_get(f, "remaining capacity:");
1169              if (!tmp) goto fclose_and_continue;
1170              if (strcasecmp(tmp, "unknown")) capacity += atoi(tmp);
1171              free(tmp);
1172
1173 fclose_and_continue:
1174              fclose(f);
1175           }
1176
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;
1181         else
1182           battery_full = -1;
1183         if (rate <= 0) time_left = -1;
1184         else
1185           {
1186              if (have_power)
1187                time_left = (3600 * ((long long)acpi_max_full - (long long)capacity)) / rate;
1188              else
1189                time_left = (3600 * (long long)capacity) / rate;
1190           }
1191      }
1192 }
1193
1194 /***---***/
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);
1201
1202 static void
1203 linux_apm_init(void)
1204 {
1205    /* nothing to do */
1206 }
1207
1208 static void
1209 linux_apm_check(void)
1210 {
1211    FILE *f;
1212    char s1[32], s2[32], s3[32], *endptr;
1213    int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val;
1214
1215    battery_full = -1;
1216    time_left = -1;
1217    have_battery = 0;
1218    have_power = 0;
1219
1220    f = fopen("/proc/apm", "r");
1221    if (!f) return;
1222
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)
1225      {
1226         fclose(f);
1227         return;
1228      }
1229    fclose(f);
1230
1231    bat_val = strtol(s1, &endptr, 10);
1232    if (*endptr != '%') return;
1233
1234    if (!strcmp(s3, "sec")) time_val = atoi(s2);
1235    else if (!strcmp(s3, "min"))
1236      time_val = atoi(s2) * 60;
1237    else time_val = 0;
1238
1239    if ((bat_flags != 0xff) && (bat_flags & 0x80))
1240      {
1241         have_battery = 0;
1242         have_power = 0;
1243         battery_full = 100;
1244         time_left = 0;
1245         return;
1246      }
1247
1248    if (bat_val >= 0)
1249      {
1250         have_battery = 1;
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;
1256      }
1257    else
1258      {
1259         switch (bat_stat)
1260           {
1261            case 0: /* high */
1262              have_battery = 1;
1263              have_power = ac_stat;
1264              battery_full = 100;
1265              time_left = -1;
1266              break;
1267
1268            case 1: /* medium */
1269              have_battery = 1;
1270              have_power = ac_stat;
1271              battery_full = 50;
1272              time_left = -1;
1273              break;
1274
1275            case 2: /* low */
1276              have_battery = 1;
1277              have_power = ac_stat;
1278              battery_full = 25;
1279              time_left = -1;
1280              break;
1281
1282            case 3: /* charging */
1283              have_battery = 1;
1284              have_power = ac_stat;
1285              battery_full = 100;
1286              time_left = -1;
1287              break;
1288           }
1289      }
1290 }
1291
1292 /***---***/
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);
1297
1298 static void
1299 linux_pmu_init(void)
1300 {
1301    /* nothing to do */
1302 }
1303
1304 static void
1305 linux_pmu_check(void)
1306 {
1307    FILE *f;
1308    char buf[4096];
1309    Eina_List *bats;
1310    char *name;
1311    int ac = 0;
1312    int charge = 0;
1313    int max_charge = 0;
1314    int seconds = 0;
1315    int curcharge = 0;
1316    int curmax = 0;
1317
1318    f = fopen("/proc/pmu/info", "r");
1319    if (f)
1320      {
1321         char *tmp;
1322         /* Skip driver */
1323         tmp = fgets(buf, sizeof(buf), f);
1324         if (!tmp)
1325           {
1326              EINA_LOG_ERR("no driver info in /proc/pmu/info");
1327              goto fclose_and_continue;
1328           }
1329         /* Skip firmware */
1330         tmp = fgets(buf, sizeof(buf), f);
1331         if (!tmp)
1332           {
1333              EINA_LOG_ERR("no firmware info in /proc/pmu/info");
1334              goto fclose_and_continue;
1335           }
1336         /* Read ac */
1337         tmp = fgets(buf, sizeof(buf), f);
1338         if (!tmp)
1339           {
1340              EINA_LOG_ERR("no AC info in /proc/pmu/info");
1341              goto fclose_and_continue;
1342           }
1343         ac = int_get(buf);
1344 fclose_and_continue:
1345         fclose(f);
1346      }
1347    bats = ecore_file_ls("/proc/pmu");
1348    if (bats)
1349      {
1350         have_battery = 1;
1351         have_power = ac;
1352         EINA_LIST_FREE(bats, name)
1353           {
1354              if (strncmp(name, "battery", 7)) continue;
1355              snprintf(buf, sizeof(buf), "/proc/pmu/%s", name);
1356              f = fopen(buf, "r");
1357              if (f)
1358                {
1359                   int timeleft = 0;
1360                   int current = 0;
1361
1362                   while (fgets(buf, sizeof (buf), f))
1363                     {
1364                        char *token;
1365
1366                        if ((token = strtok(buf, ":")))
1367                          {
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, ": "));
1376                             else
1377                               strtok(0, ": ");
1378                          }
1379                     }
1380                   curmax += max_charge;
1381                   curcharge += charge;
1382                   fclose(f);
1383                   if (!current)
1384                     {
1385                        /* Neither charging nor discharging */
1386                     }
1387                   else if (!ac)
1388                     {
1389                        /* When on dc, we are discharging */
1390                        seconds += timeleft;
1391                     }
1392                   else
1393                     {
1394                        /* Charging - works in parallel */
1395                        seconds = MAX(timeleft, seconds);
1396                     }
1397                }
1398
1399              free(name);
1400           }
1401         if (max_charge > 0) battery_full = ((long long)charge * 100) / max_charge;
1402         else battery_full = 0;
1403         time_left = seconds;
1404      }
1405    else
1406      {
1407         have_power = ac;
1408         have_battery = 0;
1409         battery_full = -1;
1410         time_left = -1;
1411      }
1412 }
1413
1414 #endif
1415
1416 static int
1417 dir_has_contents(const char *dir)
1418 {
1419    Eina_List *bats;
1420    char *file;
1421    int count;
1422
1423    bats = ecore_file_ls(dir);
1424
1425    count = eina_list_count(bats);
1426    EINA_LIST_FREE(bats, file)
1427      free(file);
1428    if (count > 0) return 1;
1429    return 0;
1430 }
1431
1432 static void
1433 init(void)
1434 {
1435 #ifdef __FreeBSD__
1436    int acline;
1437    size_t len;
1438
1439    len = sizeof(acline);
1440    if (!sysctlbyname("hw.acpi.acline", &acline, &len, NULL, 0))
1441      {
1442         int acline_mib[3] = {-1};
1443
1444         len = 3;
1445         if (!sysctlnametomib("hw.acpi.acline", acline_mib, &len))
1446           {
1447              mode = CHECK_ACPI;
1448              bsd_acpi_init();
1449           }
1450      }
1451    else
1452      {
1453 #ifdef __i386__
1454         if (ecore_file_exists("/dev/apm"))
1455           {
1456              mode = CHECK_APM;
1457              bsd_apm_init();
1458           }
1459 #endif
1460      }
1461 #elif defined(HAVE_CFBASE_H) /* OS X */
1462    darwin_init();
1463 #else
1464    if ((ecore_file_is_dir(sys_power_dir)) && (dir_has_contents(sys_power_dir)))
1465      {
1466         mode = CHECK_SYS_CLASS_POWER_SUPPLY;
1467         linux_sys_class_power_supply_init();
1468      }
1469    else if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */
1470      {
1471         mode = CHECK_ACPI;
1472         linux_acpi_init();
1473      }
1474    else if (ecore_file_exists("/proc/apm"))
1475      {
1476         mode = CHECK_APM;
1477         linux_apm_init();
1478      }
1479    else if (ecore_file_is_dir("/proc/pmu"))
1480      {
1481         mode = CHECK_PMU;
1482         linux_pmu_init();
1483      }
1484 #endif
1485 }
1486
1487 static Eina_Bool
1488 poll_cb(void *data __UNUSED__)
1489 {
1490    int ptime_left;
1491    int pbattery_full;
1492    int phave_battery;
1493    int phave_power;
1494
1495    ptime_left = time_left;
1496    pbattery_full = battery_full;
1497    phave_battery = have_battery;
1498    phave_power = have_power;
1499
1500 #ifdef __FreeBSD__
1501    switch (mode)
1502      {
1503       case CHECK_ACPI:
1504         bsd_acpi_check();
1505         break;
1506
1507 #ifdef __i386__
1508       case CHECK_APM:
1509         bsd_apm_check();
1510         break;
1511
1512 #endif
1513       default:
1514         battery_full = -1;
1515         time_left = -1;
1516         have_battery = 0;
1517         have_power = 0;
1518         break;
1519      }
1520 #elif defined(HAVE_CFBASE_H) /* OS X */
1521    darwin_check();
1522    return ECORE_CALLBACK_RENEW;
1523 #else
1524    switch (mode)
1525      {
1526       case CHECK_ACPI:
1527         linux_acpi_check();
1528         break;
1529
1530       case CHECK_APM:
1531         linux_apm_check();
1532         break;
1533
1534       case CHECK_PMU:
1535         linux_pmu_check();
1536         break;
1537
1538       case CHECK_SYS_CLASS_POWER_SUPPLY:
1539         linux_sys_class_power_supply_check();
1540         break;
1541
1542       default:
1543         battery_full = -1;
1544         time_left = -1;
1545         have_battery = 0;
1546         have_power = 0;
1547         break;
1548      }
1549 #endif
1550    if ((ptime_left != time_left) ||
1551        (pbattery_full != battery_full) ||
1552        (phave_battery != have_battery) ||
1553        (phave_power != have_power))
1554      {
1555         if ((time_left < 0) &&
1556             ((have_battery) && (battery_full < 0)))
1557           printf("ERROR\n");
1558         else
1559           printf("%i %i %i %i %i\n",
1560                  battery_full, time_left, time_left, have_battery, have_power);
1561         fflush(stdout);
1562      }
1563    return ECORE_CALLBACK_RENEW;
1564 }
1565
1566 int
1567 main(int argc,
1568      char *argv[])
1569 {
1570    if (argc != 2)
1571      {
1572         printf("ARGS INCORRECT!\n");
1573         return 0;
1574      }
1575    poll_interval = atoi(argv[1]);
1576
1577    ecore_init();
1578    ecore_file_init();
1579    ecore_con_init();
1580
1581    init();
1582    poller = ecore_poller_add(ECORE_POLLER_CORE, poll_interval, poll_cb, NULL);
1583    poll_cb(NULL);
1584
1585    ecore_main_loop_begin();
1586
1587    ecore_con_shutdown();
1588    ecore_file_shutdown();
1589    ecore_shutdown();
1590
1591    return 0;
1592 }
1593