update for beta release
[framework/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[PATH_MAX];
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 == ' ') p++;
115    return atoi(p);
116 }
117
118 static char *
119 str_get(const char *buf)
120 {
121    const char *p = strchr(buf, ':');
122    const char *q;
123    char *ret;
124
125    if (!p) return NULL;
126    p++;
127    while (*p == ' ') p++;
128
129    q = p + strlen(p) - 1;
130    while ((q > p) && ((*q == ' ') || (*q == '\n'))) q--;
131
132    if (q < p) return NULL;
133    q++;
134    ret = malloc(q - p + 1);
135    if (!ret) return NULL;
136    memcpy(ret, p, q - p);
137    ret[q - p] = '\0';
138    return ret;
139 }
140
141 static char *
142 file_str_entry_get(FILE       *f,
143                    const char *entry)
144 {
145    char buf[4096];
146    char *tmp;
147
148    tmp = fgets(buf, sizeof(buf), f);
149    if (!tmp)
150      {
151         EINA_LOG_ERR("unexpected end of file, expected: '%s'", entry);
152         return NULL;
153      }
154    if (strcmp(tmp, entry) != 0)
155      {
156         EINA_LOG_ERR("unexpected file entry, expected: '%s'", entry);
157         return NULL;
158      }
159    tmp = str_get(tmp);
160    if (!tmp)
161      {
162         EINA_LOG_ERR("unexpected file entry, missing value for '%s'", entry);
163         return NULL;
164      }
165    return tmp;
166 }
167
168 #ifdef __FreeBSD__
169
170 #define BATTERY_STATE_NONE        0
171 #define BATTERY_STATE_DISCHARGING 1
172 #define BATTERY_STATE_CHARGING    2
173 #define BATTERY_STATE_REMOVED     7
174
175 /***---***/
176 static void
177 bsd_acpi_init(void)
178 {
179    /* nothing to do */
180 }
181
182 static void
183 bsd_acpi_check(void)
184 {
185    int bat_val = 0;
186    int mib_state[4];
187    int mib_life[4];
188    int mib_time[4];
189    int mib_units[4];
190    size_t len;
191    int state = 0;
192    int level = 0;
193    int time_min = 0;
194    int life = 0;
195    int batteries = 0;
196
197    time_left = -1;
198    battery_full = -1;
199    have_battery = 0;
200    have_power = 0;
201
202    /* Read some information on first run. */
203    len = 4;
204    sysctlnametomib("hw.acpi.battery.state", mib_state, &len);
205    len = sizeof(state);
206    if (sysctl(mib_state, 4, &state, &len, NULL, 0) == -1)
207      /* ERROR */
208      state = -1;
209
210    len = 4;
211    sysctlnametomib("hw.acpi.battery.life", mib_life, &len);
212    len = sizeof(life);
213    if (sysctl(mib_life, 4, &life, &len, NULL, 0) == -1)
214      /* ERROR */
215      level = -1;
216    bat_val = life;
217
218    len = 4;
219    sysctlnametomib("hw.acpi.battery.time", mib_time, &len);
220    len = sizeof(time);
221    if (sysctl(mib_time, 4, &time_min, &len, NULL, 0) == -1)
222      /* ERROR */
223      time_min = -1;
224
225    len = 4;
226    sysctlnametomib("hw.acpi.battery.units", mib_units, &len);
227    len = sizeof(batteries);
228    if (sysctl(mib_time, 4, &batteries, &len, NULL, 0) == -1)
229      /* ERROR */
230      batteries = 1;
231
232    if (time_min >= 0) time_left = time_min * 60;
233
234    if (batteries == 1) /* hw.acpi.battery.units = 1 means NO BATTS */
235      time_left = -1;
236    else if ((state == BATTERY_STATE_CHARGING) ||
237             (state == BATTERY_STATE_DISCHARGING))
238      {
239         have_battery = 1;
240         if (state == BATTERY_STATE_CHARGING) have_power = 1;
241         else if (state == BATTERY_STATE_DISCHARGING)
242           have_power = 0;
243         if (level == -1) time_left = -1;
244         else if (time_min == -1)
245           {
246              time_left = -1;
247              battery_full = bat_val;
248           }
249         else battery_full = bat_val;
250      }
251    else
252      {
253         have_battery = 1;
254         battery_full = 100;
255         time_left = -1;
256         have_power = 1;
257      }
258 }
259
260 /***---***/
261 # ifdef __i386__
262 static void
263 bsd_apm_init(void)
264 {
265    /* nothing to do */
266 }
267
268 static void
269 bsd_apm_check(void)
270 {
271    int ac_stat, bat_stat, bat_val, time_val;
272    char buf[4096];
273    int hours, minutes;
274    int apm_fd = -1;
275    struct apm_info info;
276
277    time_left = -1;
278    battery_full = -1;
279    have_battery = 0;
280    have_power = 0;
281
282    apm_fd = open("/dev/apm", O_RDONLY);
283    if ((apm_fd != -1) && (ioctl(apm_fd, APMIO_GETINFO, &info) != -1))
284      {
285         /* set values */
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;
290      }
291    else return;
292
293    if (info.ai_batteries == 1) /* ai_batteries == 1 means NO battery,
294                                * ai_batteries == 2 means 1 battery */
295      {
296         have_power = 1;
297         return;
298      }
299
300    if (ac_stat) /* Wallpowered */
301      {
302         have_power = 1;
303         have_battery = 1;
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
306                            * will recharge */
307           {
308            case 0:
309              battery_full = 100;
310              break;
311
312            case 1:
313              battery_full = 50;
314              break;
315
316            case 2:
317              battery_full = 25;
318              break;
319
320            case 3:
321              battery_full = 100;
322              break;
323           }
324      }
325    else /* Running on battery */
326      {
327         have_battery = 1;
328         battery_full = bat_val;
329         time_left = time_val;
330      }
331 }
332
333 # endif
334
335 #elif defined(HAVE_CFBASE_H) /* OS X */
336 /***---***/
337 static void darwin_init(void);
338 static void darwin_check(void);
339
340 static void
341 darwin_init(void)
342 {
343    /* nothing to do */
344 }
345
346 static void
347 darwin_check(void)
348 {
349    const void *values;
350    int device_num, device_count;
351    int currentval = 0, maxval = 0;
352    char buf[4096];
353    CFTypeRef blob;
354    CFArrayRef sources;
355    CFDictionaryRef device_dict;
356
357    time_left = -1;
358    battery_full = -1;
359    have_battery = 0;
360    have_power = 0;
361
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++)
367      {
368         CFTypeRef ps;
369
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))
376           {
377              have_battery = 1;
378              if (CFBooleanGetValue(values) > 0) have_power = 1;
379              break;
380           }
381      }
382
383    if (!have_battery)
384      {
385         CFRelease(sources);
386         CFRelease(blob);
387         have_power = 1;
388         return;
389      }
390
391    /* Retrieve the current capacity key. */
392    values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey));
393    CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
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;
399
400    /* Retrieve the remaining battery power or time until charged in minutes. */
401    if (!have_power)
402      {
403         values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey));
404         CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
405         time_left = currentval * 60;
406      }
407    else
408      {
409         values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey));
410         CFNumberGetValue(values, kCFNumberSInt32Type, &currentval);
411         time_left = currentval * 60;
412      }
413    CFRelease(sources);
414    CFRelease(blob);
415 }
416
417 #else
418
419 /***---***/
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 */
422 #if 0
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);
426 #endif
427 static void      linux_sys_class_power_supply_init(void);
428
429 typedef struct _Sys_Class_Power_Supply_Uevent Sys_Class_Power_Supply_Uevent;
430
431 #define BASIS_CHARGE  1
432 #define BASIS_ENERGY  2
433 #define BASIS_VOLTAGE 3
434
435 struct _Sys_Class_Power_Supply_Uevent
436 {
437    char             *name;
438    int               fd;
439    Ecore_Fd_Handler *fd_handler;
440
441    int               present;
442
443    int               basis;
444    int               basis_empty;
445    int               basis_full;
446
447    unsigned char     have_current_avg : 1;
448    unsigned char     have_current_now : 1;
449 };
450
451 static Eina_List *events = NULL;
452
453 #if 0
454 static Ecore_Timer *sys_class_delay_check = NULL;
455
456 static Eina_Bool
457 linux_sys_class_power_supply_cb_delay_check(void *data)
458 {
459    linux_sys_class_power_supply_init();
460    poll_cb(NULL);
461    sys_class_delay_check = NULL;
462    return ECORE_CALLBACK_CANCEL;
463 }
464
465 static Ecore_Timer *re_init_timer = NULL;
466
467 static Eina_Bool
468 linux_sys_class_power_supply_cb_re_init(void *data)
469 {
470    Sys_Class_Power_Supply_Uevent *sysev;
471
472    if (events)
473      {
474         EINA_LIST_FREE(events, sysev)
475           {
476 //           if (sysev->fd_handler)
477 //             ecore_main_fd_handler_del(sysev->fd_handler);
478 //           if (sysev->fd >= 0) close(sysev->fd);
479                    free(sysev->name);
480                    free(sysev);
481           }
482      }
483    linux_sys_class_power_supply_init();
484    re_init_timer = NULL;
485    return ECORE_CALLBACK_CANCEL;
486 }
487
488 static Eina_Bool
489 linux_sys_class_power_supply_cb_event_fd_active(void             *data,
490                                                 Ecore_Fd_Handler *fd_handler)
491 {
492    Sys_Class_Power_Supply_Uevent *sysev;
493
494    sysev = data;
495    if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
496      {
497         int lost = 0;
498         for (;; )
499           {
500              char buf[1024];
501              int num;
502
503              if ((num = read(sysev->fd, buf, sizeof(buf))) < 1)
504                {
505                   lost = ((errno == EIO) ||
506                           (errno == EBADF) ||
507                           (errno == EPIPE) ||
508                           (errno == EINVAL) ||
509                           (errno == ENOSPC) ||
510                           (errno == ENODEV));
511                   if (num <= 0) break;
512                }
513           }
514         if (lost)
515           {
516              events = eina_list_remove(events, sysev);
517
518 //           if (sysev->fd_handler)
519 //             ecore_main_fd_handler_del(sysev->fd_handler);
520 //           if (sysev->fd >= 0) close(sysev->fd);
521              free(sysev->name);
522              free(sysev);
523
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);
526           }
527         else
528           {
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);
531           }
532      }
533    return ECORE_CALLBACK_CANCEL;
534 }
535
536 #endif
537 static void
538 linux_sys_class_power_supply_sysev_init(Sys_Class_Power_Supply_Uevent *sysev)
539 {
540    char buf[4096];
541    const char *dir = sys_power_dir;
542
543    sysev->basis = 0;
544    sysev->have_current_avg = 0;
545    sysev->have_current_now = 0;
546
547    snprintf(buf, sizeof(buf), "%s/%s/present", dir, sysev->name);
548    sysev->present = int_file_get(buf);
549    if (!sysev->present) return;
550
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;
555
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;
560
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;
565
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;
570
571    if (sysev->basis == BASIS_CHARGE)
572      {
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)
578           {
579              snprintf(buf, sizeof(buf), "%s/%s/charge_full_design", dir, sysev->name);
580              sysev->basis_full = int_file_get(buf);
581           }
582         if (sysev->basis_empty < 0)
583           {
584              snprintf(buf, sizeof(buf), "%s/%s/charge_empty_design", dir, sysev->name);
585              sysev->basis_empty = int_file_get(buf);
586           }
587      }
588    else if (sysev->basis == BASIS_ENERGY)
589      {
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)
595           {
596              snprintf(buf, sizeof(buf), "%s/%s/energy_full_design", dir, sysev->name);
597              sysev->basis_full = int_file_get(buf);
598           }
599         if (sysev->basis_empty < 0)
600           {
601              snprintf(buf, sizeof(buf), "%s/%s/energy_empty_design", dir, sysev->name);
602              sysev->basis_empty = int_file_get(buf);
603           }
604      }
605    else if (sysev->basis == BASIS_VOLTAGE)
606      {
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)
612           {
613              snprintf(buf, sizeof(buf), "%s/%s/voltage_max_design", dir, sysev->name);
614              sysev->basis_full = int_file_get(buf);
615           }
616         if (sysev->basis_empty < 0)
617           {
618              snprintf(buf, sizeof(buf), "%s/%s/voltage_min_design", dir, sysev->name);
619              sysev->basis_empty = int_file_get(buf);
620           }
621      }
622 }
623
624 static int
625 linux_sys_class_power_supply_is_battery(char *name)
626 {
627    int fd;
628    int ret = 0;
629    char buf[256];
630    const char *dir = sys_power_dir;
631
632    snprintf(buf, sizeof(buf), "%s/%s/type", dir, name);
633    fd = open(buf, O_RDONLY);
634    if (fd < 0)
635      {
636         ret = 0;
637         goto NO_OPEN;
638      }
639    else if (read(fd, buf, sizeof(buf)) < 1)
640      ret = 0;
641    else if (!strncmp(buf, "Battery", 7))
642      ret = 1;
643
644    close(fd);
645
646 NO_OPEN:
647    return ret;
648 }
649
650 static void
651 linux_sys_class_power_supply_init(void)
652 {
653    Eina_List *l;
654
655    if (events)
656      {
657         Sys_Class_Power_Supply_Uevent *sysev;
658
659         EINA_LIST_FOREACH(events, l, sysev)
660           linux_sys_class_power_supply_sysev_init(sysev);
661      }
662    else
663      {
664         Eina_List *bats;
665         char *name;
666 //      char buf[4096];
667
668         bats = ecore_file_ls("/sys/class/power_supply/");
669 //        bats = ecore_file_ls("./TST");
670         if (bats)
671           {
672              events = NULL;
673
674              EINA_LIST_FREE(bats, name)
675                {
676                   Sys_Class_Power_Supply_Uevent *sysev;
677
678                   if (!(linux_sys_class_power_supply_is_battery(name)))
679                     {
680                        free(name);
681                        continue;
682                     }
683
684                   sysev = (Sys_Class_Power_Supply_Uevent *)calloc(1, sizeof(Sys_Class_Power_Supply_Uevent));
685                   sysev->name = name;
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,
690 //                                                                ECORE_FD_READ,
691 //                                                                linux_sys_class_power_supply_cb_event_fd_active,
692 //                                                                sysev,
693 //                                                                NULL, NULL);
694                   events = eina_list_append(events, sysev);
695                   linux_sys_class_power_supply_sysev_init(sysev);
696                }
697           }
698      }
699 }
700
701 static void
702 linux_sys_class_power_supply_check(void)
703 {
704    Eina_List *l;
705    char *name;
706    char buf[4096];
707    const char *dir = sys_power_dir;
708
709    battery_full = -1;
710    time_left = -1;
711    have_battery = 0;
712    have_power = 0;
713
714    if (events)
715      {
716         Sys_Class_Power_Supply_Uevent *sysev;
717         int total_pwr_now;
718         int total_pwr_max;
719         int nofull = 0;
720
721         total_pwr_now = 0;
722         total_pwr_max = 0;
723         time_left = 0;
724         EINA_LIST_FOREACH(events, l, sysev)
725           {
726              char *tmp;
727              int present = 0;
728              int charging = -1;
729              int capacity = -1;
730              int current = -1;
731              int time_to_full = -1;
732              int time_to_empty = -1;
733              int full = -1;
734              int pwr_now = -1;
735              int pwr_empty = -1;
736              int pwr_full = -1;
737              int pwr = 0;
738
739              name = sysev->name;
740
741              /* fetch more generic info */
742              // init
743              present = sysev->present;
744              if (!present) continue;
745
746              snprintf(buf, sizeof(buf), "%s/%s/capacity", dir, name);
747              capacity = int_file_get(buf);
748              if (sysev->have_current_avg)
749                {
750                   snprintf(buf, sizeof(buf), "%s/%s/current_avg", dir, name);
751                   current = int_file_get(buf);
752                }
753              else if (sysev->have_current_now)
754                {
755                   snprintf(buf, sizeof(buf), "%s/%s/current_now", dir, name);
756                   current = int_file_get(buf);
757                }
758
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);
763              if (tmp)
764                {
765                   full = 0;
766                   if (!strncasecmp("discharging", tmp, 11)) charging = 0;
767                   else if (!strncasecmp("unknown", tmp, 7))
768                     charging = 0;
769                   else if (!strncasecmp("not charging", tmp, 12))
770                     charging = 0;
771                   else if (!strncasecmp("charging", tmp, 8))
772                     charging = 1;
773                   else if (!strncasecmp("full", tmp, 4))
774                     {
775                        full = 1;
776                        charging = 0;
777                     }
778                   free(tmp);
779                }
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 */
783              if (!full)
784                {
785                   nofull++;
786                   if (charging)
787                     {
788                        snprintf(buf, sizeof(buf), "%s/%s/time_to_full_now", dir, name);
789                        time_to_full = int_file_get(buf);
790                     }
791                   else
792                     {
793                        snprintf(buf, sizeof(buf), "%s/%s/time_to_empty_now", dir, name);
794                        time_to_empty = int_file_get(buf);
795                     }
796                }
797
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) &&
810                  (capacity >= 0))
811                {
812                   /* if we use voltage as basis.. we're not very accurate
813                    * so we should prefer capacity readings */
814                   pwr_empty = -1;
815                   pwr_full = -1;
816                   pwr_now = -1;
817                }
818
819              if (pwr_empty < 0) pwr_empty = 0;
820
821              if ((pwr_full > 0) && (pwr_full > pwr_empty))
822                {
823                   if (full) pwr_now = pwr_full;
824                   else
825                     {
826                        if (pwr_now < 0)
827                           pwr_now = (((long long)capacity * ((long long)pwr_full - (long long)pwr_empty)) / 100) + pwr_empty;
828                     }
829                   
830                   if (sysev->present) have_battery = 1;
831                   if (charging)
832                     {
833                        pwr_now = pwr_now;
834                        have_power = 1;
835                        if (time_to_full >= 0)
836                          {
837                             if (time_to_full > time_left)
838                                time_left = time_to_full;
839                          }
840                        else
841                          {
842                             if (current == 0) time_left = 0;
843                             else if (current < 0)
844                                time_left = -1;
845                             else
846                               {
847                                  pwr = (((long long)pwr_full - (long long)pwr_now) * 3600) / -current;
848                                  if (pwr > time_left) time_left = pwr;
849                               }
850                          }
851                     }
852                   else
853                     {
854                        have_power = 0;
855                        if (time_to_empty >= 0) time_left += time_to_empty;
856                        else
857                          {
858                             if (time_to_empty < 0)
859                               {
860                                  if (current > 0)
861                                    {
862                                       pwr = (((long long)pwr_now - (long long)pwr_empty) * 3600) / current;
863                                       time_left += pwr;
864                                    }
865                               }
866                          }
867                     }
868                   total_pwr_now += pwr_now - pwr_empty;
869                   total_pwr_max += pwr_full - pwr_empty;
870                }
871              /* simple current battery fallback */
872              else
873                {
874                   if (sysev->present) have_battery = 1;
875                   if (charging) have_power = 1;
876                   total_pwr_max = 100;
877                   total_pwr_now = capacity;
878                   if (total_pwr_now < 100) nofull = 1;
879                }
880           }
881         if (total_pwr_max > 0)
882           battery_full = ((long long)total_pwr_now * 100) / total_pwr_max;
883         if (nofull == 0)
884           time_left = -1;
885      }
886 }
887
888 /***---***/
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
893  */
894 static Eina_Bool linux_acpi_cb_acpid_add(void *data,
895                                          int   type,
896                                          void *event);
897 static Eina_Bool linux_acpi_cb_acpid_del(void *data,
898                                          int   type,
899                                          void *event);
900 static Eina_Bool linux_acpi_cb_acpid_data(void *data,
901                                           int   type,
902                                           void *event);
903 static void linux_acpi_init(void);
904 static void linux_acpi_check(void);
905
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;
915
916 static Eina_Bool
917 linux_acpi_cb_delay_check(void *data __UNUSED__)
918 {
919    linux_acpi_init();
920    poll_cb(NULL);
921    delay_check = NULL;
922    return ECORE_CALLBACK_CANCEL;
923 }
924
925 static Eina_Bool
926 linux_acpi_cb_acpid_add(void *data  __UNUSED__,
927                         int type    __UNUSED__,
928                         void *event __UNUSED__)
929 {
930    return ECORE_CALLBACK_PASS_ON;
931 }
932
933 static Eina_Bool
934 linux_acpi_cb_acpid_del(void *data  __UNUSED__,
935                         int type    __UNUSED__,
936                         void *event __UNUSED__)
937 {
938    ecore_con_server_del(acpid);
939    acpid = NULL;
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;
947 }
948
949 static Eina_Bool
950 linux_acpi_cb_acpid_data(void *data  __UNUSED__,
951                          int type    __UNUSED__,
952                          void *event __UNUSED__)
953 {
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;
957 }
958
959 static Eina_Bool
960 linux_acpi_cb_event_fd_active(void *data        __UNUSED__,
961                               Ecore_Fd_Handler *fd_handler)
962 {
963    if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
964      {
965         int lost = 0;
966         for (;; )
967           {
968              char buf[1024];
969              int num;
970
971              if ((num = read(event_fd, buf, sizeof(buf))) < 1)
972                {
973                   lost = ((errno == EIO) ||
974                           (errno == EBADF) ||
975                           (errno == EPIPE) ||
976                           (errno == EINVAL) ||
977                           (errno == ENOSPC));
978                   if (num == 0) break;
979                }
980           }
981         if (lost)
982           {
983              ecore_main_fd_handler_del(event_fd_handler);
984              event_fd_handler = NULL;
985              close(event_fd);
986              event_fd = -1;
987           }
988         else
989           {
990              if (delay_check) ecore_timer_del(delay_check);
991              delay_check = ecore_timer_add(0.2, linux_acpi_cb_delay_check, NULL);
992           }
993      }
994    return ECORE_CALLBACK_RENEW;
995 }
996
997 static void
998 linux_acpi_init(void)
999 {
1000    Eina_List *powers;
1001    Eina_List *bats;
1002
1003    bats = ecore_file_ls("/proc/acpi/battery");
1004    if (bats)
1005      {
1006         char *name;
1007
1008         have_power = 0;
1009         powers = ecore_file_ls("/proc/acpi/ac_adapter");
1010         if (powers)
1011           {
1012              char *name;
1013
1014              EINA_LIST_FREE(powers, name)
1015                {
1016                   char buf[4096];
1017                   FILE *f;
1018
1019                   snprintf(buf, sizeof(buf), "/proc/acpi/ac_adapter/%s/state", name);
1020                   f = fopen(buf, "r");
1021                   if (f)
1022                     {
1023                        char *tmp;
1024
1025      /* state */
1026                        tmp = fgets(buf, sizeof(buf), f);
1027                        if (tmp) tmp = str_get(tmp);
1028                        if (tmp)
1029                          {
1030                             if (!strcmp(tmp, "on-line")) have_power = 1;
1031                             free(tmp);
1032                          }
1033                     }
1034
1035                   free(name);
1036                }
1037           }
1038
1039         have_battery = 0;
1040         acpi_max_full = 0;
1041         acpi_max_design = 0;
1042         EINA_LIST_FREE(bats, name)
1043           {
1044              char buf[4096];
1045              FILE *f;
1046
1047              snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/info", name);
1048              f = fopen(buf, "r");
1049              if (f)
1050                {
1051                   char *tmp;
1052
1053      /* present */
1054                   tmp = fgets(buf, sizeof(buf), f);
1055                   if (tmp) tmp = str_get(tmp);
1056                   if (tmp)
1057                     {
1058                        if (!strcmp(tmp, "yes")) have_battery = 1;
1059                        free(tmp);
1060                     }
1061      /* design cap */
1062                   tmp = fgets(buf, sizeof(buf), f);
1063                   if (tmp) tmp = str_get(tmp);
1064                   if (tmp)
1065                     {
1066                        if (strcmp(tmp, "unknown")) acpi_max_design += atoi(tmp);
1067                        free(tmp);
1068                     }
1069      /* last full 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_full += atoi(tmp);
1075                        free(tmp);
1076                     }
1077                   fclose(f);
1078                }
1079
1080              free(name);
1081           }
1082      }
1083    if (!acpid)
1084      {
1085         acpid = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM,
1086                                          "/var/run/acpid.socket", -1, NULL);
1087         if (acpid)
1088           {
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);
1095           }
1096         else
1097           {
1098              if (event_fd < 0)
1099                {
1100                   event_fd = open("/proc/acpi/event", O_RDONLY);
1101                   if (event_fd >= 0)
1102                     event_fd_handler = ecore_main_fd_handler_add(event_fd,
1103                                                                  ECORE_FD_READ,
1104                                                                  linux_acpi_cb_event_fd_active,
1105                                                                  NULL,
1106                                                                  NULL, NULL);
1107                }
1108           }
1109      }
1110 }
1111
1112 static void
1113 linux_acpi_check(void)
1114 {
1115    Eina_List *bats;
1116
1117    battery_full = -1;
1118    time_left = -1;
1119    have_battery = 0;
1120    have_power = 0;
1121
1122    bats = ecore_file_ls("/proc/acpi/battery");
1123    if (bats)
1124      {
1125         char *name;
1126         int rate = 0;
1127         int capacity = 0;
1128
1129         EINA_LIST_FREE(bats, name)
1130           {
1131              char buf[4096];
1132              char *tmp;
1133              FILE *f;
1134
1135              snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name);
1136              free(name);
1137              f = fopen(buf, "r");
1138              if (!f) continue;
1139
1140              tmp = file_str_entry_get(f, "present:");
1141              if (!tmp) goto fclose_and_continue;
1142              if (!strcasecmp(tmp, "yes")) have_battery = 1;
1143              free(tmp);
1144
1145              tmp = file_str_entry_get(f, "capacity state:");
1146              if (!tmp) goto fclose_and_continue;
1147              free(tmp);
1148
1149              tmp = file_str_entry_get(f, "charging state:");
1150              if (!tmp) goto fclose_and_continue;
1151              if ((have_power == 0) && (!strcasecmp(tmp, "charging")))
1152                have_power = 1;
1153              free(tmp);
1154
1155              tmp = file_str_entry_get(f, "present rate:");
1156              if (!tmp) goto fclose_and_continue;
1157              if (strcasecmp(tmp, "unknown")) rate += atoi(tmp);
1158              free(tmp);
1159
1160              tmp = file_str_entry_get(f, "remaining capacity:");
1161              if (!tmp) goto fclose_and_continue;
1162              if (strcasecmp(tmp, "unknown")) capacity += atoi(tmp);
1163              free(tmp);
1164
1165 fclose_and_continue:
1166              fclose(f);
1167           }
1168
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;
1173         else
1174           battery_full = -1;
1175         if (rate <= 0) time_left = -1;
1176         else
1177           {
1178              if (have_power)
1179                time_left = (3600 * ((long long)acpi_max_full - (long long)capacity)) / rate;
1180              else
1181                time_left = (3600 * (long long)capacity) / rate;
1182           }
1183      }
1184 }
1185
1186 /***---***/
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);
1193
1194 static void
1195 linux_apm_init(void)
1196 {
1197    /* nothing to do */
1198 }
1199
1200 static void
1201 linux_apm_check(void)
1202 {
1203    FILE *f;
1204    char s1[32], s2[32], s3[32], *endptr;
1205    int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val;
1206
1207    battery_full = -1;
1208    time_left = -1;
1209    have_battery = 0;
1210    have_power = 0;
1211
1212    f = fopen("/proc/apm", "r");
1213    if (!f) return;
1214
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)
1217      {
1218         fclose(f);
1219         return;
1220      }
1221    fclose(f);
1222
1223    bat_val = strtol(s1, &endptr, 10);
1224    if (*endptr != '%') return;
1225
1226    if (!strcmp(s3, "sec")) time_val = atoi(s2);
1227    else if (!strcmp(s3, "min"))
1228      time_val = atoi(s2) * 60;
1229    else time_val = 0;
1230
1231    if ((bat_flags != 0xff) && (bat_flags & 0x80))
1232      {
1233         have_battery = 0;
1234         have_power = 0;
1235         battery_full = 100;
1236         time_left = 0;
1237         return;
1238      }
1239
1240    if (bat_val >= 0)
1241      {
1242         have_battery = 1;
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;
1248      }
1249    else
1250      {
1251         switch (bat_stat)
1252           {
1253            case 0: /* high */
1254              have_battery = 1;
1255              have_power = ac_stat;
1256              battery_full = 100;
1257              time_left = -1;
1258              break;
1259
1260            case 1: /* medium */
1261              have_battery = 1;
1262              have_power = ac_stat;
1263              battery_full = 50;
1264              time_left = -1;
1265              break;
1266
1267            case 2: /* low */
1268              have_battery = 1;
1269              have_power = ac_stat;
1270              battery_full = 25;
1271              time_left = -1;
1272              break;
1273
1274            case 3: /* charging */
1275              have_battery = 1;
1276              have_power = ac_stat;
1277              battery_full = 100;
1278              time_left = -1;
1279              break;
1280           }
1281      }
1282 }
1283
1284 /***---***/
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);
1289
1290 static void
1291 linux_pmu_init(void)
1292 {
1293    /* nothing to do */
1294 }
1295
1296 static void
1297 linux_pmu_check(void)
1298 {
1299    FILE *f;
1300    char buf[4096];
1301    Eina_List *bats;
1302    char *name;
1303    int ac = 0;
1304    int charge = 0;
1305    int max_charge = 0;
1306    int seconds = 0;
1307    int curcharge = 0;
1308    int curmax = 0;
1309
1310    f = fopen("/proc/pmu/info", "r");
1311    if (f)
1312      {
1313         char *tmp;
1314         /* Skip driver */
1315         tmp = fgets(buf, sizeof(buf), f);
1316         if (!tmp)
1317           {
1318              EINA_LOG_ERR("no driver info in /proc/pmu/info");
1319              goto fclose_and_continue;
1320           }
1321         /* Skip firmware */
1322         tmp = fgets(buf, sizeof(buf), f);
1323         if (!tmp)
1324           {
1325              EINA_LOG_ERR("no firmware info in /proc/pmu/info");
1326              goto fclose_and_continue;
1327           }
1328         /* Read ac */
1329         tmp = fgets(buf, sizeof(buf), f);
1330         if (!tmp)
1331           {
1332              EINA_LOG_ERR("no AC info in /proc/pmu/info");
1333              goto fclose_and_continue;
1334           }
1335         ac = int_get(buf);
1336 fclose_and_continue:
1337         fclose(f);
1338      }
1339    bats = ecore_file_ls("/proc/pmu");
1340    if (bats)
1341      {
1342         have_battery = 1;
1343         have_power = ac;
1344         EINA_LIST_FREE(bats, name)
1345           {
1346              if (strncmp(name, "battery", 7)) continue;
1347              snprintf(buf, sizeof(buf), "/proc/pmu/%s", name);
1348              f = fopen(buf, "r");
1349              if (f)
1350                {
1351                   int timeleft = 0;
1352                   int current = 0;
1353
1354                   while (fgets(buf, sizeof (buf), f))
1355                     {
1356                        char *token;
1357
1358                        if ((token = strtok(buf, ":")))
1359                          {
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, ": "));
1368                             else
1369                               strtok(0, ": ");
1370                          }
1371                     }
1372                   curmax += max_charge;
1373                   curcharge += charge;
1374                   fclose(f);
1375                   if (!current)
1376                     {
1377      /* Neither charging nor discharging */
1378                     }
1379                   else if (!ac)
1380                     {
1381      /* When on dc, we are discharging */
1382                         seconds += timeleft;
1383                     }
1384                   else
1385                     {
1386      /* Charging - works in parallel */
1387                         seconds = MAX(timeleft, seconds);
1388                     }
1389                }
1390
1391              free(name);
1392           }
1393         if (max_charge > 0) battery_full = ((long long)charge * 100) / max_charge;
1394         else battery_full = 0;
1395         time_left = seconds;
1396      }
1397    else
1398      {
1399         have_power = ac;
1400         have_battery = 0;
1401         battery_full = -1;
1402         time_left = -1;
1403      }
1404 }
1405
1406 #endif
1407
1408 static int
1409 dir_has_contents(const char *dir)
1410 {
1411    Eina_List *bats;
1412    char *file;
1413    int count;
1414
1415    bats = ecore_file_ls(dir);
1416
1417    count = eina_list_count(bats);
1418    EINA_LIST_FREE(bats, file)
1419      free(file);
1420    if (count > 0) return 1;
1421    return 0;
1422 }
1423
1424 static void
1425 init(void)
1426 {
1427 #ifdef __FreeBSD__
1428    int acline;
1429    size_t len;
1430
1431    len = sizeof(acline);
1432    if (!sysctlbyname("hw.acpi.acline", &acline, &len, NULL, 0))
1433      {
1434         int acline_mib[3] = {-1};
1435
1436         len = 3;
1437         if (!sysctlnametomib("hw.acpi.acline", acline_mib, &len))
1438           {
1439              mode = CHECK_ACPI;
1440              bsd_acpi_init();
1441           }
1442      }
1443    else
1444      {
1445 #ifdef __i386__
1446         if (ecore_file_exists("/dev/apm"))
1447           {
1448              mode = CHECK_APM;
1449              bsd_apm_init();
1450           }
1451 #endif
1452      }
1453 #elif defined(HAVE_CFBASE_H) /* OS X */
1454    darwin_init();
1455 #else
1456    if ((ecore_file_is_dir(sys_power_dir)) && (dir_has_contents(sys_power_dir)))
1457      {
1458         mode = CHECK_SYS_CLASS_POWER_SUPPLY;
1459         linux_sys_class_power_supply_init();
1460      }
1461    else if (ecore_file_is_dir("/proc/acpi")) /* <= 2.6.24 */
1462      {
1463         mode = CHECK_ACPI;
1464         linux_acpi_init();
1465      }
1466    else if (ecore_file_exists("/proc/apm"))
1467      {
1468         mode = CHECK_APM;
1469         linux_apm_init();
1470      }
1471    else if (ecore_file_is_dir("/proc/pmu"))
1472      {
1473         mode = CHECK_PMU;
1474         linux_pmu_init();
1475      }
1476 #endif
1477 }
1478
1479 static Eina_Bool
1480 poll_cb(void *data __UNUSED__)
1481 {
1482    int ptime_left;
1483    int pbattery_full;
1484    int phave_battery;
1485    int phave_power;
1486
1487    ptime_left = time_left;
1488    pbattery_full = battery_full;
1489    phave_battery = have_battery;
1490    phave_power = have_power;
1491
1492 #ifdef __FreeBSD__
1493    switch (mode)
1494      {
1495       case CHECK_ACPI:
1496         bsd_acpi_check();
1497         break;
1498
1499 #ifdef __i386__
1500       case CHECK_APM:
1501         bsd_apm_check();
1502         break;
1503
1504 #endif
1505       default:
1506         battery_full = -1;
1507         time_left = -1;
1508         have_battery = 0;
1509         have_power = 0;
1510         break;
1511      }
1512 #elif defined(HAVE_CFBASE_H) /* OS X */
1513    darwin_check();
1514    return ECORE_CALLBACK_RENEW;
1515 #else
1516    switch (mode)
1517      {
1518       case CHECK_ACPI:
1519         linux_acpi_check();
1520         break;
1521
1522       case CHECK_APM:
1523         linux_apm_check();
1524         break;
1525
1526       case CHECK_PMU:
1527         linux_pmu_check();
1528         break;
1529
1530       case CHECK_SYS_CLASS_POWER_SUPPLY:
1531         linux_sys_class_power_supply_check();
1532         break;
1533
1534       default:
1535         battery_full = -1;
1536         time_left = -1;
1537         have_battery = 0;
1538         have_power = 0;
1539         break;
1540      }
1541 #endif
1542    if ((ptime_left != time_left) ||
1543        (pbattery_full != battery_full) ||
1544        (phave_battery != have_battery) ||
1545        (phave_power != have_power))
1546      {
1547         if ((time_left < 0) &&
1548             ((have_battery) && (battery_full < 0)))
1549           printf("ERROR\n");
1550         else
1551           printf("%i %i %i %i %i\n",
1552                  battery_full, time_left, time_left, have_battery, have_power);
1553         fflush(stdout);
1554      }
1555    return ECORE_CALLBACK_RENEW;
1556 }
1557
1558 int
1559 main(int   argc,
1560      char *argv[])
1561 {
1562    if (argc != 2)
1563      {
1564         printf("ARGS INCORRECT!\n");
1565         return 0;
1566      }
1567    poll_interval = atoi(argv[1]);
1568
1569    ecore_init();
1570    ecore_file_init();
1571    ecore_con_init();
1572
1573    init();
1574    poller = ecore_poller_add(ECORE_POLLER_CORE, poll_interval, poll_cb, NULL);
1575    poll_cb(NULL);
1576
1577    ecore_main_loop_begin();
1578
1579    ecore_con_shutdown();
1580    ecore_file_shutdown();
1581    ecore_shutdown();
1582
1583    return 0;
1584 }
1585