e: Port battery module to upower and edbus
authorJosé Roberto de Souza <zehortigoza@profusion.mobi>
Wed, 2 Jan 2013 13:14:29 +0000 (13:14 +0000)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 2 Jan 2013 13:14:29 +0000 (13:14 +0000)
Patch by: José Roberto de Souza  <zehortigoza@profusion.mobi>

SVN revision: 81975

configure.ac
src/bin/e.h
src/modules/Makefile_battery.am
src/modules/battery/e_mod_dbus.c [deleted file]
src/modules/battery/e_mod_main.c
src/modules/battery/e_mod_main.h
src/modules/battery/e_mod_upower.c [new file with mode: 0644]

index 475c294..a15c497 100644 (file)
@@ -548,6 +548,7 @@ PKG_CHECK_MODULES(E, [
   eina >= ${efl_version}
   dbus-1
   edbus >= ${efl_version}
+  edbus2 >= ${efl_version}
   eio >= ${efl_version}
   $hal_mount
   $eeze_mount
@@ -570,6 +571,7 @@ efreet-trash >= ${efl_version} \
 eina >= ${efl_version} \
 dbus-1 \
 edbus >= ${efl_version} \
+edbus2 \
 eio >= ${efl_version} \
 $hal_mount \
 $udisks_mount \
index 8a06c4f..f996b75 100644 (file)
@@ -113,6 +113,7 @@ void *alloca (size_t);
 # include <Efreet_Mime.h>
 # include <Edje.h>
 # include <E_DBus.h>
+# include <EDBus.h>
 # include <Eio.h>
 
 # ifdef HAVE_HAL
index fa6c057..d3b39dc 100644 (file)
@@ -18,7 +18,7 @@ else
 if HAVE_OPENBSD
 battery_module_la_SOURCES += battery/e_mod_openbsd.c
 else
-battery_module_la_SOURCES += battery/e_mod_dbus.c
+battery_module_la_SOURCES += battery/e_mod_upower.c
 endif
 endif
 
diff --git a/src/modules/battery/e_mod_dbus.c b/src/modules/battery/e_mod_dbus.c
deleted file mode 100644 (file)
index 06f4c7e..0000000
+++ /dev/null
@@ -1,390 +0,0 @@
-#include "e.h"
-#include "e_mod_main.h"
-
-static void _battery_dbus_battery_props(void *data, void *reply_data, DBusError *error);
-static void _battery_dbus_ac_adapter_props(void *data, void *reply_data, DBusError *error);
-static void _battery_dbus_battery_property_changed(void *data, DBusMessage *msg);
-static void _battery_dbus_battery_add(const char *udi);
-static void _battery_dbus_battery_del(const char *udi);
-static void _battery_dbus_ac_adapter_add(const char *udi);
-static void _battery_dbus_ac_adapter_del(const char *udi);
-static void _battery_dbus_find_battery(void *user_data, void *reply_data, DBusError *err);
-static void _battery_dbus_find_ac(void *user_data, void *reply_data, DBusError *err);
-static void _battery_dbus_is_battery(void *user_data, void *reply_data, DBusError *err);
-static void _battery_dbus_is_ac_adapter(void *user_data, void *reply_data, DBusError *err);
-static void _battery_dbus_dev_add(void *data, DBusMessage *msg);
-static void _battery_dbus_dev_del(void *data, DBusMessage *msg);
-
-extern Eina_List *device_batteries;
-extern Eina_List *device_ac_adapters;
-extern double init_time;
-
-static E_DBus_Connection *e_dbus_conn = NULL;
-
-int
-_battery_dbus_start(void)
-{
-   e_dbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
-   if (!e_dbus_conn) return 0;
-   // FIXME: e_dbus doesn't allow us to track this pending call
-   e_hal_manager_find_device_by_capability
-     (e_dbus_conn, "battery", _battery_dbus_find_battery, NULL);
-   e_hal_manager_find_device_by_capability
-     (e_dbus_conn, "ac_adapter", _battery_dbus_find_ac, NULL);
-   battery_config->dbus.dev_add =
-     e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER,
-                               E_HAL_MANAGER_PATH,
-                               E_HAL_MANAGER_INTERFACE,
-                               "DeviceAdded", _battery_dbus_dev_add, NULL);
-   battery_config->dbus.dev_del =
-     e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER,
-                               E_HAL_MANAGER_PATH,
-                               E_HAL_MANAGER_INTERFACE,
-                               "DeviceRemoved", _battery_dbus_dev_del, NULL);
-   init_time = ecore_time_get();
-   return 1;
-}
-
-void
-_battery_dbus_stop(void)
-{
-   Ac_Adapter *ac;
-   Battery *bat;
-
-   if (!e_dbus_conn) return;
-
-   if (battery_config->dbus.have)
-     {
-        dbus_pending_call_cancel(battery_config->dbus.have);
-        battery_config->dbus.have = NULL;
-     }
-   if (battery_config->dbus.dev_add)
-     {
-        e_dbus_signal_handler_del(e_dbus_conn, battery_config->dbus.dev_add);
-        battery_config->dbus.dev_add = NULL;
-     }
-   if (battery_config->dbus.dev_del)
-     {
-        e_dbus_signal_handler_del(e_dbus_conn, battery_config->dbus.dev_del);
-        battery_config->dbus.dev_del = NULL;
-     }
-   EINA_LIST_FREE(device_ac_adapters, ac)
-     {
-        e_dbus_signal_handler_del(e_dbus_conn, ac->prop_change);
-        eina_stringshare_del(ac->udi);
-        eina_stringshare_del(ac->product);
-        free(ac);
-     }
-   EINA_LIST_FREE(device_batteries, bat)
-     {
-        e_dbus_signal_handler_del(e_dbus_conn, bat->prop_change);
-        eina_stringshare_del(bat->udi);
-        eina_stringshare_del(bat->technology);
-        eina_stringshare_del(bat->type);
-        eina_stringshare_del(bat->charge_units);
-        eina_stringshare_del(bat->model);
-        eina_stringshare_del(bat->vendor);
-        free(bat);
-     }
-   e_dbus_connection_close(e_dbus_conn);
-   e_dbus_conn = NULL;
-}
-
-static void
-_battery_dbus_battery_props(void *data, void *reply_data, DBusError *error __UNUSED__)
-{
-   E_Hal_Properties *ret = reply_data;
-   Battery *bat = data;
-   int err = 0;
-   const char *str;
-
-   if (dbus_error_is_set(error))
-     {
-        dbus_error_free(error);
-        return;
-     }
-   if (!ret) return;
-
-#undef GET_BOOL
-#undef GET_INT
-#undef GET_STR
-#define GET_BOOL(val, s) bat->val = e_hal_property_bool_get(ret, s, &err)
-#define GET_INT(val, s)  bat->val = e_hal_property_int_get(ret, s, &err)
-#define GET_STR(val, s)                          \
-  if (bat->val) eina_stringshare_del(bat->val);  \
-  bat->val = NULL;                               \
-  str = e_hal_property_string_get(ret, s, &err); \
-  if (str)                                       \
-    {                                            \
-       bat->val = eina_stringshare_ref(str);     \
-    }
-
-   GET_BOOL(present, "battery.present");
-   GET_STR(technology, "battery.reporting.technology");
-   GET_STR(model, "battery.model");
-   GET_STR(vendor, "battery.vendor");
-   GET_STR(type, "battery.type");
-   GET_STR(charge_units, "battery.reporting.unit");
-   GET_INT(percent, "battery.charge_level.percentage");
-   GET_BOOL(can_charge, "battery.is_rechargeable");
-   GET_INT(current_charge, "battery.charge_level.current");
-   GET_INT(charge_rate, "battery.charge_level.rate");
-   GET_INT(design_charge, "battery.charge_level.design");
-   GET_INT(last_full_charge, "battery.charge_level.last_full");
-   if (e_hal_property_bool_get(ret, "battery.rechargeable.is_charging", &err))
-     {
-        bat->charging = 1;
-        GET_INT(time_full, "battery.remaining_time");
-        bat->time_left = -1;
-     }
-   else
-     {
-        bat->charging = 0;
-        GET_INT(time_left, "battery.remaining_time");
-        bat->time_full = -1;
-     }
-   bat->got_prop = 1;
-   _battery_device_update();
-}
-
-static void
-_battery_dbus_ac_adapter_props(void *data, void *reply_data, DBusError *error __UNUSED__)
-{
-   E_Hal_Properties *ret = reply_data;
-   Ac_Adapter *ac = data;
-   int err = 0;
-   const char *str;
-
-   if (dbus_error_is_set(error))
-     {
-        dbus_error_free(error);
-        return;
-     }
-   if (!ret) return;
-
-#undef GET_BOOL
-#undef GET_STR
-#define GET_BOOL(val, s) ac->val = e_hal_property_bool_get(ret, s, &err)
-#define GET_STR(val, s)                          \
-  if (ac->val) eina_stringshare_del(ac->val);    \
-  ac->val = NULL;                                \
-  str = e_hal_property_string_get(ret, s, &err); \
-  if (str)                                       \
-    {                                            \
-       ac->val = eina_stringshare_ref(str);      \
-    }
-
-   GET_BOOL(present, "ac_adapter.present");
-   GET_STR(product, "info.product");
-   _battery_device_update();
-}
-
-static void
-_battery_dbus_battery_property_changed(void *data, DBusMessage *msg __UNUSED__)
-{
-   // FIXME: e_dbus doesn't allow us to track this pending call
-   e_hal_device_get_all_properties(e_dbus_conn, ((Battery *)data)->udi,
-                                   _battery_dbus_battery_props, data);
-}
-
-static void
-_battery_dbus_ac_adapter_property_changed(void *data, DBusMessage *msg __UNUSED__)
-{
-   // FIXME: e_dbus doesn't allow us to track this pending call
-   e_hal_device_get_all_properties(e_dbus_conn, ((Ac_Adapter *)data)->udi,
-                                   _battery_dbus_ac_adapter_props, data);
-}
-
-static void
-_battery_dbus_battery_add(const char *udi)
-{
-   Battery *bat;
-
-   bat = _battery_battery_find(udi);
-   if (!bat)
-     {
-        bat = E_NEW(Battery, 1);
-        if (!bat) return;
-        bat->udi = eina_stringshare_add(udi);
-        device_batteries = eina_list_append(device_batteries, bat);
-        bat->prop_change =
-          e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER, udi,
-                                    E_HAL_DEVICE_INTERFACE, "PropertyModified",
-                                    _battery_dbus_battery_property_changed,
-                                    bat);
-     }
-   // FIXME: e_dbus doesn't allow us to track this pending call
-   e_hal_device_get_all_properties(e_dbus_conn, udi,
-                                   _battery_dbus_battery_props, bat);
-
-   _battery_device_update();
-}
-
-static void
-_battery_dbus_battery_del(const char *udi)
-{
-   Battery *bat;
-
-   bat = _battery_battery_find(udi);
-   if (bat)
-     {
-        e_dbus_signal_handler_del(e_dbus_conn, bat->prop_change);
-        device_batteries = eina_list_remove(device_batteries, bat);
-        eina_stringshare_del(bat->udi);
-        eina_stringshare_del(bat->technology);
-        eina_stringshare_del(bat->type);
-        eina_stringshare_del(bat->charge_units);
-        eina_stringshare_del(bat->model);
-        eina_stringshare_del(bat->vendor);
-        free(bat);
-        return;
-     }
-   _battery_device_update();
-}
-
-static void
-_battery_dbus_ac_adapter_add(const char *udi)
-{
-   Ac_Adapter *ac;
-
-   ac = E_NEW(Ac_Adapter, 1);
-   if (!ac) return;
-   ac->udi = eina_stringshare_add(udi);
-   device_ac_adapters = eina_list_append(device_ac_adapters, ac);
-   ac->prop_change =
-     e_dbus_signal_handler_add(e_dbus_conn, E_HAL_SENDER, udi,
-                               E_HAL_DEVICE_INTERFACE, "PropertyModified",
-                               _battery_dbus_ac_adapter_property_changed,
-                               ac);
-   // FIXME: e_dbus doesn't allow us to track this pending call
-   e_hal_device_get_all_properties(e_dbus_conn, udi,
-                                   _battery_dbus_ac_adapter_props, ac);
-   _battery_device_update();
-}
-
-static void
-_battery_dbus_ac_adapter_del(const char *udi)
-{
-   Ac_Adapter *ac;
-
-   ac = _battery_ac_adapter_find(udi);
-   if (ac)
-     {
-        e_dbus_signal_handler_del(e_dbus_conn, ac->prop_change);
-        device_ac_adapters = eina_list_remove(device_ac_adapters, ac);
-        eina_stringshare_del(ac->udi);
-        eina_stringshare_del(ac->product);
-        free(ac);
-        return;
-     }
-   _battery_device_update();
-}
-
-static void
-_battery_dbus_find_battery(void *user_data __UNUSED__, void *reply_data, DBusError *err __UNUSED__)
-{
-   Eina_List *l;
-   char *device;
-   E_Hal_Manager_Find_Device_By_Capability_Return *ret;
-
-   ret = reply_data;
-   if (dbus_error_is_set(err))
-     {
-        dbus_error_free(err);
-        return;
-     }
-   if (!ret) return;
-
-   if (eina_list_count(ret->strings) < 1) return;
-   EINA_LIST_FOREACH(ret->strings, l, device)
-     _battery_dbus_battery_add(device);
-}
-
-static void
-_battery_dbus_find_ac(void *user_data __UNUSED__, void *reply_data, DBusError *err __UNUSED__)
-{
-   Eina_List *l;
-   char *device;
-   E_Hal_Manager_Find_Device_By_Capability_Return *ret;
-
-   ret = reply_data;
-   if (dbus_error_is_set(err))
-     {
-        dbus_error_free(err);
-        return;
-     }
-   if (!ret) return;
-
-   if (eina_list_count(ret->strings) < 1) return;
-   EINA_LIST_FOREACH(ret->strings, l, device)
-     _battery_dbus_ac_adapter_add(device);
-}
-
-static void
-_battery_dbus_is_battery(void *user_data, void *reply_data, DBusError *err)
-{
-   char *udi = user_data;
-   E_Hal_Device_Query_Capability_Return *ret;
-
-   ret = reply_data;
-   if (dbus_error_is_set(err))
-     {
-        dbus_error_free(err);
-        goto error;
-     }
-   if (!ret) goto error;
-   if (ret->boolean)
-     _battery_dbus_battery_add(udi);
-error:
-   eina_stringshare_del(udi);
-}
-
-static void
-_battery_dbus_is_ac_adapter(void *user_data, void *reply_data, DBusError *err)
-{
-   char *udi = user_data;
-   E_Hal_Device_Query_Capability_Return *ret;
-
-   ret = reply_data;
-   if (dbus_error_is_set(err))
-     {
-        dbus_error_free(err);
-        goto error;
-     }
-   if (!ret) goto error;
-
-   if (ret->boolean)
-     _battery_dbus_ac_adapter_add(udi);
-error:
-   eina_stringshare_del(udi);
-}
-
-static void
-_battery_dbus_dev_add(void *data __UNUSED__, DBusMessage *msg)
-{
-   DBusError err;
-   char *udi = NULL;
-
-   dbus_error_init(&err);
-   dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID);
-   if (!udi) return;
-   // FIXME: e_dbus doesn't allow us to track this pending call
-   e_hal_device_query_capability(e_dbus_conn, udi, "battery",
-                                 _battery_dbus_is_battery, (void *)eina_stringshare_add(udi));
-   e_hal_device_query_capability(e_dbus_conn, udi, "ac_adapter",
-                                 _battery_dbus_is_ac_adapter, (void *)eina_stringshare_add(udi));
-}
-
-static void
-_battery_dbus_dev_del(void *data __UNUSED__, DBusMessage *msg)
-{
-   DBusError err;
-   char *udi = NULL;
-
-   dbus_error_init(&err);
-   dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID);
-   if (!udi) return;
-   _battery_dbus_battery_del(udi);
-   _battery_dbus_ac_adapter_del(udi);
-}
-
index 866dbe6..3d44d81 100644 (file)
@@ -88,9 +88,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
 
 #ifdef HAVE_EEZE
    eeze_init();
