update for beta release
[framework/uifw/e17.git] / src / modules / battery / e_mod_udev.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 static void _battery_udev_event_battery(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch);
5 static void _battery_udev_event_ac(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch);
6 static void _battery_udev_battery_add(const char *syspath);
7 static void _battery_udev_ac_add(const char *syspath);
8 static void _battery_udev_battery_del(const char *syspath);
9 static void _battery_udev_ac_del(const char *syspath);
10 static Eina_Bool _battery_udev_battery_update_poll(void *data);
11 static void _battery_udev_battery_update(const char *syspath, Battery *bat);
12 static void _battery_udev_ac_update(const char *syspath, Ac_Adapter *ac);
13
14 extern Eina_List *device_batteries;
15 extern Eina_List *device_ac_adapters;
16 extern double init_time;
17
18 int 
19 _battery_udev_start(void)
20 {
21    Eina_List *devices;
22    const char *dev;
23    
24    devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_POWER_BAT, NULL);
25    EINA_LIST_FREE(devices, dev)
26      _battery_udev_battery_add(dev);
27
28    devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_POWER_AC, NULL);
29    EINA_LIST_FREE(devices, dev)
30      _battery_udev_ac_add(dev);
31
32    if (!battery_config->batwatch)
33      battery_config->batwatch = eeze_udev_watch_add(EEZE_UDEV_TYPE_POWER_BAT, EEZE_UDEV_EVENT_NONE, _battery_udev_event_battery, NULL);
34    if (!battery_config->acwatch)
35      battery_config->acwatch = eeze_udev_watch_add(EEZE_UDEV_TYPE_POWER_AC, EEZE_UDEV_EVENT_NONE, _battery_udev_event_ac, NULL);
36
37    init_time = ecore_time_get();
38    return 1;
39 }
40
41 void 
42 _battery_udev_stop(void)
43 {
44    Ac_Adapter *ac;
45    Battery *bat;
46
47    if (battery_config->batwatch)
48      eeze_udev_watch_del(battery_config->batwatch);
49    if (battery_config->acwatch)
50      eeze_udev_watch_del(battery_config->acwatch);
51
52    EINA_LIST_FREE(device_ac_adapters, ac)
53      {
54         free(ac);
55      }
56    EINA_LIST_FREE(device_batteries, bat)
57      {
58         eina_stringshare_del(bat->udi);
59         eina_stringshare_del(bat->technology);
60         eina_stringshare_del(bat->model);
61         eina_stringshare_del(bat->vendor);
62         ecore_poller_del(bat->poll);
63         free(bat);
64      }
65 }
66
67
68 static void 
69 _battery_udev_event_battery(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch __UNUSED__)
70 {
71    if ((event & EEZE_UDEV_EVENT_ADD) ||
72        (event & EEZE_UDEV_EVENT_ONLINE))
73      _battery_udev_battery_add(syspath);
74    else if ((event & EEZE_UDEV_EVENT_REMOVE) ||
75             (event & EEZE_UDEV_EVENT_OFFLINE))
76      _battery_udev_battery_del(syspath);
77    else /* must be change */
78      _battery_udev_battery_update(syspath, data);
79 }
80
81 static void 
82 _battery_udev_event_ac(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch __UNUSED__)
83 {
84    if ((event & EEZE_UDEV_EVENT_ADD) ||
85        (event & EEZE_UDEV_EVENT_ONLINE))
86      _battery_udev_ac_add(syspath);
87    else if ((event & EEZE_UDEV_EVENT_REMOVE) ||
88             (event & EEZE_UDEV_EVENT_OFFLINE))
89      _battery_udev_ac_del(syspath);
90    else /* must be change */
91      _battery_udev_ac_update(syspath, data);
92 }
93
94 static void 
95 _battery_udev_battery_add(const char *syspath)
96 {
97    Battery *bat;
98
99    if ((bat = _battery_battery_find(syspath)))
100      {
101         eina_stringshare_del(syspath);
102         _battery_udev_battery_update(NULL, bat);
103         return;
104      }
105
106    if (!(bat = E_NEW(Battery, 1)))
107      {
108         eina_stringshare_del(syspath);
109         return;
110      }
111    bat->last_update = ecore_time_get();
112    bat->udi = eina_stringshare_add(syspath);
113    bat->poll = ecore_poller_add(ECORE_POLLER_CORE, 
114                                 battery_config->poll_interval, 
115                                 _battery_udev_battery_update_poll, bat);
116    device_batteries = eina_list_append(device_batteries, bat);
117    _battery_udev_battery_update(syspath, bat);
118 }
119
120 static void 
121 _battery_udev_ac_add(const char *syspath)
122 {
123    Ac_Adapter *ac;
124
125    if ((ac = _battery_ac_adapter_find(syspath)))
126      {
127         eina_stringshare_del(syspath);
128         _battery_udev_ac_update(NULL, ac);
129         return;
130      }
131
132    if (!(ac = E_NEW(Ac_Adapter, 1)))
133      {
134         eina_stringshare_del(syspath);
135         return;
136      }
137    ac->udi = eina_stringshare_add(syspath);
138    device_ac_adapters = eina_list_append(device_ac_adapters, ac);
139    _battery_udev_ac_update(syspath, ac);
140 }
141
142 static void 
143 _battery_udev_battery_del(const char *syspath)
144 {
145    Battery *bat;
146
147    if (!(bat = _battery_battery_find(syspath)))
148      {
149         eina_stringshare_del(syspath);
150         _battery_device_update();
151         return;
152      }
153
154    device_batteries = eina_list_remove(device_batteries, bat);
155    eina_stringshare_del(bat->udi);
156    eina_stringshare_del(bat->technology);
157    eina_stringshare_del(bat->model);
158    eina_stringshare_del(bat->vendor);
159    ecore_poller_del(bat->poll);
160    free(bat);
161 }
162
163 static void 
164 _battery_udev_ac_del(const char *syspath)
165 {
166    Ac_Adapter *ac;
167
168    if (!(ac = _battery_ac_adapter_find(syspath)))
169      {
170         eina_stringshare_del(syspath);
171         _battery_device_update();
172         return;
173      }
174
175    device_ac_adapters = eina_list_remove(device_ac_adapters, ac);
176    eina_stringshare_del(ac->udi);
177    free(ac);
178 }
179
180 static Eina_Bool 
181 _battery_udev_battery_update_poll(void *data)
182 {
183    _battery_udev_battery_update(NULL, data);
184
185    return EINA_TRUE;
186 }
187
188 #define GET_NUM(TYPE, VALUE, PROP) test = eeze_udev_syspath_get_property(TYPE->udi, #PROP); \
189   do \
190     if (test) \
191       { \
192          TYPE->VALUE = strtod(test, NULL); \
193       } \
194   while (0)
195
196 #define GET_STR(TYPE, VALUE, PROP) TYPE->VALUE = eeze_udev_syspath_get_property(TYPE->udi, #PROP)
197   
198 static void 
199 _battery_udev_battery_update(const char *syspath, Battery *bat)
200 {
201    const char *test;
202    double time, charge;
203    
204    if (!bat)
205      {
206         if (!(bat = _battery_battery_find(syspath)))
207           return _battery_udev_battery_add(syspath);
208      }
209    /* update the poller interval */
210    ecore_poller_poller_interval_set(bat->poll, battery_config->poll_interval);
211    
212    GET_NUM(bat, present, POWER_SUPPLY_PRESENT);
213    if (!bat->got_prop)
214      {/* only need to get these once */
215         GET_STR(bat, technology, POWER_SUPPLY_TECHNOLOGY);
216         GET_STR(bat, model, POWER_SUPPLY_MODEL_NAME);
217         GET_STR(bat, vendor, POWER_SUPPLY_MANUFACTURER);
218         GET_NUM(bat, design_charge, POWER_SUPPLY_ENERGY_FULL_DESIGN);
219         if (!bat->design_charge)
220           GET_NUM(bat, design_charge, POWER_SUPPLY_CHARGE_FULL_DESIGN);
221      }
222    GET_NUM(bat, last_full_charge, POWER_SUPPLY_ENERGY_FULL);
223    if (!bat->last_full_charge)
224      GET_NUM(bat, last_full_charge, POWER_SUPPLY_CHARGE_FULL);
225    test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_ENERGY_NOW");
226    if (!test)
227      {
228         eina_stringshare_del(test);
229         test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_CHARGE_NOW");
230      }
231    if (test)
232      {
233
234         charge = strtod(test, NULL);
235         eina_stringshare_del(test);
236         time = ecore_time_get();
237         if ((bat->got_prop) && (charge != bat->current_charge))
238           bat->charge_rate = ((charge - bat->current_charge) / (time - bat->last_update));
239         bat->last_update = time;
240         bat->current_charge = charge;
241         bat->percent = 100 * (bat->current_charge / bat->last_full_charge);
242         if (bat->got_prop)
243           {
244              if (bat->charge_rate > 0)
245                {
246                   if (battery_config->fuzzy && (++battery_config->fuzzcount <= 10) && (bat->time_full > 0))
247                     bat->time_full = (((bat->last_full_charge - bat->current_charge) / bat->charge_rate) + bat->time_full) / 2;
248                   else
249                     bat->time_full = (bat->last_full_charge - bat->current_charge) / bat->charge_rate;
250                   bat->time_left = -1;
251                }
252              else
253                {
254                   if (battery_config->fuzzy && (battery_config->fuzzcount <= 10) && (bat->time_left > 0))
255                     bat->time_left = (((0 - bat->current_charge) / bat->charge_rate) + bat->time_left) / 2;
256                   else
257                     bat->time_left = (0 - bat->current_charge) / bat->charge_rate;
258                   bat->time_full = -1;
259                }
260           }
261         else
262           {
263              bat->time_full = -1;
264              bat->time_left = -1;
265           }
266      }
267    if (battery_config->fuzzcount > 10) battery_config->fuzzcount = 0;
268    test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_STATUS");
269    if (test)
270      {
271         if (!strcmp(test, "Charging"))
272           bat->charging = 1;
273         else if ((!strcmp(test, "Unknown")) && (bat->charge_rate >= 0))
274             bat->charging = 1;
275         else
276           bat->charging = 0;
277         eina_stringshare_del(test);
278      }
279    else
280      bat->charging = 0;
281    if (bat->got_prop)
282      _battery_device_update();
283    bat->got_prop = 1;
284 }
285
286 static void 
287 _battery_udev_ac_update(const char *syspath, Ac_Adapter *ac)
288 {
289    const char *test;
290    
291    if (!ac)
292      {
293         if (!(ac = _battery_ac_adapter_find(syspath)))
294           return _battery_udev_ac_add(syspath);
295      }
296
297    GET_NUM(ac, present, POWER_SUPPLY_ONLINE);
298    /* yes, it's really that simple. */
299
300    _battery_device_update();
301 }