-#elif !defined __OpenBSD__
-   e_dbus_init();
-   e_hal_init();
 #endif
 
    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
@@ -109,9 +106,6 @@ _gc_shutdown(E_Gadcon_Client *gcc)
 
 #ifdef HAVE_EEZE
    eeze_shutdown();
-#elif !defined __OpenBSD__
-   e_hal_shutdown();
-   e_dbus_shutdown();
 #endif
 
    inst = gcc->data;
@@ -380,7 +374,7 @@ _battery_config_updated(void)
 #elif defined __OpenBSD__
         ok = _battery_openbsd_start();
 #else
-        ok = _battery_dbus_start();
+        ok = _battery_upower_start();
 #endif
      }
    if (ok) return;
@@ -858,7 +852,7 @@ e_modapi_shutdown(E_Module *m __UNUSED__)
 #elif defined __OpenBSD__
    _battery_openbsd_stop();
 #else
-   _battery_dbus_stop();
+   _battery_upower_stop();
 #endif
 
 #ifdef HAVE_ENOTIFY
index 61c8a77..f4c96b5 100644 (file)
@@ -4,7 +4,7 @@
 #ifdef HAVE_EEZE
 # include <Eeze.h>
 #else
-# include <E_Hal.h>
+# include <EDBus.h>
 #endif
 
 typedef struct _Config       Config;
@@ -58,15 +58,6 @@ struct _Config
 #if defined HAVE_EEZE || defined __OpenBSD__
    Eina_Bool            fuzzy;
    int                  fuzzcount;
-#else
-   struct {
-      // FIXME: on bat_conf del dbus_pending_call_cancel(dbus.have);
-      //        then set dbus.have to NULL
-      DBusPendingCall       *have;
-      // FIXME: on bat_conf del e_dbus_signal_handler_del() these
-      E_DBus_Signal_Handler *dev_add;
-      E_DBus_Signal_Handler *dev_del;
-   } dbus;
 #endif
 };
 
@@ -78,9 +69,6 @@ struct _Battery
    const char *udi;
 #if defined HAVE_EEZE || defined __OpenBSD__
    Ecore_Poller *poll;
-#else
-   E_DBus_Signal_Handler *prop_change;
-   Eina_Bool can_charge:1;
 #endif
    Eina_Bool present:1;
    Eina_Bool charging:1;
@@ -108,6 +96,7 @@ struct _Battery
    const char *model;
    const char *vendor;
    Eina_Bool got_prop:1;
+   EDBus_Proxy *proxy;
 #ifdef __OpenBSD__
    int * mib;
 #endif
@@ -116,11 +105,9 @@ struct _Battery
 struct _Ac_Adapter
 {
    const char *udi;
-#ifndef HAVE_EEZE
-   E_DBus_Signal_Handler *prop_change;
-#endif
    Eina_Bool present:1;
    const char *product;
+   EDBus_Proxy *proxy;
 #ifdef __OpenBSD__
    int * mib;
 #endif
@@ -136,8 +123,8 @@ void _battery_udev_stop(void);
 /* end e_mod_udev.c */
 #elif !defined __OpenBSD__
 /* in e_mod_dbus.c */
-int  _battery_dbus_start(void);
-void _battery_dbus_stop(void);
+int _battery_upower_start(void);
+void _battery_upower_stop(void);
 /* end e_mod_dbus.c */
 #else
 /* in e_mod_openbsd.c */
diff --git a/src/modules/battery/e_mod_upower.c b/src/modules/battery/e_mod_upower.c
new file mode 100644 (file)
index 0000000..2013f31
--- /dev/null
@@ -0,0 +1,363 @@
+#include "e.h"
+#include "e_mod_main.h"
+
+#define BUS "org.freedesktop.UPower"
+#define PATH "/org/freedesktop/UPower"
+#define IFACE "org.freedesktop.UPower"
+
+extern Eina_List *device_batteries;
+extern Eina_List *device_ac_adapters;
+extern double init_time;
+
+static EDBus_Connection *conn;
+static EDBus_Proxy *upower_proxy;
+
+static void _battery_free(Battery *bat);
+static void _ac_free(Ac_Adapter *ac);
+
+static void
+_ac_get_all_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__)
+{
+   Ac_Adapter *ac = data;
+   EDBus_Message_Iter *array, *dict, *variant;
+
+   if (edbus_message_error_get(msg, NULL, NULL))
+     return;
+   if (!edbus_message_arguments_get(msg, "a{sv}", &array))
+     return;
+   while (edbus_message_iter_get_and_next(array, 'e', &dict))
+     {
+        char *key;
+        if (!edbus_message_iter_arguments_get(dict, "sv", &key, &variant))
+          continue;
+        if (!strcmp(key, "Online"))
+          {
+             Eina_Bool b;
+             edbus_message_iter_arguments_get(variant, "b", &b);
+             ac->present = b;
+          }
+     }
+   _battery_device_update();
+}
+
+static void
+_ac_changed_cb(void *data, const EDBus_Message *msg __UNUSED__)
+{
+   Ac_Adapter *ac = data;
+   edbus_proxy_property_get_all(ac->proxy, _ac_get_all_cb, ac);
+}
+
+static void
+_process_ac(EDBus_Proxy *proxy)
+{
+   Ac_Adapter *ac;
+   ac = E_NEW(Ac_Adapter, 1);
+   if (!ac) goto error;
+   ac->proxy = proxy;
+   ac->udi = eina_stringshare_add(edbus_object_path_get(edbus_proxy_object_get(proxy)));
+   edbus_proxy_property_get_all(proxy, _ac_get_all_cb, ac);
+   edbus_proxy_signal_handler_add(proxy, "Changed", _ac_changed_cb, ac);
+   device_ac_adapters = eina_list_append(device_ac_adapters, ac);
+   return;
+error:
+   edbus_object_unref(edbus_proxy_object_get(proxy));
+   return;
+}
+
+static const char *bat_techologys[] = {
+               "Unknown",
+               "Lithium ion",
+               "Lithium polymer",
+               "Lithium iron phosphate",
+               "Lead acid",
+               "Nickel cadmium",
+               "Nickel metal hydride"
+};
+
+static void
+_bat_get_all_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__)
+{
+   Battery *bat = data;
+   EDBus_Message_Iter *array, *dict, *variant;
+
+   bat->got_prop = EINA_TRUE;
+   if (edbus_message_error_get(msg, NULL, NULL))
+     return;
+   if (!edbus_message_arguments_get(msg, "a{sv}", &array))
+     return;
+   while (edbus_message_iter_get_and_next(array, 'e', &dict))
+     {
+        char *key;
+        if (!edbus_message_iter_arguments_get(dict, "sv", &key, &variant))
+          continue;
+        if (!strcmp(key, "IsPresent"))
+           {
+              Eina_Bool b;
+              edbus_message_iter_arguments_get(variant, "b", &b);
+              bat->present = b;
+           }
+        else if (!strcmp(key, "TimeToEmpty"))
+          {
+             int64_t empty = 0;
+             edbus_message_iter_arguments_get(variant, "x", &empty);
+             bat->time_left = (int) empty;
+             if (empty > 0)
+               bat->charging = EINA_FALSE;
+             else
+               bat->charging = EINA_TRUE;
+          }
+        else if (!strcmp(key, "Percentage"))
+          {
+             double d;
+             edbus_message_iter_arguments_get(variant, "d", &d);
+             bat->percent = (int) d;
+          }
+        else if (!strcmp(key, "Energy"))
+          {
+             double d;
+             edbus_message_iter_arguments_get(variant, "d", &d);
+             bat->current_charge = (int) d;
+          }
+        else if (!strcmp(key, "EnergyFullDesign"))
+          {
+             double d;
+             edbus_message_iter_arguments_get(variant, "d", &d);
+             bat->design_charge = (int) d;
+          }
+        else if (!strcmp(key, "EnergyFull"))
+          {
+             double d;
+             edbus_message_iter_arguments_get(variant, "d", &d);
+             bat->last_full_charge = (int) d;
+          }
+        else if (!strcmp(key, "TimeToFull"))
+          {
+             int64_t full = 0;
+             edbus_message_iter_arguments_get(variant, "x", &full);
+             bat->time_full = (int) full;
+          }
+        else if (!strcmp(key, "Technology"))
+          {
+             uint32_t tec = 0;
+             edbus_message_iter_arguments_get(variant, "u", &tec);
+             bat->technology = bat_techologys[tec];
+          }
+        else if (!strcmp(key, "Model"))
+          {
+             char *txt;
+             if (!edbus_message_iter_arguments_get(variant, "s", &txt))
+               continue;
+             if (bat->model)
+               eina_stringshare_del(bat->model);
+             bat->model = eina_stringshare_add(txt);
+          }
+        else if (!strcmp(key, "Vendor"))
+          {
+             char *txt;
+             if (!edbus_message_iter_arguments_get(variant, "s", &txt))
+               continue;
+             if (bat->vendor)
+               eina_stringshare_del(bat->vendor);
+             bat->vendor = eina_stringshare_add(txt);
+          }
+     }
+   _battery_device_update();
+}
+
+static void
+_bat_changed_cb(void *data, const EDBus_Message *msg __UNUSED__)
+{
+   Battery *bat = data;
+   edbus_proxy_property_get_all(bat->proxy, _bat_get_all_cb, bat);
+}
+
+static void
+_process_battery(EDBus_Proxy *proxy)
+{
+   Battery *bat;
+
+   bat = E_NEW(Battery, 1);
+   if (!bat)
+     {
+       edbus_object_unref(edbus_proxy_object_get(proxy));
+       return;
+     }
+
+   bat->proxy = proxy;
+   bat->udi = eina_stringshare_add(edbus_object_path_get(edbus_proxy_object_get(proxy)));
+   edbus_proxy_property_get_all(proxy, _bat_get_all_cb, bat);
+   edbus_proxy_signal_handler_add(proxy, "Changed", _bat_changed_cb, bat);
+   device_batteries = eina_list_append(device_batteries, bat);
+   _battery_device_update();
+}
+
+static void
+_device_type_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__)
+{
+   EDBus_Proxy *proxy = data;
+   EDBus_Message_Iter *variant;
+   EDBus_Object *obj;
+   unsigned int type = 0;
+   char *signature;
+
+   if (edbus_message_error_get(msg, NULL, NULL))
+     goto error;
+
+   if (!edbus_message_arguments_get(msg, "v", &variant))
+     goto error;
+
+   signature = edbus_message_iter_signature_get(variant);
+   if (!signature || signature[0] != 'u')
+     goto error;
+
+   edbus_message_iter_arguments_get(variant, "u", &type);
+   if (type == 1)
+     _process_ac(proxy);
+   else if (type == 2)
+     _process_battery(proxy);
+   else
+     goto error;
+
+   return;
+error:
+   obj = edbus_proxy_object_get(proxy);
+   edbus_proxy_unref(proxy);
+   edbus_object_unref(obj);
+   return;
+}
+
+static void
+_process_enumerate_path(char *path)
+{
+   EDBus_Object *obj;
+   EDBus_Proxy *proxy;
+
+   if (!path || !path[0])
+     return;
+
+   obj = edbus_object_get(conn, BUS, path);
+   EINA_SAFETY_ON_FALSE_RETURN(obj);
+   proxy = edbus_proxy_get(obj, "org.freedesktop.UPower.Device");
+   edbus_proxy_property_get(proxy, "Type", _device_type_cb, proxy);
+}
+
+static void
+_enumerate_cb(void *data __UNUSED__, const EDBus_Message *msg, EDBus_Pending *pending __UNUSED__)
+{
+   char *path;
+   EDBus_Message_Iter *array;
+   if (edbus_message_error_get(msg, NULL, NULL))
+     return;
+
+   if (!edbus_message_arguments_get(msg, "ao", &array))
+     return;
+
+   while (edbus_message_iter_get_and_next(array, 'o', &path))
+     _process_enumerate_path(path);
+}
+
+static void
+_device_added_cb(void *data __UNUSED__, const EDBus_Message *msg)
+{
+   char *path;
+   if (!edbus_message_arguments_get(msg, "o", &path))
+     return;
+   _process_enumerate_path(path);
+}
+
+static void
+_device_removed_cb(void *data __UNUSED__, const EDBus_Message *msg)
+{
+   Battery *bat;
+   Ac_Adapter *ac;
+   char *path;
+
+   if (!edbus_message_arguments_get(msg, "o", &path))
+     return;
+   bat = _battery_battery_find(path);
+   if (bat)
+     {
+         _battery_free(bat);
+        _battery_device_update();
+        return;
+     }
+   ac = _battery_ac_adapter_find(path);
+   if (ac)
+     {
+        _ac_free(ac);
+        _battery_device_update();
+     }
+}
+
+int
+_battery_upower_start(void)
+{
+   EDBus_Object *obj;
+
+   edbus_init();
+   conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SYSTEM);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(conn, 0);
+
+   obj = edbus_object_get(conn, BUS, PATH);
+   EINA_SAFETY_ON_NULL_GOTO(obj, obj_error);
+   upower_proxy = edbus_proxy_get(obj, IFACE);
+   EINA_SAFETY_ON_NULL_GOTO(upower_proxy, proxy_error);
+   edbus_proxy_call(upower_proxy, "EnumerateDevices", _enumerate_cb, NULL, -1, "");
+   edbus_proxy_signal_handler_add(upower_proxy, "DeviceAdded", _device_added_cb, NULL);
+   edbus_proxy_signal_handler_add(upower_proxy, "DeviceRemoved", _device_removed_cb, NULL);
+   return 1;
+
+proxy_error:
+   edbus_object_unref(obj);
+obj_error:
+   edbus_connection_unref(conn);
+   return 0;
+}
+
+void
+_battery_upower_stop(void)
+{
+   Eina_List *list, *list2;
+   Battery *bat;
+   Ac_Adapter *ac;
+   EDBus_Object *obj;
+
+   EINA_LIST_FOREACH_SAFE(device_batteries, list, list2, bat)
+     _battery_free(bat);
+   EINA_LIST_FOREACH_SAFE(device_ac_adapters, list, list2, ac)
+     _ac_free(ac);
+
+   obj = edbus_proxy_object_get(upower_proxy);
+   edbus_proxy_unref(upower_proxy);
+   edbus_object_unref(obj);
+   edbus_connection_unref(conn);
+   edbus_shutdown();
+}
+
+static void
+_battery_free(Battery *bat)
+{
+   EDBus_Object *obj = edbus_proxy_object_get(bat->proxy);
+   edbus_proxy_unref(bat->proxy);
+   edbus_object_unref(obj);
+
+   device_batteries = eina_list_remove(device_batteries, bat);
+   eina_stringshare_del(bat->udi);
+   if (bat->model)
+     eina_stringshare_del(bat->model);
+   if (bat->vendor)
+     eina_stringshare_del(bat->vendor);
+   free(bat);
+}
+
+static void
+_ac_free(Ac_Adapter *ac)
+{
+   EDBus_Object *obj = edbus_proxy_object_get(ac->proxy);
+   edbus_proxy_unref(ac->proxy);
+   edbus_object_unref(obj);
+
+   device_ac_adapters = eina_list_remove(device_ac_adapters, ac);
+   eina_stringshare_del(ac->udi);
+   free(ac);
+}