connman client library is in, with tests and all.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 31 Mar 2009 01:23:07 +0000 (01:23 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 31 Mar 2009 01:23:07 +0000 (01:23 +0000)
during endless nights and talks I debugged it and seems to not leak or
segfault, but now we need a GUI for it!

My idea is to have an gadget much like mixer, it would show the
current connection and status, when you click you'd get a "Controls",
a list of devices and a "offline" checkbox.

Controls would open a detailed control panel with devices (ie:
interfaces, eth0, eth1, wlan0...), networks (access points) and
properties about them, like the passphrase, whenever to remember or
not, autoconnect or not, policy and even reoder (change priority).

List of devices would show them ("Wireless") and possible some
information, like the current access point name or ssid, it's a radio.

Offline checkbox (and e_action) are mandatory so you can easily turn
them off. Connman is smart and will turn off radios, that can also
save power.

Ideas, anyone willing to implement the gadget?

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/e_dbus@39807 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

16 files changed:
configure.ac
econnman.pc.in [new file with mode: 0644]
src/bin/Makefile.am
src/bin/e_dbus_connman_test.c [new file with mode: 0644]
src/bin/e_dbus_connman_test_api.c [new file with mode: 0644]
src/lib/Makefile.am
src/lib/connman/E_Connman.h [new file with mode: 0644]
src/lib/connman/Makefile.am [new file with mode: 0644]
src/lib/connman/e_connman.c [new file with mode: 0644]
src/lib/connman/e_connman_connection.c [new file with mode: 0644]
src/lib/connman/e_connman_device.c [new file with mode: 0644]
src/lib/connman/e_connman_element.c [new file with mode: 0644]
src/lib/connman/e_connman_manager.c [new file with mode: 0644]
src/lib/connman/e_connman_network.c [new file with mode: 0644]
src/lib/connman/e_connman_private.h [new file with mode: 0644]
src/lib/connman/e_connman_profile.c [new file with mode: 0644]

index cb97e73..8a3ad51 100644 (file)
@@ -32,15 +32,20 @@ AC_ARG_ENABLE(ehal,
                                  [enable_ehal=$enableval],
                                  [enable_ehal="yes"])
 AC_ARG_ENABLE(enm,
-                                 AC_HELP_STRING([--disable-enm], 
+                                 AC_HELP_STRING([--disable-enm],
                                                                          [Disable enm build]),
                                  [enable_enm=$enableval],
                                  [enable_enm="yes"])
 AC_ARG_ENABLE(enotify,
-                                 AC_HELP_STRING([--disable-enotify], 
+                                 AC_HELP_STRING([--disable-enotify],
                                                                          [Disable enotify build]),
                                  [enable_enotify=$enableval],
                                  [enable_enotify="yes"])
+AC_ARG_ENABLE(econnman,
+                                 AC_HELP_STRING([--disable-econnman],
+                                                                         [Disable econnman build]),
+                                 [enable_econnman=$enableval],
+                                 [enable_econnman="yes"])
 
 
 PKG_CHECK_MODULES([EINA], [eina-0])
@@ -73,6 +78,7 @@ AC_ARG_ENABLE(build-test-gui,
 AM_CONDITIONAL([BUILD_EHAL],    [test "x${enable_ehal}"    = "xyes"])
 AM_CONDITIONAL([BUILD_ENM],     [test "x${enable_enm}"     = "xyes"])
 AM_CONDITIONAL([BUILD_ENOTIFY], [test "x${enable_enotify}" = "xyes"])
+AM_CONDITIONAL([BUILD_ECONNMAN], [test "x${enable_econnman}" = "xyes"])
 
 AC_OUTPUT([
 e_dbus.spec
@@ -83,11 +89,13 @@ src/lib/dbus/Makefile
 src/lib/hal/Makefile
 src/lib/nm/Makefile
 src/lib/notification/Makefile
+src/lib/connman/Makefile
 src/bin/Makefile
 edbus.pc
 ehal.pc
 enotify.pc
 enm.pc
+econnman.pc
 ])
 
 
@@ -106,6 +114,7 @@ echo
 echo "  EHal.................: $enable_ehal"
 echo "  ENM..................: $enable_enm"
 echo "  ENotify..............: $enable_enotify"
+echo "  EConnman.............: $enable_econnman"
 echo
 echo "Configuration Options Summary:"
 echo
diff --git a/econnman.pc.in b/econnman.pc.in
new file mode 100644 (file)
index 0000000..68b4248
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: econnman
+Description: network connection manager (connman)
+Requires: ecore edbus
+Version: @VERSION@
+Libs: -L${libdir} -leconnman
+Cflags: -I${includedir}
index 2017f05..1258938 100644 (file)
@@ -5,6 +5,7 @@ EDBUS_CPPFLAGS = \
 -I$(top_srcdir)/src/lib/hal \
 -I$(top_srcdir)/src/lib/nm \
 -I$(top_srcdir)/src/lib/notification \
+-I$(top_srcdir)/src/lib/connman \
 @EDBUS_CFLAGS@ \
 @EINA_CFLAGS@
 
@@ -22,8 +23,20 @@ endif
 if BUILD_ENOTIFY
 ENOTIFY_PROG = e_dbus_notify e_dbus_notification_daemon e-notify-send
 endif
+if BUILD_ECONNMAN
+ECONNMAN_PROG = e_dbus_connman_test
+ECONNMAN_PROG_NOINST = e_dbus_connman_test_api
+endif
+
+bin_PROGRAMS = \
+$(EDBUS_PROG) \
+$(EHAL_PROG) \
+$(ENM_PROG) \
+$(ENOTIFY_PROG) \
+$(ECONNMAN_PROG)
 
-bin_PROGRAMS = $(EDBUS_PROG) $(EHAL_PROG) $(ENM_PROG) $(ENOTIFY_PROG)
+noinst_PROGRAMS = \
+$(ECONNMAN_PROG_NOINST)
 
 e_dbus_test_SOURCES = \
 test.c
@@ -94,4 +107,16 @@ e_notify_send_SOURCES = \
 e_notify_send_CPPFLAGS = $(EDBUS_CPPFLAGS)
 e_notify_send_LDADD = $(top_builddir)/src/lib/dbus/libedbus.la $(top_builddir)/src/lib/notification/libenotify.la
 e_notify_send_DEPENDENCIES = $(top_builddir)/src/lib/dbus/libedbus.la $(top_builddir)/src/lib/notification/libenotify.la
-endif 
+endif
+
+if BUILD_ECONNMAN
+e_dbus_connman_test_SOURCES = e_dbus_connman_test.c
+e_dbus_connman_test_CPPFLAGS = $(EDBUS_CPPFLAGS)
+e_dbus_connman_test_LDADD = $(top_builddir)/src/lib/dbus/libedbus.la $(top_builddir)/src/lib/connman/libeconnman.la
+e_dbus_connman_test_DEPENDENCIES = $(top_builddir)/src/lib/dbus/libedbus.la $(top_builddir)/src/lib/connman/libeconnman.la
+
+e_dbus_connman_test_api_SOURCES = e_dbus_connman_test_api.c
+e_dbus_connman_test_api_CPPFLAGS = $(EDBUS_CPPFLAGS)
+e_dbus_connman_test_api_LDADD = $(top_builddir)/src/lib/dbus/libedbus.la $(top_builddir)/src/lib/connman/libeconnman.la
+e_dbus_connman_test_api_DEPENDENCIES = $(top_builddir)/src/lib/dbus/libedbus.la $(top_builddir)/src/lib/connman/libeconnman.la
+endif
diff --git a/src/bin/e_dbus_connman_test.c b/src/bin/e_dbus_connman_test.c
new file mode 100644 (file)
index 0000000..090dca1
--- /dev/null
@@ -0,0 +1,1595 @@
+#include "E_Connman.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+static void
+_elements_print(E_Connman_Element **elements, int count)
+{
+   int i;
+   for (i = 0; i < count; i++)
+     {
+       printf("--- element %d:\n", i);
+       e_connman_element_print(stdout, elements[i]);
+     }
+   free(elements);
+   printf("END: all elements count = %d\n", count);
+}
+
+static int
+_on_element_add(void *data, int type, void *info)
+{
+   E_Connman_Element *element = info;
+   printf(">>> %s\n", element->path);
+   return 1;
+}
+
+static int
+_on_element_del(void *data, int type, void *info)
+{
+   E_Connman_Element *element = info;
+   printf("<<< %s\n", element->path);
+   return 1;
+}
+
+static int
+_on_element_updated(void *data, int type, void *info)
+{
+   E_Connman_Element *element = info;
+   printf("!!! %s\n", element->path);
+   e_connman_element_print(stderr, element);
+   return 1;
+}
+
+static int
+_on_cmd_quit(char *cmd, char *args)
+{
+   fputs("Bye!\n", stderr);
+   ecore_main_loop_quit();
+   return 0;
+}
+
+static int
+_on_cmd_sync(char *cmd, char *args)
+{
+   e_connman_manager_sync_elements();
+   return 1;
+}
+
+static char *
+_tok(char *p)
+{
+   p = strchr(p, ' ');
+   if (!p)
+     return NULL;
+
+   *p = '\0';
+   p++;
+   while (isspace(*p))
+     p++;
+   if (*p == '\0')
+     return NULL;
+
+   return p;
+}
+
+static int
+_on_cmd_get_all(char *cmd, char *args)
+{
+   E_Connman_Element **elements;
+   char *type;
+   unsigned int count;
+   bool ret;
+
+   if (!args)
+     type = NULL;
+   else
+     type = args;
+
+   if (type)
+     ret = e_connman_elements_get_all_type(type, &count, &elements);
+   else
+     ret = e_connman_elements_get_all(&count, &elements);
+
+   if (!ret)
+     fputs("ERROR: could not get elements\n", stderr);
+   else
+     {
+       printf("BEG: all elements type=%s count = %d\n", type, count);
+       _elements_print(elements, count);
+     }
+
+   return 1;
+}
+
+static E_Connman_Element *
+_element_from_args(char *args, char **next_args)
+{
+   E_Connman_Element *element;
+
+   if (!args)
+     {
+       fputs("ERROR: missing element path\n", stderr);
+       *next_args = NULL;
+       return NULL;
+     }
+
+   *next_args = _tok(args);
+   element = e_connman_element_get(args);
+   if (!element)
+     fprintf(stderr, "ERROR: no element called \"%s\".\n", args);
+
+   return element;
+}
+
+static int
+_on_cmd_print(char *cmd, char *args)
+{
+   char *next_args;
+   E_Connman_Element *element = _element_from_args(args, &next_args);
+   if (element)
+     e_connman_element_print(stdout, element);
+   return 1;
+}
+
+static int
+_on_cmd_get_properties(char *cmd, char *args)
+{
+   char *next_args;
+   E_Connman_Element *element = _element_from_args(args, &next_args);
+   if (element)
+     e_connman_element_properties_sync(element);
+   return 1;
+}
+
+static int
+_on_cmd_property_set(char *cmd, char *args)
+{
+   char *next_args, *name, *p;
+   E_Connman_Element *element = _element_from_args(args, &next_args);
+   void *value;
+   long vlong;
+   unsigned short vu16;
+   unsigned int vu32;
+   int type;
+
+   if (!element)
+     return 1;
+
+   if (!next_args)
+     {
+       fputs("ERROR: missing parameters name, type and value.\n", stderr);
+       return 1;
+     }
+
+   name = next_args;
+   p = _tok(name);
+   if (!p)
+     {
+       fputs("ERROR: missing parameters type and value.\n", stderr);
+       return 1;
+     }
+
+   next_args = _tok(p);
+   if (!next_args)
+     {
+       fputs("ERROR: missing parameter value.\n", stderr);
+       return 1;
+     }
+
+   type = p[0];
+   switch (type)
+     {
+      case DBUS_TYPE_BOOLEAN:
+        vlong = !!atol(next_args);
+        value = (void *)vlong;
+        fprintf(stderr, "DBG: boolean is: %ld\n", vlong);
+        break;
+      case DBUS_TYPE_UINT16:
+        vu16 = strtol(next_args, &p, 0);
+        if (p == next_args)
+          {
+             fprintf(stderr, "ERROR: invalid number \"%s\".\n", next_args);
+             return 1;
+          }
+        value = &vu16;
+        fprintf(stderr, "DBG: u16 is: %hu\n", vu16);
+        break;
+      case DBUS_TYPE_UINT32:
+        vu32 = strtol(next_args, &p, 0);
+        if (p == next_args)
+          {
+             fprintf(stderr, "ERROR: invalid number \"%s\".\n", next_args);
+             return 1;
+          }
+        value = &vu32;
+        fprintf(stderr, "DBG: u16 is: %u\n", vu32);
+        break;
+      case DBUS_TYPE_STRING:
+      case DBUS_TYPE_OBJECT_PATH:
+        p = next_args + strlen(next_args);
+        if (p > next_args)
+          p--;
+        while (p > next_args && isspace(*p))
+          p--;
+        if (p <= next_args)
+          {
+             fprintf(stderr, "ERROR: invalid string \"%s\".\n", next_args);
+          }
+        p[1] = '\0';
+        value = next_args;
+        fprintf(stderr, "DBG: string is: \"%s\"\n", next_args);
+        break;
+      default:
+        fprintf(stderr, "ERROR: don't know how to parse type '%c' (%d)\n",
+                type, type);
+        return 1;
+     }
+
+   fprintf(stderr, "set_property %s [%p] %s %c %p...\n",
+          args, element, name, type, value);
+   e_connman_element_property_set(element, name, type, value);
+   return 1;
+}
+
+
+/* Manager Commands */
+
+static int
+_on_cmd_manager_get(char *cmd, char *args)
+{
+   E_Connman_Element *element;
+   element = e_connman_manager_get();
+   e_connman_element_print(stderr, element);
+   return 1;
+}
+
+static int
+_on_cmd_manager_get_profiles(char *cmd, char *args)
+{
+   unsigned int count;
+   E_Connman_Element **profiles;
+
+   if (!e_connman_manager_profiles_get(&count, &profiles))
+     {
+       fputs("ERROR: can't get profiles\n", stderr);
+       return 1;
+     }
+   printf("BEG: all manager profiles elements count = %d\n", count);
+   _elements_print(profiles, count);
+   return 1;
+}
+
+static int
+_on_cmd_manager_get_devices(char *cmd, char *args)
+{
+   unsigned int count;
+   E_Connman_Element **devices;
+
+   if (!e_connman_manager_devices_get(&count, &devices))
+     {
+       fputs("ERROR: can't get devices\n", stderr);
+       return 1;
+     }
+   printf("BEG: all manager devices elements count = %d\n", count);
+   _elements_print(devices, count);
+   return 1;
+}
+
+static int
+_on_cmd_manager_get_connections(char *cmd, char *args)
+{
+   unsigned int count;
+   E_Connman_Element **connections;
+
+   if (!e_connman_manager_connections_get(&count, &connections))
+     {
+       fputs("ERROR: can't get connections\n", stderr);
+       return 1;
+     }
+   printf("BEG: all manager connections elements count = %d\n", count);
+   _elements_print(connections, count);
+   return 1;
+}
+
+static int
+_on_cmd_manager_register_agent(char *cmd, char *args)
+{
+   char *path;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the object path\n", stderr);
+       return 1;
+     }
+
+   path = args;
+   if (e_connman_manager_register_agent(path, NULL, NULL))
+     printf(":::Registering agent %s...\n", path);
+   else
+     fprintf(stderr, "ERROR: can't register agent %s\n", path);
+
+   return 1;
+}
+
+static int
+_on_cmd_manager_unregister_agent(char *cmd, char *args)
+{
+   char *path;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the object path\n", stderr);
+       return 1;
+     }
+
+   path = args;
+   if (e_connman_manager_unregister_agent(path, NULL, NULL))
+     printf(":::Unregistering agent %s...\n", path);
+   else
+     fprintf(stderr, "ERROR: can't unregister agent %s\n", path);
+
+   return 1;
+}
+
+static int
+_on_cmd_manager_get_state(char *cmd, char *args)
+{
+   const char *state;
+   if (e_connman_manager_state_get(&state))
+     printf(":::Manager state = \"%s\"\n", state);
+   else
+     fputs("ERROR: can't get manager state\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_manager_get_policy(char *cmd, char *args)
+{
+   const char *policy;
+   if (e_connman_manager_policy_get(&policy))
+     printf(":::Manager policy = \"%s\"\n", policy);
+   else
+     fputs("ERROR: can't get manager policy\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_manager_set_policy(char *cmd, char *args)
+{
+   char *policy;
+   if (!args)
+     {
+       fputs("ERROR: missing the policy value\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   policy = args;
+   if (e_connman_manager_policy_set(policy, NULL, NULL))
+     printf(":::Manager policy set to \"%s\"\n", policy);
+   else
+     fputs("ERROR: can't set manager policy\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_manager_get_offline_mode(char *cmd, char *args)
+{
+   bool offline;
+   if (e_connman_manager_offline_mode_get(&offline))
+     printf(":::Manager Offline Mode = %hhu\n", offline);
+   else
+     fputs("ERROR: can't get manager offline mode\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_manager_set_offline_mode(char *cmd, char *args)
+{
+   bool offline;
+   if (!args)
+     {
+       fputs("ERROR: missing the offline mode value\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   offline = !!atol(args);
+   if (e_connman_manager_offline_mode_set(offline, NULL, NULL))
+     printf(":::Manager Offline Mode set to %hhu\n", offline);
+   else
+     fputs("ERROR: can't set manager offline mode\n", stderr);
+   return 1;
+}
+
+/* Device Commands */
+
+static int
+_on_cmd_device_create_network(char *cmd, char *args)
+{
+   char *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+   e = e_connman_device_get(path);
+   if (e_connman_device_network_create(e, NULL, NULL))
+     printf(":::Creating Network %s...\n", path);
+   else
+     fputs("ERROR: can't create network\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_remove_network(char *cmd, char *args)
+{
+   char *path, *device_path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   device_path = args;
+   path = _tok(args);
+
+   if (!path)
+     {
+       fputs("ERROR: missing the object network\n", stderr);
+       return 1;
+     }
+   _tok(path);
+
+   e = e_connman_device_get(device_path);
+   if (e_connman_device_network_remove(e, path, NULL, NULL))
+     printf(":::Removing Network %s...\n", path);
+   else
+     fputs("ERROR: can't remove network\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_propose_scan(char *cmd, char *args)
+{
+   char *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_propose_scan(e, NULL, NULL))
+     printf(":::Proposing scan %s...\n", path);
+   else
+     fputs("ERROR: can't propose scan\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_name(char *cmd, char *args)
+{
+   const char *name, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_name_get(e, &name))
+     printf(":::Device %s Name = \"%s\"\n", path, name);
+   else
+     fputs("ERROR: can't get device name\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_type(char *cmd, char *args)
+{
+   const char *type, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_type_get(e, &type))
+     printf(":::Device %s Type = \"%s\"\n", path, type);
+   else
+     fputs("ERROR: can't get device type\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_interface(char *cmd, char *args)
+{
+   const char *interface, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_interface_get(e, &interface))
+     printf(":::Device %s Interface = \"%s\"\n", path, interface);
+   else
+     fputs("ERROR: can't get device interface\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_policy(char *cmd, char *args)
+{
+   const char *policy, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_policy_get(e, &policy))
+     printf(":::Device %s Policy = \"%s\"\n", path, policy);
+   else
+     fputs("ERROR: can't get device policy\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_set_policy(char *cmd, char *args)
+{
+   char *policy;
+   const char *device_path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   device_path = args;
+   policy = _tok(args);
+
+   if (!policy)
+     {
+       fputs("ERROR: missing the policy value\n", stderr);
+       return 1;
+     }
+   _tok(policy);
+
+   e = e_connman_device_get(device_path);
+   if (e_connman_device_policy_set(e, policy, NULL, NULL))
+     printf(":::Device %s policy set to \"%s\"\n", device_path, policy);
+   else
+     fputs("ERROR: can't set device policy\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_priority(char *cmd, char *args)
+{
+   char *path;
+   unsigned char priority;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_priority_get(e, &priority))
+     printf(":::Device %s Priority = %#02hhx (%d)\n", path, priority, priority);
+   else
+     fputs("ERROR: can't get device priority\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_set_priority(char *cmd, char *args)
+{
+   char *next_args, *device_path, *p;
+   unsigned char priority;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   device_path = args;
+   next_args = _tok(args);
+   if (!next_args)
+     {
+       fputs("ERROR: missing the priority value\n", stderr);
+       return 1;
+     }
+   _tok(next_args);
+   priority = strtol(next_args, &p, 0);
+   if (p == next_args)
+     {
+       fprintf(stderr, "ERROR: invalid number \"%s\".\n", next_args);
+       return 1;
+     }
+
+   e = e_connman_device_get(device_path);
+   if (e_connman_device_priority_set(e, priority, NULL, NULL))
+     printf(":::Device %s priority set to %d\n", device_path, priority);
+   else
+     fputs("ERROR: can't set device priority\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_powered(char *cmd, char *args)
+{
+   char *path;
+   bool powered;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_powered_get(e, &powered))
+     printf(":::Device %s Powered = %hhu\n", path, powered);
+   else
+     fputs("ERROR: can't get device powered\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_set_powered(char *cmd, char *args)
+{
+   char *device_path, *next_args;
+   bool powered;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   device_path = args;
+   next_args = _tok(args);
+   if (!next_args)
+     {
+       fputs("ERROR: missing the powered value\n", stderr);
+       return 1;
+     }
+   powered = !!atol(next_args);
+
+   e = e_connman_device_get(device_path);
+   if (e_connman_device_powered_set(e, powered, NULL, NULL))
+     printf(":::Device %s powered set to %hhu\n", device_path, powered);
+   else
+     fputs("ERROR: can't set device powered\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_scan_interval(char *cmd, char *args)
+{
+   char *path;
+   unsigned short scan_interval;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_scan_interval_get(e, &scan_interval))
+     printf(":::Device %s ScanInterval = %hu\n", path, scan_interval);
+   else
+     fputs("ERROR: can't get device scan interval\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_set_scan_interval(char *cmd, char *args)
+{
+   char *device_path, *next_args, *p;
+   unsigned short scan_interval;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   device_path = args;
+   next_args = _tok(args);
+   if (!next_args)
+     {
+       fputs("ERROR: missing the scan interval value\n", stderr);
+       return 1;
+     }
+   scan_interval = strtol(next_args, &p, 0);
+   if (p == next_args)
+     {
+       fprintf(stderr, "ERROR: invalid number \"%s\".\n", next_args);
+       return 1;
+     }
+
+   e = e_connman_device_get(device_path);
+   if (e_connman_device_scan_interval_set(e, scan_interval, NULL, NULL))
+     printf(":::Device %s scan interval set to %hu\n", device_path, scan_interval);
+   else
+     fputs("ERROR: can't set device scan interval\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_scanning(char *cmd, char *args)
+{
+   char *path;
+   bool scanning;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (e_connman_device_scanning_get(e, &scanning))
+     printf(":::Device %s Scanning = %hhu\n", path, scanning);
+   else
+     fputs("ERROR: can't get device scanning\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_device_get_networks(char *cmd, char *args)
+{
+   E_Connman_Element **networks;
+   unsigned int count;
+   char *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the device path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_device_get(path);
+   if (!e_connman_device_networks_get(e, &count, &networks))
+     {
+       fputs("ERROR: can't get networks\n", stderr);
+       return 1;
+     }
+
+   printf("BEG: all device network elements count = %d\n", count);
+   _elements_print(networks, count);
+   return 1;
+}
+
+/* Profile Commands */
+
+static int
+_on_cmd_profile_get_name(char *cmd, char *args)
+{
+   const char *name, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the profile path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_profile_get(path);
+   if (e_connman_profile_name_get(e, &name))
+     printf(":::Profile %s Name = \"%s\"\n", path, name);
+   else
+     fputs("ERROR: can't get profile name\n", stderr);
+   return 1;
+}
+
+/* Connection Commands */
+
+static int
+_on_cmd_connection_get_type(char *cmd, char *args)
+{
+   const char *type, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (e_connman_connection_type_get(e, &type))
+     printf(":::Connection %s Type = \"%s\"\n", path, type);
+   else
+     fputs("ERROR: can't get connection type\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_interface(char *cmd, char *args)
+{
+   const char *interface, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (e_connman_connection_interface_get(e, &interface))
+     printf(":::Connection %s Interface = \"%s\"\n", path, interface);
+   else
+     fputs("ERROR: can't get connection type\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_device(char *cmd, char *args)
+{
+   E_Connman_Element *e, *device;
+   char *path;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (!e_connman_connection_device_get(e, &device))
+     fputs("ERROR: can't get connection device\n", stderr);
+   else
+     e_connman_element_print(stderr, device);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_network(char *cmd, char *args)
+{
+   E_Connman_Element *e, *network;
+   char *path;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (!e_connman_connection_network_get(e, &network))
+     fputs("ERROR: can't get connection network\n", stderr);
+   else
+     e_connman_element_print(stderr, network);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_strength(char *cmd, char *args)
+{
+   char *path;
+   unsigned char strength;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (e_connman_connection_strength_get(e, &strength))
+     printf(":::Connection %s Strength = %#02hhx (%d)\n", path, strength, strength);
+   else
+     fputs("ERROR: can't get connection strength\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_default(char *cmd, char *args)
+{
+   char *path;
+   bool connection_default;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (e_connman_connection_default_get(e, &connection_default))
+     printf(":::Connection %s Default = %hhu\n", path, connection_default);
+   else
+     fputs("ERROR: can't get connection default\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_ipv4_method(char *cmd, char *args)
+{
+   const char *method, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (e_connman_connection_ipv4_method_get(e, &method))
+     printf(":::Connection %s IPv4 Method = \"%s\"\n", path, method);
+   else
+     fputs("ERROR: can't get connection ipv4 method\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_connection_get_ipv4_address(char *cmd, char *args)
+{
+   const char *address, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the connection path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_connection_get(path);
+   if (e_connman_connection_ipv4_address_get(e, &address))
+     printf(":::Connection %s IPv4 Address = \"%s\"\n", path, address);
+   else
+     fputs("ERROR: can't get connection ipv4 address\n", stderr);
+   return 1;
+}
+
+/* Network Commands */
+
+static int
+_on_cmd_network_connect(char *cmd, char *args)
+{
+   char *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_connect(e, NULL, NULL))
+     printf(":::Connecting to Network %s...\n", path);
+   else
+     fputs("ERROR: can't connect to network\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_disconnect(char *cmd, char *args)
+{
+   char *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_disconnect(e, NULL, NULL))
+     printf(":::Disconnecting Network %s...\n", path);
+   else
+     fputs("ERROR: can't disconnect network\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_name(char *cmd, char *args)
+{
+   const char *name, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_name_get(e, &name))
+     printf(":::Network %s Name = \"%s\"\n", path, name);
+   else
+     fputs("ERROR: can't get network name\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_available(char *cmd, char *args)
+{
+   const char *path;
+   bool available;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_available_get(e, &available))
+     printf(":::Network %s Available = %hhu\n", path, available);
+   else
+     fputs("ERROR: can't get network available\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_connected(char *cmd, char *args)
+{
+   char *path;
+   bool connected;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_connected_get(e, &connected))
+     printf(":::Network %s Connected = %hhu\n", path, connected);
+   else
+     fputs("ERROR: can't get network connected\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_remember(char *cmd, char *args)
+{
+   char *path;
+   bool remember;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_remember_get(e, &remember))
+     printf(":::Network %s Remember = %hhu\n", path, remember);
+   else
+     fputs("ERROR: can't get network remember\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_set_remember(char *cmd, char *args)
+{
+   char *network_path, *next_args;
+   bool remember;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   network_path = args;
+   next_args = _tok(args);
+   if (!next_args)
+     {
+       fputs("ERROR: missing the remember value\n", stderr);
+       return 1;
+     }
+   _tok(next_args);
+   remember = !!atol(next_args);
+
+   e = e_connman_network_get(network_path);
+   if (e_connman_network_remember_set(e, remember, NULL, NULL))
+     printf(":::Network %s remember set to %d\n", network_path, remember);
+   else
+     fputs("ERROR: can't set network remember\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_strength(char *cmd, char *args)
+{
+   char *path;
+   unsigned char strength;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_strength_get(e, &strength))
+     printf(":::Network %s Strength = %#02hhx (%d)\n", path, strength, strength);
+   else
+     fputs("ERROR: can't get network strength\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_device(char *cmd, char *args)
+{
+   E_Connman_Element *e, *device;
+   char *path;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (!e_connman_network_device_get(e, &device))
+     fputs("ERROR: can't get network device\n", stderr);
+   else
+     e_connman_element_print(stderr, device);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_wifi_ssid(char *cmd, char *args)
+{
+   unsigned char *bytes;
+   char *path;
+   unsigned int i, count;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_wifi_ssid_get(e, &count, &bytes))
+     {
+       printf(":::Network %s Wifi SSID = ", path);
+       for (i = 0; i < count; i++)
+         printf("%#02hhx (\"%c\"), ", bytes[i], bytes[i]);
+       printf("\n");
+     }
+   else
+     fputs("ERROR: can't get network wifi ssid\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_wifi_mode(char *cmd, char *args)
+{
+   const char *wifi_mode, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_wifi_mode_get(e, &wifi_mode))
+     printf(":::Network %s Wifi Mode = \"%s\"\n", path, wifi_mode);
+   else
+     fputs("ERROR: can't get network wifi mode\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_set_wifi_mode(char *cmd, char *args)
+{
+   char *wifi_mode;
+   const char *network_path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   network_path = args;
+   wifi_mode = _tok(args);
+
+   if (!wifi_mode)
+     {
+       fputs("ERROR: missing the wifi mode value\n", stderr);
+       return 1;
+     }
+   _tok(wifi_mode);
+
+   e = e_connman_network_get(network_path);
+   if (e_connman_network_wifi_mode_set(e, wifi_mode, NULL, NULL))
+     printf(":::Network %s wifi mode set to \"%s\"\n", network_path, wifi_mode);
+   else
+     fputs("ERROR: can't set network wifi mode\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_wifi_security(char *cmd, char *args)
+{
+   const char *wifi_security, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_wifi_security_get(e, &wifi_security))
+     printf(":::Network %s Wifi Security = \"%s\"\n", path, wifi_security);
+   else
+     fputs("ERROR: can't get network wifi security\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_set_wifi_security(char *cmd, char *args)
+{
+   char *wifi_security, *network_path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   network_path = args;
+   wifi_security = _tok(args);
+
+   if (!wifi_security)
+     {
+       fputs("ERROR: missing the wifi security value\n", stderr);
+       return 1;
+     }
+   _tok(wifi_security);
+
+   e = e_connman_network_get(network_path);
+   if (e_connman_network_wifi_security_set(e, wifi_security, NULL, NULL))
+     printf(":::Network %s wifi security set to \"%s\"\n", network_path, wifi_security);
+   else
+     fputs("ERROR: can't set network wifi security\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_get_wifi_passphrase(char *cmd, char *args)
+{
+   const char *wifi_passphrase, *path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   _tok(args);
+   path = args;
+
+   e = e_connman_network_get(path);
+   if (e_connman_network_wifi_passphrase_get(e, &wifi_passphrase))
+     printf(":::Network %s Wifi Passphrase = \"%s\"\n", path, wifi_passphrase);
+   else
+     fputs("ERROR: can't get network wifi passphrase\n", stderr);
+   return 1;
+}
+
+static int
+_on_cmd_network_set_wifi_passphrase(char *cmd, char *args)
+{
+   char *wifi_passphrase, *network_path;
+   E_Connman_Element *e;
+
+   if (!args)
+     {
+       fputs("ERROR: missing the network path\n", stderr);
+       return 1;
+     }
+   network_path = args;
+   wifi_passphrase = _tok(args);
+
+   if (!wifi_passphrase)
+     {
+       fputs("ERROR: missing the wifi passphrase value\n", stderr);
+       return 1;
+     }
+   _tok(wifi_passphrase);
+
+   e = e_connman_network_get(network_path);
+   if (e_connman_network_wifi_passphrase_set(e, wifi_passphrase, NULL, NULL))
+     printf(":::Network %s wifi passphrase set to \"%s\"\n", network_path, wifi_passphrase);
+   else
+     fputs("ERROR: can't set network wifi passphrase\n", stderr);
+   return 1;
+}
+
+
+static int
+_on_input(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   char buf[256];
+   char *cmd, *args;
+   const struct {
+      const char *cmd;
+      int (*cb)(char *cmd, char *args);
+   } *itr, maps[] = {
+     {"quit", _on_cmd_quit},
+     {"sync", _on_cmd_sync},
+     {"get_all", _on_cmd_get_all},
+     {"print", _on_cmd_print},
+     {"get_properties", _on_cmd_get_properties},
+     {"set_property", _on_cmd_property_set},
+     {"manager_get", _on_cmd_manager_get},
+     {"manager_get_profiles", _on_cmd_manager_get_profiles},
+     {"manager_get_devices", _on_cmd_manager_get_devices},
+     {"manager_get_connections", _on_cmd_manager_get_connections},
+     {"manager_register_agent", _on_cmd_manager_register_agent},
+     {"manager_unregister_agent", _on_cmd_manager_unregister_agent},
+     {"manager_get_state", _on_cmd_manager_get_state},
+     {"manager_get_policy", _on_cmd_manager_get_policy},
+     {"manager_set_policy", _on_cmd_manager_set_policy},
+     {"manager_get_offline_mode", _on_cmd_manager_get_offline_mode},
+     {"manager_set_offline_mode", _on_cmd_manager_set_offline_mode},
+     {"device_create_network", _on_cmd_device_create_network},
+     {"device_remove_network", _on_cmd_device_remove_network},
+     {"device_propose_scan", _on_cmd_device_propose_scan},
+     {"device_get_name", _on_cmd_device_get_name},
+     {"device_get_type", _on_cmd_device_get_type},
+     {"device_get_interface", _on_cmd_device_get_interface},
+     {"device_get_policy", _on_cmd_device_get_policy},
+     {"device_set_policy", _on_cmd_device_set_policy},
+     {"device_get_priority", _on_cmd_device_get_priority},
+     {"device_set_priority", _on_cmd_device_set_priority},
+     {"device_get_powered", _on_cmd_device_get_powered},
+     {"device_set_powered", _on_cmd_device_set_powered},
+     {"device_get_scan_interval", _on_cmd_device_get_scan_interval},
+     {"device_set_scan_interval", _on_cmd_device_set_scan_interval},
+     {"device_get_scanning", _on_cmd_device_get_scanning},
+     {"device_get_networks", _on_cmd_device_get_networks},
+     {"profile_get_name", _on_cmd_profile_get_name},
+     {"connection_get_type", _on_cmd_connection_get_type},
+     {"connection_get_interface", _on_cmd_connection_get_interface},
+     {"connection_get_strength", _on_cmd_connection_get_strength},
+     {"connection_get_default", _on_cmd_connection_get_default},
+     {"connection_get_device", _on_cmd_connection_get_device},
+     {"connection_get_network", _on_cmd_connection_get_network},
+     {"connection_get_ipv4_method", _on_cmd_connection_get_ipv4_method},
+     {"connection_get_ipv4_address", _on_cmd_connection_get_ipv4_address},
+     {"network_connect", _on_cmd_network_connect},
+     {"network_disconnect", _on_cmd_network_disconnect},
+     {"network_get_name", _on_cmd_network_get_name},
+     {"network_get_available", _on_cmd_network_get_available},
+     {"network_get_connected", _on_cmd_network_get_connected},
+     {"network_get_remember", _on_cmd_network_get_remember},
+     {"network_set_remember", _on_cmd_network_set_remember},
+     {"network_get_strength", _on_cmd_network_get_strength},
+     {"network_get_device", _on_cmd_network_get_device},
+     {"network_get_wifi_ssid", _on_cmd_network_get_wifi_ssid},
+     {"network_get_wifi_mode", _on_cmd_network_get_wifi_mode},
+     {"network_set_wifi_mode", _on_cmd_network_set_wifi_mode},
+     {"network_get_wifi_security", _on_cmd_network_get_wifi_security},
+     {"network_set_wifi_security", _on_cmd_network_set_wifi_security},
+     {"network_get_wifi_passphrase", _on_cmd_network_get_wifi_passphrase},
+     {"network_set_wifi_passphrase", _on_cmd_network_set_wifi_passphrase},
+     {NULL, NULL}
+   };
+
+   if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
+     {
+       fputs("ERROR: reading from stdin, exit\n", stderr);
+       return 0;
+     }
+
+   if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+     {
+       fputs("ERROR: nothing to read?\n", stderr);
+       return 0;
+     }
+
+   if (!fgets(buf, sizeof(buf), stdin))
+     {
+       fprintf(stderr, "ERROR: could not read command: %s\n", strerror(errno));
+       ecore_main_loop_quit();
+       return 0;
+     }
+
+   cmd = buf;
+   while (isspace(*cmd))
+     cmd++;
+
+   args = strchr(cmd, ' ');
+   if (args)
+     {
+       char *p;
+
+       *args = '\0';
+       args++;
+
+       while (isspace(*args))
+         args++;
+
+       p = args + strlen(args) - 1;
+       if (*p == '\n')
+         *p = '\0';
+     }
+   else
+     {
+       char *p;
+
+       p = cmd + strlen(cmd) - 1;
+       if (*p == '\n')
+         *p = '\0';
+     }
+
+   if (strcmp(cmd, "help") == 0)
+     {
+       if (args)
+         {
+            printf("Commands with '%s' in the name:\n", args);
+            for (itr = maps; itr->cmd != NULL; itr++)
+              if (strstr(itr->cmd, args))
+                printf("\t%s\n", itr->cmd);
+         }
+       else
+         {
+            fputs("Commands:\n", stdout);
+            for (itr = maps; itr->cmd != NULL; itr++)
+              printf("\t%s\n", itr->cmd);
+         }
+       fputc('\n', stdout);
+       return 1;
+     }
+
+   for (itr = maps; itr->cmd != NULL; itr++)
+     if (strcmp(itr->cmd, cmd) == 0)
+       return itr->cb(cmd, args);
+
+   printf("unknown command \"%s\", args=%s\n", cmd, args);
+   return 1;
+}
+
+int
+main(int argc, char *argv[])
+{
+   E_DBus_Connection *c;
+
+   ecore_init();
+   e_dbus_init();
+   eina_init();
+
+   c = e_dbus_bus_get(DBUS_BUS_SYSTEM);
+   if (!c) {
+      printf("ERROR: can't connect to system session\n");
+      return -1;
+   }
+
+   e_connman_system_init(c);
+   ecore_event_handler_add(E_CONNMAN_EVENT_ELEMENT_ADD, _on_element_add, NULL);
+   ecore_event_handler_add(E_CONNMAN_EVENT_ELEMENT_DEL, _on_element_del, NULL);
+   ecore_event_handler_add(E_CONNMAN_EVENT_ELEMENT_UPDATED,
+                          _on_element_updated, NULL);
+
+   ecore_main_fd_handler_add
+     (0, ECORE_FD_READ | ECORE_FD_ERROR, _on_input, NULL, NULL, NULL);
+
+   ecore_main_loop_begin();
+
+   e_connman_system_shutdown();
+
+   e_dbus_connection_close(c);
+   eina_shutdown();
+   e_dbus_shutdown();
+   ecore_shutdown();
+
+   fputs("DBG: clean exit.\n", stderr);
+
+   return 0;
+}
diff --git a/src/bin/e_dbus_connman_test_api.c b/src/bin/e_dbus_connman_test_api.c
new file mode 100644 (file)
index 0000000..e18f958
--- /dev/null
@@ -0,0 +1,544 @@
+#include "E_Connman.h"
+#include <stdio.h>
+#include <string.h>
+
+#define DBG(...) EINA_ERROR_PDBG(__VA_ARGS__)
+#define INF(...) EINA_ERROR_PINFO(__VA_ARGS__)
+#define WRN(...) EINA_ERROR_PWARN(__VA_ARGS__)
+#define ERR(...) EINA_ERROR_PERR(__VA_ARGS__)
+
+static int success = 0;
+static int failure = 0;
+static Ecore_Timer *exiter = NULL;
+
+static bool
+_test_string_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, const char **value))
+{
+   const char *value;
+   bool ret;
+
+   INF("BEGIN: testing string get %s of element %s...\n", name, element->path);
+   ret = func(element, &value);
+   if (ret)
+     INF("SUCCESS: testing string get %s of element %s: %s\n",
+        name, element->path, value);
+   else
+     WRN("FAILURE: testing string get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_bool_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, bool *value))
+{
+   bool value, ret;
+
+   INF("BEGIN: testing bool get %s of element %s...\n", name, element->path);
+   ret = func(element, &value);
+   if (ret)
+     INF("SUCCESS: testing bool get %s of element %s: %hhu\n",
+        name, element->path, value);
+   else
+     WRN("FAILURE: testing bool get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_uchar_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, unsigned char *value))
+{
+   unsigned char value;
+   bool ret;
+
+   INF("BEGIN: testing uchar get %s of element %s...\n", name, element->path);
+   ret = func(element, &value);
+   if (ret)
+     INF("SUCCESS: testing uchar get %s of element %s: %hhu\n",
+        name, element->path, value);
+   else
+     WRN("FAILURE: testing uchar get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_ushort_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, unsigned short *value))
+{
+   unsigned short value;
+   bool ret;
+
+   INF("BEGIN: testing ushort get %s of element %s...\n", name, element->path);
+   ret = func(element, &value);
+   if (ret)
+     INF("SUCCESS: testing ushort get %s of element %s: %hu\n",
+        name, element->path, value);
+   else
+     WRN("FAILURE: testing ushort get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_uchar_array_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, unsigned int *count, unsigned char **value))
+{
+   unsigned char *value;
+   unsigned int count;
+   bool ret;
+
+   INF("BEGIN: testing ushort get %s of element %s...\n", name, element->path);
+   ret = func(element, &count, &value);
+   if (ret)
+     {
+       INF("SUCCESS: testing ushort get %s of element %s: %p\n",
+           name, element->path, value);
+       free(value);
+     }
+   else
+     WRN("FAILURE: testing ushort get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_element_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, E_Connman_Element **value))
+{
+   E_Connman_Element *value;
+   bool ret;
+
+   INF("BEGIN: testing element get %s of element %s...\n", name, element->path);
+   ret = func(element, &value);
+   if (ret)
+     INF("SUCCESS: testing element get %s of element %s: %p\n",
+        name, element->path, value);
+   else
+     WRN("FAILURE: testing element get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_elements_get(E_Connman_Element *element, const char *name, bool (*func)(const E_Connman_Element *element, unsigned int *count, E_Connman_Element ***elements))
+{
+   E_Connman_Element **value;
+   unsigned int count;
+   bool ret;
+
+   INF("BEGIN: testing elements get %s of element %s...\n",
+       name, element->path);
+   ret = func(element, &count, &value);
+   if (ret)
+     {
+       INF("SUCCESS: testing elements get %s of element %s: %p\n",
+           name, element->path, value);
+       free(value);
+     }
+   else
+     WRN("FAILURE: testing elements get %s of element %s\n",
+        name, element->path);
+
+   return ret;
+}
+
+static bool
+_test_elements_get_global(const char *name, bool (*func)(unsigned int *count, E_Connman_Element ***elements))
+{
+   E_Connman_Element **value;
+   unsigned int count;
+   bool ret;
+
+   INF("BEGIN: testing elements get %s\n", name);
+   ret = func(&count, &value);
+   if (ret)
+     {
+       INF("SUCCESS: testing elements get %s: %p\n", name, value);
+       free(value);
+     }
+   else
+     WRN("FAILURE: testing elements get %s\n", name);
+
+   return ret;
+}
+
+static bool
+_test_string_get_global(const char *name, bool (*func)(const char **value))
+{
+   const char *value;
+   bool ret;
+
+   INF("BEGIN: testing string get %s...\n", name);
+   ret = func(&value);
+   if (ret)
+     INF("SUCCESS: testing string get %s: %s\n", name, value);
+   else
+     WRN("FAILURE: testing string get %s\n", name);
+
+   return ret;
+}
+
+static bool
+_test_bool_get_global(const char *name, bool (*func)(bool *value))
+{
+   bool value, ret;
+
+   INF("BEGIN: testing bool get %s...\n", name);
+   ret = func(&value);
+   if (ret)
+     INF("SUCCESS: testing bool get %s: %hhu\n", name, value);
+   else
+     WRN("FAILURE: testing bool get %s\n", name);
+
+   return ret;
+}
+
+struct test_desc
+{
+   const char *name;
+   enum {
+     TEST_DESC_TYPE_STRING_GET,
+     TEST_DESC_TYPE_BOOL_GET,
+     TEST_DESC_TYPE_UCHAR_GET,
+     TEST_DESC_TYPE_USHORT_GET,
+     TEST_DESC_TYPE_UCHAR_ARRAY_GET,
+     TEST_DESC_TYPE_ELEMENT_GET,
+     TEST_DESC_TYPE_ELEMENTS_GET,
+     TEST_DESC_TYPE_ELEMENTS_GET_GLOBAL,
+     TEST_DESC_TYPE_STRING_GET_GLOBAL,
+     TEST_DESC_TYPE_BOOL_GET_GLOBAL,
+     TEST_DESC_TYPE_LAST
+   } type;
+   union {
+      bool (*string_get)(const E_Connman_Element *element, const char **value);
+      bool (*bool_get)(const E_Connman_Element *element, bool *value);
+      bool (*uchar_get)(const E_Connman_Element *element, unsigned char *value);
+      bool (*ushort_get)(const E_Connman_Element *element, unsigned short*value);
+      bool (*uchar_array_get)(const E_Connman_Element *element, unsigned int *count, unsigned char **value);
+      bool (*element_get)(const E_Connman_Element *element, E_Connman_Element **value);
+      bool (*elements_get)(const E_Connman_Element *element, unsigned int *count, E_Connman_Element ***elements);
+      bool (*elements_get_global)(unsigned int *count, E_Connman_Element ***elements);
+      bool (*string_get_global)(const char **value);
+      bool (*bool_get_global)(bool *value);
+      void *dummy;
+   } func;
+   bool may_fail;
+};
+
+#define TEST_DESC_STRING_GET(_func, may_fail)                          \
+  {#_func, TEST_DESC_TYPE_STRING_GET, .func.string_get=_func, may_fail}
+#define TEST_DESC_BOOL_GET(_func, may_fail)                            \
+  {#_func, TEST_DESC_TYPE_BOOL_GET, .func.bool_get=_func, may_fail}
+#define TEST_DESC_UCHAR_GET(_func, may_fail)                           \
+  {#_func, TEST_DESC_TYPE_UCHAR_GET, .func.uchar_get=_func, may_fail}
+#define TEST_DESC_USHORT_GET(_func, may_fail)                          \
+  {#_func, TEST_DESC_TYPE_USHORT_GET, .func.ushort_get=_func, may_fail}
+#define TEST_DESC_UCHAR_ARRAY_GET(_func, may_fail)                     \
+  {#_func, TEST_DESC_TYPE_UCHAR_ARRAY_GET, .func.uchar_array_get=_func, may_fail}
+#define TEST_DESC_ELEMENT_GET(_func, may_fail)                         \
+  {#_func, TEST_DESC_TYPE_ELEMENT_GET, .func.element_get=_func, may_fail}
+#define TEST_DESC_ELEMENTS_GET(_func, may_fail)                                \
+  {#_func, TEST_DESC_TYPE_ELEMENTS_GET, .func.elements_get=_func, may_fail}
+#define TEST_DESC_ELEMENTS_GET_GLOBAL(_func, may_fail)                 \
+  {#_func, TEST_DESC_TYPE_ELEMENTS_GET_GLOBAL, .func.elements_get_global=_func, may_fail}
+#define TEST_DESC_STRING_GET_GLOBAL(_func, may_fail)                   \
+  {#_func, TEST_DESC_TYPE_STRING_GET_GLOBAL, .func.string_get_global=_func, may_fail}
+#define TEST_DESC_BOOL_GET_GLOBAL(_func, may_fail)                     \
+  {#_func, TEST_DESC_TYPE_BOOL_GET_GLOBAL, .func.bool_get_global=_func, may_fail}
+#define TEST_DESC_SENTINEL {NULL, TEST_DESC_TYPE_LAST, .func.dummy=NULL}
+
+static bool
+_test_element(E_Connman_Element *element, const struct test_desc *test_descs)
+{
+   const struct test_desc *itr;
+   int total, ok = 0, fail = 0;
+   bool ret = 1;
+
+   for (itr = test_descs; itr->type != TEST_DESC_TYPE_LAST; itr++)
+     {
+       bool r;
+
+       switch (itr->type)
+         {
+          case TEST_DESC_TYPE_STRING_GET:
+             r = _test_string_get(element, itr->name, itr->func.string_get);
+             break;
+          case TEST_DESC_TYPE_BOOL_GET:
+             r = _test_bool_get(element, itr->name, itr->func.bool_get);
+             break;
+          case TEST_DESC_TYPE_UCHAR_GET:
+             r = _test_uchar_get(element, itr->name, itr->func.uchar_get);
+             break;
+          case TEST_DESC_TYPE_USHORT_GET:
+             r = _test_ushort_get(element, itr->name, itr->func.ushort_get);
+             break;
+          case TEST_DESC_TYPE_UCHAR_ARRAY_GET:
+             r = _test_uchar_array_get
+               (element, itr->name, itr->func.uchar_array_get);
+             break;
+          case TEST_DESC_TYPE_ELEMENT_GET:
+             r = _test_element_get
+               (element, itr->name, itr->func.element_get);
+             break;
+          case TEST_DESC_TYPE_ELEMENTS_GET:
+             r = _test_elements_get
+               (element, itr->name, itr->func.elements_get);
+             break;
+          case TEST_DESC_TYPE_ELEMENTS_GET_GLOBAL:
+             r = _test_elements_get_global
+               (itr->name, itr->func.elements_get_global);
+             break;
+          case TEST_DESC_TYPE_STRING_GET_GLOBAL:
+             r = _test_string_get_global
+               (itr->name, itr->func.string_get_global);
+             break;
+          case TEST_DESC_TYPE_BOOL_GET_GLOBAL:
+             r = _test_bool_get_global
+               (itr->name, itr->func.bool_get_global);
+             break;
+          default:
+             ERR("unknown test type %d (%s)\n", itr->type, itr->name);
+             r = 0;
+             break;
+         }
+
+       if (r || itr->may_fail)
+         ok++;
+       else
+         {
+            ERR("test failed %s, element %s [%s]\n",
+                itr->name, element->path, element->interface);
+            fail++;
+            ret = 0;
+         }
+     }
+
+   total = ok + failure;
+   success += ok;
+   failure += fail;
+   if (total == 0)
+     {
+       INF("no tests for %s [%s]\n", element->path, element->interface);
+       return 1;
+     }
+
+   INF("testing %s success: %d, failure: %d: %d%% [%s]\n",
+       element->path, ok, fail, (ok * 100) / total,
+       element->interface);
+
+   return ret;
+}
+
+static const struct test_desc test_desc_manager[] = {
+  TEST_DESC_STRING_GET_GLOBAL(e_connman_manager_state_get, 0),
+  TEST_DESC_STRING_GET_GLOBAL(e_connman_manager_policy_get, 0),
+  //TEST_DESC_STRING_SET_GLOBAL(e_connman_manager_policy_set, 0),
+  TEST_DESC_BOOL_GET_GLOBAL(e_connman_manager_offline_mode_get, 0),
+  //TEST_DESC_BOOL_SET_GLOBAL(e_connman_manager_offline_mode_set, 0),
+  TEST_DESC_ELEMENTS_GET_GLOBAL(e_connman_manager_profiles_get, 0),
+  TEST_DESC_ELEMENTS_GET_GLOBAL(e_connman_manager_devices_get, 0),
+  TEST_DESC_ELEMENTS_GET_GLOBAL(e_connman_manager_connections_get, 1),
+  TEST_DESC_SENTINEL
+};
+
+static const struct test_desc test_desc_device[] = {
+  TEST_DESC_STRING_GET(e_connman_device_name_get, 0),
+  TEST_DESC_STRING_GET(e_connman_device_type_get, 0),
+  TEST_DESC_STRING_GET(e_connman_device_interface_get, 0),
+  TEST_DESC_STRING_GET(e_connman_device_policy_get, 0),
+  //TEST_DESC_STRING_SET(e_connman_device_policy_set, 0),
+  TEST_DESC_UCHAR_GET(e_connman_device_priority_get, 0),
+  //TEST_DESC_UCHAR_SET(e_connman_device_priority_set, 0),
+  TEST_DESC_BOOL_GET(e_connman_device_powered_get, 0),
+  //TEST_DESC_BOOL_SET(e_connman_device_powered_set, 0),
+  TEST_DESC_USHORT_GET(e_connman_device_scan_interval_get, 1),
+  //TEST_DESC_USHORT_SET(e_connman_device_scan_interval_set, 1),
+  TEST_DESC_BOOL_GET(e_connman_device_scanning_get, 1),
+  TEST_DESC_ELEMENTS_GET(e_connman_device_networks_get, 1),
+  TEST_DESC_SENTINEL
+};
+
+static const struct test_desc test_desc_profile[] = {
+  TEST_DESC_STRING_GET(e_connman_profile_name_get, 0),
+  TEST_DESC_SENTINEL
+};
+
+static const struct test_desc test_desc_connection[] = {
+  TEST_DESC_STRING_GET(e_connman_connection_type_get, 0),
+  TEST_DESC_STRING_GET(e_connman_connection_interface_get, 0),
+  TEST_DESC_UCHAR_GET(e_connman_connection_strength_get, 0),
+  TEST_DESC_BOOL_GET(e_connman_connection_default_get, 0),
+  TEST_DESC_ELEMENT_GET(e_connman_connection_device_get, 0),
+  TEST_DESC_ELEMENT_GET(e_connman_connection_network_get, 0),
+  TEST_DESC_STRING_GET(e_connman_connection_ipv4_method_get, 0),
+  TEST_DESC_STRING_GET(e_connman_connection_ipv4_address_get, 0),
+  TEST_DESC_SENTINEL
+};
+
+static const struct test_desc test_desc_network[] = {
+  TEST_DESC_STRING_GET(e_connman_network_name_get, 0),
+  TEST_DESC_BOOL_GET(e_connman_network_available_get, 0),
+  TEST_DESC_BOOL_GET(e_connman_network_connected_get, 0),
+  TEST_DESC_BOOL_GET(e_connman_network_remember_get, 0),
+  //TEST_DESC_BOOL_SET(e_connman_network_remember_set, 0),
+  TEST_DESC_UCHAR_GET(e_connman_network_strength_get, 1),
+  TEST_DESC_ELEMENT_GET(e_connman_network_device_get, 0),
+  TEST_DESC_UCHAR_ARRAY_GET(e_connman_network_wifi_ssid_get, 1),
+  TEST_DESC_STRING_GET(e_connman_network_wifi_mode_get, 1),
+  // TEST_DESC_STRING_SET(e_connman_network_wifi_mode_set, 1),
+  TEST_DESC_STRING_GET(e_connman_network_wifi_security_get, 1),
+  // TEST_DESC_STRING_SET(e_connman_network_wifi_security_set, 1),
+  TEST_DESC_STRING_GET(e_connman_network_wifi_passphrase_get, 1),
+  //TEST_DESC_STRING_SET(e_connman_network_wifi_passphrase_set, 1),
+  TEST_DESC_SENTINEL
+};
+
+static int
+_quit(void *data)
+{
+   ecore_main_loop_quit();
+   return 0;
+}
+
+static int
+_on_exiter(void *data)
+{
+   e_connman_system_shutdown();
+   ecore_idle_enterer_add(_quit, NULL);
+   exiter = NULL;
+   return 0;
+}
+
+static void
+_exiter_reschedule(void)
+{
+   if (exiter)
+     ecore_timer_del(exiter);
+   exiter = ecore_timer_add(10, _on_exiter, NULL);
+}
+
+struct test_element_timer_data
+{
+   E_Connman_Element *element;
+   Ecore_Timer *timer;
+};
+
+static int
+_test_element_timer(void *data)
+{
+   struct test_element_timer_data *d = data;
+   E_Connman_Element *element = d->element;
+
+   if (e_connman_element_is_device(element))
+     _test_element(element, test_desc_device);
+   else if (e_connman_element_is_profile(element))
+     _test_element(element, test_desc_profile);
+   else if (e_connman_element_is_connection(element))
+     _test_element(element, test_desc_connection);
+   else if (e_connman_element_is_network(element))
+     _test_element(element, test_desc_network);
+   else if (e_connman_element_is_manager(element))
+     _test_element(element, test_desc_manager);
+   else
+     ERR("!!! don't know how to test %s [%s]\n",
+        element->path, element->interface);
+
+   _exiter_reschedule();
+
+   d->timer = NULL;
+   return 0;
+}
+
+static void
+_element_listener(void *data, const E_Connman_Element *element)
+{
+   struct test_element_timer_data *d = data;
+   if (d->timer)
+     ecore_timer_del(d->timer);
+   d->timer = ecore_timer_add(1.0, _test_element_timer, d);
+   _exiter_reschedule();
+}
+
+static void
+_element_listener_free(void *data)
+{
+   struct test_element_timer_data *d = data;
+   if (d->timer)
+     ecore_timer_del(d->timer);
+   free(d);
+}
+
+static int
+_on_element_add(void *data, int type, void *info)
+{
+   E_Connman_Element *element = info;
+   struct test_element_timer_data *d;
+
+   d = malloc(sizeof(*d));
+   if (!d)
+     return 1;
+
+   d->element = element;
+   d->timer = ecore_timer_add(1.0, _test_element_timer, d);
+   e_connman_element_listener_add
+     (element, _element_listener, d, _element_listener_free);
+
+   return 1;
+}
+
+static int
+_on_element_del(void *data, int type, void *info)
+{
+   return 1;
+}
+
+static int
+_on_element_updated(void *data, int type, void *info)
+{
+   return 1;
+}
+
+int
+main(int argc, char *argv[])
+{
+   E_DBus_Connection *c;
+   int total;
+
+   ecore_init();
+   e_dbus_init();
+   eina_init();
+
+   c = e_dbus_bus_get(DBUS_BUS_SYSTEM);
+   if (!c) {
+      printf("ERROR: can't connect to system session\n");
+      return -1;
+   }
+
+   e_connman_system_init(c);
+   ecore_event_handler_add(E_CONNMAN_EVENT_ELEMENT_ADD, _on_element_add, NULL);
+   ecore_event_handler_add(E_CONNMAN_EVENT_ELEMENT_DEL, _on_element_del, NULL);
+   ecore_event_handler_add(E_CONNMAN_EVENT_ELEMENT_UPDATED,
+                          _on_element_updated, NULL);
+
+   _exiter_reschedule();
+
+   ecore_main_loop_begin();
+
+   e_dbus_connection_close(c);
+   eina_stringshare_dump();
+   eina_shutdown();
+   e_dbus_shutdown();
+   ecore_shutdown();
+
+   total = success + failure;
+   if (total == 0)
+     fputs("DBG: clean exit, no tests executed.\n", stderr);
+   else
+     fprintf(stderr, "DBG: clean exit, success: %d, failure: %d, %d%%\n",
+            success, failure, (success * 100) / total);
+
+   return 0;
+}
index 87c2fe1..bcb2dfe 100644 (file)
@@ -1,3 +1,3 @@
 MAINTAINERCLEANFILES = Makefile.in
 
-SUBDIRS=dbus hal nm notification
+SUBDIRS=dbus hal nm notification connman
diff --git a/src/lib/connman/E_Connman.h b/src/lib/connman/E_Connman.h
new file mode 100644 (file)
index 0000000..7ae4ae2
--- /dev/null
@@ -0,0 +1,232 @@
+#ifndef E_CONNMAN_H
+#define E_CONNMAN_H
+
+#include <E_DBus.h>
+#include <Ecore_Data.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#ifdef EAPI
+#undef EAPI
+#endif
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  /* Ecore Events */
+  extern int E_CONNMAN_EVENT_MANAGER_IN;
+  extern int E_CONNMAN_EVENT_MANAGER_OUT;
+  extern int E_CONNMAN_EVENT_ELEMENT_ADD;
+  extern int E_CONNMAN_EVENT_ELEMENT_DEL;
+  extern int E_CONNMAN_EVENT_ELEMENT_UPDATED;
+
+  typedef struct _E_Connman_Element E_Connman_Element;
+
+  struct _E_Connman_Element
+  {
+     const char *path;
+     const char *interface;
+     E_DBus_Signal_Handler *signal_handler;
+     Eina_Inlist *props;
+
+     /* private */
+     struct {
+       Eina_Inlist *properties_get;
+       Eina_Inlist *property_set;
+       Eina_Inlist *network_create;
+       Eina_Inlist *network_remove;
+       Eina_Inlist *network_connect;
+       Eina_Inlist *network_disconnect;
+       Eina_Inlist *agent_register;
+       Eina_Inlist *agent_unregister;
+       Eina_Inlist *device_propose_scan;
+     } _pending;
+     struct {
+       Ecore_Idler *changed;
+     } _idler;
+     Eina_Inlist *_listeners;
+     int _references;
+  };
+
+  EAPI unsigned int e_connman_system_init(E_DBus_Connection *edbus_conn) EINA_ARG_NONNULL(1);
+  EAPI unsigned int e_connman_system_shutdown(void);
+
+  EAPI bool e_connman_manager_sync_elements(void);
+
+  EAPI bool e_connman_elements_get_all(unsigned int *count, E_Connman_Element ***p_elements) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_elements_get_all_type(const char *type, unsigned int *count, E_Connman_Element ***p_elements) EINA_ARG_NONNULL(1, 2, 3) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI E_Connman_Element *e_connman_element_get(const char *path);
+
+  EAPI void e_connman_element_listener_add(E_Connman_Element *element, void (*cb)(void *data, const E_Connman_Element *element), const void *data, void (*free_data)(void *data)) EINA_ARG_NONNULL(1, 2);
+  EAPI void e_connman_element_listener_del(E_Connman_Element *element, void (*cb)(void *data, const E_Connman_Element *element), const void *data) EINA_ARG_NONNULL(1, 2);
+
+  EAPI int e_connman_element_ref(E_Connman_Element *element) EINA_ARG_NONNULL(1);
+  EAPI int e_connman_element_unref(E_Connman_Element *element) EINA_ARG_NONNULL(1);
+
+  EAPI void e_connman_element_print(FILE *fp, const E_Connman_Element *element) EINA_ARG_NONNULL(1, 2);
+
+
+  EAPI bool e_connman_element_properties_sync(E_Connman_Element *element) EINA_ARG_NONNULL(1);
+  EAPI bool e_connman_element_properties_sync_full(E_Connman_Element *element, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1);
+
+  EAPI bool e_connman_element_property_set(E_Connman_Element *element, const char *prop, int type, const void *value) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_property_set_full(E_Connman_Element *element, const char *prop, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
+
+  EAPI void e_connman_element_properties_list(const E_Connman_Element *element, bool (*cb)(void *data, const E_Connman_Element *element, const char *name, int type, const void *value), const void *data) EINA_ARG_NONNULL(1, 2);
+
+  EAPI bool e_connman_element_property_type_get_stringshared(const E_Connman_Element *element, const char *name, int *type) EINA_ARG_NONNULL(1, 2, 3) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_property_type_get(const E_Connman_Element *element, const char *name, int *type) EINA_ARG_NONNULL(1, 2, 3) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_property_get_stringshared(const E_Connman_Element *element, const char *name, int *type, void *value) EINA_ARG_NONNULL(1, 2, 4) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_property_get(const E_Connman_Element *element, const char *name, int *type, void *value) EINA_ARG_NONNULL(1, 2, 4) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_element_is_manager(const E_Connman_Element *element) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_is_device(const E_Connman_Element *element) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_is_profile(const E_Connman_Element *element) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_is_connection(const E_Connman_Element *element) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_element_is_network(const E_Connman_Element *element) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+
+  /* Manager Methods */
+
+  EAPI E_Connman_Element *e_connman_manager_get(void) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_manager_register_agent(const char *object_path, E_DBus_Method_Return_Cb cb, const void *data);
+  EAPI bool e_connman_manager_unregister_agent(const char *object_path, E_DBus_Method_Return_Cb cb, const void *data);
+
+  EAPI bool e_connman_manager_state_get(const char **state);
+
+  EAPI bool e_connman_manager_policy_get(const char **policy);
+  EAPI bool e_connman_manager_policy_set(const char *policy, E_DBus_Method_Return_Cb cb, const void *data);
+
+  EAPI bool e_connman_manager_offline_mode_get(bool *offline);
+  EAPI bool e_connman_manager_offline_mode_set(bool offline, E_DBus_Method_Return_Cb cb, const void *data);
+
+  EAPI bool e_connman_manager_profiles_get(unsigned int *count, E_Connman_Element ***p_elements);
+  EAPI bool e_connman_manager_devices_get(unsigned int *count, E_Connman_Element ***p_elements);
+  EAPI bool e_connman_manager_connections_get(unsigned int *count, E_Connman_Element ***p_elements);
+
+  // TODO: profile_add (not implemented in connman right now)
+  // TODO: profile_remove (not implemented in connman right now)
+  // TODO: profile_active_get (not implemented in connman right now)
+  // TODO: profile_active_set (not implemented in connman right now)
+  // TODO: services_get (not implemented in connman right now)
+
+
+  /* Device Methods */
+  EAPI E_Connman_Element *e_connman_device_get(const char *path) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_network_create(E_Connman_Element *device, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_device_network_remove(E_Connman_Element *device, const char *network_path, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_propose_scan(E_Connman_Element *device, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_name_get(const E_Connman_Element *device, const char **name) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_type_get(const E_Connman_Element *device, const char **type) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_interface_get(const E_Connman_Element *device, const char **interface) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_policy_get(const E_Connman_Element *device, const char **policy) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_device_policy_set(E_Connman_Element *device, const char *policy, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_priority_get(const E_Connman_Element *device, unsigned char *priority) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_device_priority_set(E_Connman_Element *device, unsigned char priority, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_powered_get(const E_Connman_Element *device, bool *powered) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_device_powered_set(E_Connman_Element *device, bool powered, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_scan_interval_get(const E_Connman_Element *device, unsigned short *scan_interval) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_device_scan_interval_set(E_Connman_Element *device, unsigned short scan_interval, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_scanning_get(const E_Connman_Element *device, bool *scanning) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_device_networks_get(const E_Connman_Element *device, unsigned int *count, E_Connman_Element ***p_elements) EINA_ARG_NONNULL(1, 2, 3) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  // TODO: network_join (harder, need to think of good api that do not suck)
+  // TODO: address_get
+
+
+  /* Profile Methods */
+
+  EAPI E_Connman_Element *e_connman_profile_get(const char *path) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_profile_name_get(const E_Connman_Element *profile, const char **name) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  // TODO: services_get (not implemented in connman right now)
+
+  /* Connection Methods */
+
+  EAPI E_Connman_Element *e_connman_connection_get(const char *path) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_connection_type_get(const E_Connman_Element *connection, const char **type) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_connection_interface_get(const E_Connman_Element *connection, const char **interface) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_connection_strength_get(const E_Connman_Element *connection, unsigned char *strength) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_connection_default_get(const E_Connman_Element *connection, bool *connection_default) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_connection_device_get(const E_Connman_Element *connection, E_Connman_Element **element) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_connection_network_get(const E_Connman_Element *connection, E_Connman_Element **element) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_connection_ipv4_method_get(const E_Connman_Element *connection, const char **method) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_connection_ipv4_address_get(const E_Connman_Element *connection, const char **address) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  // TODO: ipv4_gateway_get
+  // TODO: ipv4_netmask_get
+
+
+  /* Network Methods */
+  EAPI E_Connman_Element *e_connman_network_get(const char *path) EINA_ARG_NONNULL(1) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_connect(E_Connman_Element *network, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_network_disconnect(E_Connman_Element *network, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_name_get(const E_Connman_Element *network, const char **name) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_available_get(const E_Connman_Element *network, bool *available) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_connected_get(const E_Connman_Element *network, bool *connected) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_remember_get(const E_Connman_Element *network, bool *remember) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_network_remember_set(E_Connman_Element *network, bool remember, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_strength_get(const E_Connman_Element *network, unsigned char *strength) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_device_get(const E_Connman_Element *network, E_Connman_Element **element) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_wifi_ssid_get(const E_Connman_Element *network, unsigned int *count, unsigned char **wifi_ssid) EINA_ARG_NONNULL(1, 2, 3) EINA_PURE EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_wifi_mode_get(const E_Connman_Element *network, const char **wifi_mode) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_network_wifi_mode_set(E_Connman_Element *network, const char *wifi_mode, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_wifi_security_get(const E_Connman_Element *network, const char **wifi_security) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_network_wifi_security_set(E_Connman_Element *network, const char *wifi_security, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  EAPI bool e_connman_network_wifi_passphrase_get(const E_Connman_Element *network, const char **wifi_passphare) EINA_ARG_NONNULL(1, 2) EINA_PURE EINA_WARN_UNUSED_RESULT;
+  EAPI bool e_connman_network_wifi_passphrase_set(E_Connman_Element *network, const char *wifi_passphrase, E_DBus_Method_Return_Cb cb, const void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+  // TODO: address_get
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* E_CONNMAN_H */
diff --git a/src/lib/connman/Makefile.am b/src/lib/connman/Makefile.am
new file mode 100644 (file)
index 0000000..2cf6d9c
--- /dev/null
@@ -0,0 +1,30 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I $(top_srcdir)/src/lib/dbus \
+@EDBUS_CFLAGS@ @EVAS_CFLAGS@ @EINA_CFLAGS@
+
+if BUILD_ECONNMAN
+
+lib_LTLIBRARIES = libeconnman.la
+include_HEADERS = E_Connman.h
+
+libeconnman_la_SOURCES = \
+E_Connman.h \
+e_connman_private.h \
+e_connman.c \
+e_connman_connection.c \
+e_connman_device.c \
+e_connman_element.c \
+e_connman_manager.c \
+e_connman_network.c \
+e_connman_profile.c
+
+libeconnman_la_LIBADD = \
+@EDBUS_LIBS@ @EVAS_LIBS@ \
+$(top_builddir)/src/lib/dbus/libedbus.la \
+@EINA_LIBS@
+
+libeconnman_la_LDFLAGS = -version-info @version_info@
+
+endif
diff --git a/src/lib/connman/e_connman.c b/src/lib/connman/e_connman.c
new file mode 100644 (file)
index 0000000..f339eac
--- /dev/null
@@ -0,0 +1,404 @@
+#include "e_connman_private.h"
+#include <stdlib.h>
+#include <string.h>
+
+static E_DBus_Signal_Handler *cb_name_owner_changed = NULL;
+static DBusPendingCall *pending_get_name_owner = NULL;
+static unsigned int init_count = 0;
+static char *unique_name = NULL;
+
+static const char bus_name[] = "org.moblin.connman";
+static const char fdo_bus_name[] = "org.freedesktop.DBus";
+static const char fdo_interface[] = "org.freedesktop.DBus";
+static const char fdo_path[] = "/org/freedesktop/DBus";
+
+E_DBus_Connection *e_connman_conn = NULL;
+
+EAPI int E_CONNMAN_EVENT_MANAGER_IN = 0;
+EAPI int E_CONNMAN_EVENT_MANAGER_OUT = 0;
+EAPI int E_CONNMAN_EVENT_ELEMENT_ADD = 0;
+EAPI int E_CONNMAN_EVENT_ELEMENT_DEL = 0;
+EAPI int E_CONNMAN_EVENT_ELEMENT_UPDATED = 0;
+
+const char *e_connman_iface_manager = NULL;
+const char *e_connman_iface_network = NULL;
+const char *e_connman_iface_profile = NULL;
+const char *e_connman_iface_service = NULL;
+const char *e_connman_iface_device = NULL;
+const char *e_connman_iface_connection = NULL;
+
+const char *e_connman_prop_available = NULL;
+const char *e_connman_prop_connected = NULL;
+const char *e_connman_prop_connections = NULL;
+const char *e_connman_prop_default = NULL;
+const char *e_connman_prop_device = NULL;
+const char *e_connman_prop_devices = NULL;
+const char *e_connman_prop_interface = NULL;
+const char *e_connman_prop_ipv4_address = NULL;
+const char *e_connman_prop_ipv4_method = NULL;
+const char *e_connman_prop_name = NULL;
+const char *e_connman_prop_network = NULL;
+const char *e_connman_prop_networks = NULL;
+const char *e_connman_prop_offline_mode = NULL;
+const char *e_connman_prop_policy = NULL;
+const char *e_connman_prop_powered = NULL;
+const char *e_connman_prop_priority = NULL;
+const char *e_connman_prop_profiles = NULL;
+const char *e_connman_prop_remember = NULL;
+const char *e_connman_prop_scan_interval = NULL;
+const char *e_connman_prop_scanning = NULL;
+const char *e_connman_prop_state = NULL;
+const char *e_connman_prop_strengh = NULL;
+const char *e_connman_prop_type = NULL;
+const char *e_connman_prop_wifi_mode = NULL;
+const char *e_connman_prop_wifi_passphrase = NULL;
+const char *e_connman_prop_wifi_security = NULL;
+const char *e_connman_prop_wifi_ssid = NULL;
+
+const char *
+e_connman_system_bus_name_get(void)
+{
+   return unique_name ? unique_name : bus_name;
+}
+
+
+/***********************************************************************
+ * Manager
+ ***********************************************************************/
+
+/**
+ * Synchronize elements with server.
+ *
+ * This will call Manager.GetProperties() on server, retrieve properties
+ * and some element paths and then request their properties.
+ *
+ * This call will add events E_CONNMAN_EVENT_ELEMENT_ADD and
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED to the main loop.
+ *
+ * This will not remove stale elements.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_sync_elements(void)
+{
+   E_Connman_Element *manager;
+
+   if (!unique_name)
+     return FALSE;
+   manager = e_connman_element_register(manager_path, e_connman_iface_manager);
+   if (manager)
+     e_connman_element_properties_sync(manager);
+   else
+     return FALSE;
+
+   DBG("sync_manager: %s (%s)\n", unique_name, bus_name);
+
+   return TRUE;
+}
+
+static void
+_e_connman_system_name_owner_exit(void)
+{
+   e_connman_manager_clear_elements();
+   ecore_event_add(E_CONNMAN_EVENT_MANAGER_OUT, NULL, NULL, NULL);
+
+   free(unique_name);
+   unique_name = NULL;
+}
+
+static void
+_e_connman_system_name_owner_enter(const char *uid)
+{
+   DBG("enter connman at %s (old was %s)\n", uid, unique_name);
+   if (unique_name && strcmp(unique_name, uid) == 0)
+     {
+       DBG("same unique_name for connman, ignore.\n");
+       return;
+     }
+
+   if (unique_name)
+     _e_connman_system_name_owner_exit();
+
+   unique_name = strdup(uid);
+
+   ecore_event_add(E_CONNMAN_EVENT_MANAGER_IN, NULL, NULL, NULL);
+   e_connman_manager_sync_elements();
+}
+
+static void
+_e_connman_system_name_owner_changed(void *data, DBusMessage *msg)
+{
+   DBusError err;
+   const char *name, *from, *to;
+
+   dbus_error_init(&err);
+   if (!dbus_message_get_args(msg, &err,
+                             DBUS_TYPE_STRING, &name,
+                             DBUS_TYPE_STRING, &from,
+                             DBUS_TYPE_STRING, &to,
+                             DBUS_TYPE_INVALID))
+     {
+       ERR("could not get NameOwnerChanged arguments: %s: %s\n",
+           err.name, err.message);
+       dbus_error_free(&err);
+       return;
+     }
+
+   if (strcmp(name, bus_name) != 0)
+     return;
+
+   DBG("NameOwnerChanged from=[%s] to=[%s]\n", from, to);
+
+   if (from[0] == '\0' && to[0] != '\0')
+     _e_connman_system_name_owner_enter(to);
+   else if (from[0] != '\0' && to[0] == '\0')
+     {
+       DBG("exit connman at %s\n", from);
+       if (strcmp(unique_name, from) != 0)
+         DBG("%s was not the known name %s, ignored.\n", from, unique_name);
+       else
+         _e_connman_system_name_owner_exit();
+     }
+   else
+     DBG("unknow change from %s to %s\n", from, to);
+}
+
+static void
+_e_connman_get_name_owner(void *data, DBusMessage *msg, DBusError *err)
+{
+   DBusMessageIter itr;
+   int t;
+   const char *uid;
+
+   pending_get_name_owner = NULL;
+
+   if (!_dbus_callback_check_and_init(msg, &itr, err))
+     return;
+
+   t = dbus_message_iter_get_arg_type(&itr);
+   if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
+     return;
+
+   dbus_message_iter_get_basic(&itr, &uid);
+   if (!uid)
+     {
+       ERR("no name owner!\n");
+       return;
+     }
+
+   _e_connman_system_name_owner_enter(uid);
+   return;
+}
+
+/**
+ * Initialize E Connection Manager (E_Connman) system.
+ *
+ * This will connect and watch org.moblin.connman.Manager and Element
+ * events and translate to Ecore main loop events, also provide a
+ * proxy for method invocation on server.
+ *
+ * Interesting events are:
+ *   - E_CONNMAN_EVENT_MANAGER_IN: issued when connman is avaiable.
+ *   - E_CONNMAN_EVENT_MANAGER_OUT: issued when connman connection is lost.
+ *   - E_CONNMAN_EVENT_ELEMENT_ADD: element was added.
+ *   - E_CONNMAN_EVENT_ELEMENT_DEL: element was deleted.
+ *   - E_CONNMAN_EVENT_ELEMENT_UPDATED: element was updated (properties
+ *     or state changed).
+ *
+ * Manager IN/OUT events do not provide any event information, just
+ * tells you that system is usable or not. After manager is out, all
+ * elements will be removed, so after this event do not use the system anymore.
+ *
+ * Element events will give you an element object. After DEL event callback
+ * returns, that element will not be valid anymore.
+ */
+unsigned int
+e_connman_system_init(E_DBus_Connection *edbus_conn)
+{
+   init_count++;
+
+   if (init_count > 1)
+     return init_count;
+
+   if (!eina_init())
+     fputs("ERROR: Error during the initialization of eina.\n", stderr);
+
+   if (E_CONNMAN_EVENT_MANAGER_IN == 0)
+     E_CONNMAN_EVENT_MANAGER_IN = ecore_event_type_new();
+   if (E_CONNMAN_EVENT_MANAGER_OUT == 0)
+     E_CONNMAN_EVENT_MANAGER_OUT = ecore_event_type_new();
+   if (E_CONNMAN_EVENT_ELEMENT_ADD == 0)
+     E_CONNMAN_EVENT_ELEMENT_ADD = ecore_event_type_new();
+   if (E_CONNMAN_EVENT_ELEMENT_DEL == 0)
+     E_CONNMAN_EVENT_ELEMENT_DEL = ecore_event_type_new();
+   if (E_CONNMAN_EVENT_ELEMENT_UPDATED == 0)
+     E_CONNMAN_EVENT_ELEMENT_UPDATED = ecore_event_type_new();
+
+   if (e_connman_iface_manager == NULL)
+     e_connman_iface_manager = eina_stringshare_add("org.moblin.connman.Manager");
+   if (e_connman_iface_network == NULL)
+     e_connman_iface_network = eina_stringshare_add("org.moblin.connman.Network");
+   if (e_connman_iface_profile == NULL)
+     e_connman_iface_profile = eina_stringshare_add("org.moblin.connman.Profile");
+   if (e_connman_iface_service == NULL)
+     e_connman_iface_service = eina_stringshare_add("org.moblin.connman.Service");
+   if (e_connman_iface_device == NULL)
+     e_connman_iface_device = eina_stringshare_add("org.moblin.connman.Device");
+   if (e_connman_iface_connection == NULL)
+     e_connman_iface_connection = eina_stringshare_add("org.moblin.connman.Connection");
+
+   if (e_connman_prop_available == NULL)
+     e_connman_prop_available = eina_stringshare_add("Available");
+   if (e_connman_prop_connected == NULL)
+     e_connman_prop_connected = eina_stringshare_add("Connected");
+   if (e_connman_prop_connections == NULL)
+     e_connman_prop_connections = eina_stringshare_add("Connections");
+   if (e_connman_prop_default == NULL)
+     e_connman_prop_default = eina_stringshare_add("Default");
+   if (e_connman_prop_device == NULL)
+     e_connman_prop_device = eina_stringshare_add("Device");
+   if (e_connman_prop_devices == NULL)
+     e_connman_prop_devices = eina_stringshare_add("Devices");
+   if (e_connman_prop_interface == NULL)
+     e_connman_prop_interface = eina_stringshare_add("Interface");
+   if (e_connman_prop_ipv4_address == NULL)
+     e_connman_prop_ipv4_address = eina_stringshare_add("IPv4.Address");
+   if (e_connman_prop_ipv4_method == NULL)
+     e_connman_prop_ipv4_method = eina_stringshare_add("IPv4.Method");
+   if (e_connman_prop_name == NULL)
+     e_connman_prop_name = eina_stringshare_add("Name");
+   if (e_connman_prop_network == NULL)
+     e_connman_prop_network = eina_stringshare_add("Network");
+   if (e_connman_prop_networks == NULL)
+     e_connman_prop_networks = eina_stringshare_add("Networks");
+   if (e_connman_prop_offline_mode == NULL)
+     e_connman_prop_offline_mode = eina_stringshare_add("OfflineMode");
+   if (e_connman_prop_policy == NULL)
+     e_connman_prop_policy = eina_stringshare_add("Policy");
+   if (e_connman_prop_powered == NULL)
+     e_connman_prop_powered = eina_stringshare_add("Powered");
+   if (e_connman_prop_priority == NULL)
+     e_connman_prop_priority = eina_stringshare_add("Priority");
+   if (e_connman_prop_profiles == NULL)
+     e_connman_prop_profiles = eina_stringshare_add("Profiles");
+   if (e_connman_prop_remember == NULL)
+     e_connman_prop_remember = eina_stringshare_add("Remember");
+   if (e_connman_prop_scan_interval == NULL)
+     e_connman_prop_scan_interval = eina_stringshare_add("ScanInterval");
+   if (e_connman_prop_scanning == NULL)
+     e_connman_prop_scanning = eina_stringshare_add("Scanning");
+   if (e_connman_prop_state == NULL)
+     e_connman_prop_state = eina_stringshare_add("State");
+   if (e_connman_prop_strengh == NULL)
+     e_connman_prop_strengh = eina_stringshare_add("Strength");
+   if (e_connman_prop_type == NULL)
+     e_connman_prop_type = eina_stringshare_add("Type");
+   if (e_connman_prop_wifi_mode == NULL)
+     e_connman_prop_wifi_mode = eina_stringshare_add("WiFi.Mode");
+   if (e_connman_prop_wifi_passphrase == NULL)
+     e_connman_prop_wifi_passphrase = eina_stringshare_add("WiFi.Passphrase");
+   if (e_connman_prop_wifi_security == NULL)
+     e_connman_prop_wifi_security = eina_stringshare_add("WiFi.Security");
+   if (e_connman_prop_wifi_ssid == NULL)
+     e_connman_prop_wifi_ssid = eina_stringshare_add("WiFi.SSID");
+
+   e_connman_conn = edbus_conn;
+   cb_name_owner_changed = e_dbus_signal_handler_add
+     (e_connman_conn, fdo_bus_name, fdo_path, fdo_interface, "NameOwnerChanged",
+      _e_connman_system_name_owner_changed, NULL);
+
+   if (pending_get_name_owner)
+     dbus_pending_call_cancel(pending_get_name_owner);
+
+   pending_get_name_owner = e_dbus_get_name_owner
+     (e_connman_conn, bus_name, _e_connman_get_name_owner, NULL);
+
+   e_connman_elements_init();
+
+   return init_count;
+}
+
+static inline void
+_stringshare_del(const char **str)
+{
+   if (!*str)
+     return;
+   eina_stringshare_del(*str);
+   *str = NULL;
+}
+
+/**
+ * Shutdown connman system.
+ *
+ * When count drops to 0 resources will be released and no calls should be
+ * made anymore.
+ */
+unsigned int
+e_connman_system_shutdown(void)
+{
+   if (init_count == 0)
+     {
+       fputs("ERROR: connman system already shutdown.\n", stderr);
+       return 0;
+     }
+   init_count--;
+   if (init_count > 0)
+     return init_count;
+
+   _stringshare_del(&e_connman_iface_manager);
+   _stringshare_del(&e_connman_iface_network);
+   _stringshare_del(&e_connman_iface_profile);
+   _stringshare_del(&e_connman_iface_service);
+   _stringshare_del(&e_connman_iface_device);
+   _stringshare_del(&e_connman_iface_connection);
+
+   _stringshare_del(&e_connman_prop_available);
+   _stringshare_del(&e_connman_prop_connected);
+   _stringshare_del(&e_connman_prop_connections);
+   _stringshare_del(&e_connman_prop_default);
+   _stringshare_del(&e_connman_prop_device);
+   _stringshare_del(&e_connman_prop_devices);
+   _stringshare_del(&e_connman_prop_interface);
+   _stringshare_del(&e_connman_prop_ipv4_address);
+   _stringshare_del(&e_connman_prop_ipv4_method);
+   _stringshare_del(&e_connman_prop_name);
+   _stringshare_del(&e_connman_prop_network);
+   _stringshare_del(&e_connman_prop_networks);
+   _stringshare_del(&e_connman_prop_offline_mode);
+   _stringshare_del(&e_connman_prop_policy);
+   _stringshare_del(&e_connman_prop_powered);
+   _stringshare_del(&e_connman_prop_priority);
+   _stringshare_del(&e_connman_prop_profiles);
+   _stringshare_del(&e_connman_prop_remember);
+   _stringshare_del(&e_connman_prop_scan_interval);
+   _stringshare_del(&e_connman_prop_scanning);
+   _stringshare_del(&e_connman_prop_state);
+   _stringshare_del(&e_connman_prop_strengh);
+   _stringshare_del(&e_connman_prop_type);
+   _stringshare_del(&e_connman_prop_wifi_mode);
+   _stringshare_del(&e_connman_prop_wifi_passphrase);
+   _stringshare_del(&e_connman_prop_wifi_security);
+   _stringshare_del(&e_connman_prop_wifi_ssid);
+
+   if (pending_get_name_owner)
+     {
+       dbus_pending_call_cancel(pending_get_name_owner);
+       pending_get_name_owner = NULL;
+     }
+
+   if (cb_name_owner_changed)
+     {
+       e_dbus_signal_handler_del(e_connman_conn, cb_name_owner_changed);
+       cb_name_owner_changed = NULL;
+     }
+
+   if (unique_name)
+     _e_connman_system_name_owner_exit();
+
+   e_connman_elements_shutdown();
+   eina_shutdown();
+   e_connman_conn = NULL;
+
+   return init_count;
+}
diff --git a/src/lib/connman/e_connman_connection.c b/src/lib/connman/e_connman_connection.c
new file mode 100644 (file)
index 0000000..0a92ceb
--- /dev/null
@@ -0,0 +1,225 @@
+#include "e_connman_private.h"
+
+E_Connman_Element *
+e_connman_connection_get(const char *path)
+{
+   E_Connman_Element *connection;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
+
+   connection = e_connman_element_get(path);
+   if (!connection)
+     return NULL;
+
+   if (!e_connman_element_is_connection(connection))
+     {
+       WRN("path '%s' is not a connection!\n", path);
+       return NULL;
+     }
+
+   return connection;
+}
+
+/**
+ * Get property "Type" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The connection type (for example "wifi", etc.)
+ *
+ * @param connection_path to get property.
+ * @param type where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_type_get(const E_Connman_Element *connection, const char **type)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(type, 0);
+   return e_connman_element_property_get_stringshared
+     (connection, e_connman_prop_type, NULL, type);
+}
+
+/**
+ * Get property "Interface" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The connection interface (for example "eth0" etc.)
+ *
+ * This value is for pure informational purposes. It
+ * is not guaranteed that it is always present.
+ *
+ * @param connection_path to get property.
+ * @param interface where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_interface_get(const E_Connman_Element *connection, const char **interface)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(interface, 0);
+   return e_connman_element_property_get_stringshared
+     (connection, e_connman_prop_interface, NULL, interface);
+}
+
+/**
+ * Get property "Strength" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates the signal strength of the connection.
+ *
+ * This property is optional and not always present.
+ *
+ * @param connection_path to get property.
+ * @param strength where to store the property value, must be a pointer
+ *        to byte (unsigned char*).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_strength_get(const E_Connman_Element *connection, unsigned char *strength)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(strength, 0);
+   return e_connman_element_property_get_stringshared
+     (connection, e_connman_prop_strengh, NULL, strength);
+}
+
+/**
+ * Get property "Default" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates if it is a default connection. It is
+ * possible to have multiple default connections.
+ *
+ * @param connection_path to get property.
+ * @param connection_default where to store the property value, must be a
+ *        pointer to boolean (bool *).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_default_get(const E_Connman_Element *connection, bool *connection_default)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection_default, 0);
+   return e_connman_element_property_get_stringshared
+     (connection, e_connman_prop_default, NULL, connection_default);
+}
+
+/**
+ * Get the device element this connection has
+ * been established with.
+ *
+ * @param connection_path to get property.
+ * @param element where to store element, just changed if return is 1
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_device_get(const E_Connman_Element *connection, E_Connman_Element **element)
+{
+   const char *device_path;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   if (!e_connman_element_property_get_stringshared
+       (connection, e_connman_prop_device, NULL, &device_path))
+     return 0;
+   *element = e_connman_element_get(device_path);
+   return 1;
+}
+
+/**
+ * Get the network element this connection
+ * belongs to.
+ *
+ * @param connection_path to get property.
+ * @param element where to store element, just changed if return is 1
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_network_get(const E_Connman_Element *connection, E_Connman_Element **element)
+{
+   const char *network_path;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   if (!e_connman_element_property_get_stringshared
+       (connection, e_connman_prop_network, NULL, &network_path))
+     return 0;
+   *element = e_connman_element_get(network_path);
+   return 1;
+}
+
+/**
+ * Get property "IPv4.Method" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates the way how the IPv4 settings were
+ * configured. Possible values here are "dhcp"
+ * and "static".
+ *
+ * @param connection_path to get property.
+ * @param method where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_ipv4_method_get(const E_Connman_Element *connection, const char **method)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(method, 0);
+   return e_connman_element_property_get_stringshared
+     (connection, e_connman_prop_ipv4_method, NULL, method);
+}
+
+/**
+ * Get property "IPv4.Address" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Shows the current configured IPv4 address.
+ *
+ * @param connection_path to get property.
+ * @param address where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_connection_ipv4_address_get(const E_Connman_Element *connection, const char **address)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connection, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(address, 0);
+   return e_connman_element_property_get_stringshared
+     (connection, e_connman_prop_ipv4_address, NULL, address);
+}
diff --git a/src/lib/connman/e_connman_device.c b/src/lib/connman/e_connman_device.c
new file mode 100644 (file)
index 0000000..028dd21
--- /dev/null
@@ -0,0 +1,538 @@
+#include "e_connman_private.h"
+
+E_Connman_Element *
+e_connman_device_get(const char *path)
+{
+   E_Connman_Element *device;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
+
+   device = e_connman_element_get(path);
+   if (!device)
+     return NULL;
+
+   if (!e_connman_element_is_device(device))
+     {
+       WRN("path '%s' is not a device!\n", path);
+       return NULL;
+     }
+
+   return device;
+}
+
+static void
+_e_connman_device_network_create_callback(void *user_data, DBusMessage *msg, DBusError *err)
+{
+   WRN("FIXME need to receive the network object path\n");
+}
+
+/**
+ * Creates a network object from the specified properties. Valid
+ * properties are WiFi.SSID, WiFi.Security and WiFi.Passphrase.
+ *
+ * Call method CreateNetwork(dict_network) at the given device
+ * on server.
+ *
+ * @param device_path to call method on server.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_network_create(E_Connman_Element *device, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "CreateNetwork";
+   DBusMessageIter itr, v;
+   DBusMessage *msg;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+
+   msg = dbus_message_new_method_call
+     (e_connman_system_bus_name_get(), device->path, device->interface,
+      name);
+
+   if (!msg)
+     return 0;
+
+   dbus_message_iter_init_append(msg, &itr);
+   dbus_message_iter_open_container(&itr, DBUS_TYPE_ARRAY,
+                                   DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                   DBUS_TYPE_STRING_AS_STRING
+                                   DBUS_TYPE_VARIANT_AS_STRING
+                                   DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &v);
+
+   /* FIXME need to create the message */
+
+   dbus_message_iter_close_container(&itr, &v);
+   return e_connman_element_message_send
+     (device, name, _e_connman_device_network_create_callback,
+      msg, &device->_pending.network_create, cb, data);
+}
+
+/**
+ * Removes a previoulsy created network object.
+ *
+ * Call method RemoveNetwork(network) at the given device on server in order to remove
+ * it.
+ *
+ * @param device_path to call method on server.
+ * @param network_path network path to be removed.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_network_remove(E_Connman_Element *device, const char *network_path, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "RemoveNetwork";
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network_path, 0);
+   return e_connman_element_call_with_path
+     (device, name, network_path, NULL,
+      &device->_pending.network_remove, cb, data);
+}
+
+/**
+ * Propose device to scan.
+ *
+ * Call method ProposeScan() at the given device on server in order to propose it
+ * to scan.
+ *
+ * @param device_path to call method on server.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_propose_scan(E_Connman_Element *device, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "ProposeScan";
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   return e_connman_element_call_full
+     (device, name, NULL, &device->_pending.device_propose_scan, cb, data);
+}
+
+/**
+ * Get property "Name" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The device name (for example "Wireless" etc.)
+ *
+ * This name can be used for directly displaying it in
+ * the application. It has pure informational purpose.
+ *
+ * @param device_path to get property.
+ * @param name where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_name_get(const E_Connman_Element *device, const char **name)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_name, NULL, name);
+}
+
+/**
+ * Get property "Type" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The device type (for example "ethernet", "wifi" etc.)
+ *
+ * @param device_path to get property.
+ * @param type where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_type_get(const E_Connman_Element *device, const char **type)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(type, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_type, NULL, type);
+}
+
+/**
+ * Get property "Interface" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The device interface (for example "eth0" etc.)
+ *
+ * This value is for pure informational purposes. It
+ * is not guaranteed that it is always present.
+ *
+ * @param device_path to get property.
+ * @param interface where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_interface_get(const E_Connman_Element *device, const char **interface)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(interface, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_interface, NULL, interface);
+}
+
+/**
+ * Get property "Policy" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Setting of the device power and connection policy.
+ * Possible values are "ignore", "off", "auto"
+ * and "manual".
+ *
+ * The policy defines on how the device is initialized
+ * when brought up and how it connects. The actual
+ * device power state can be changed independently to
+ * this value.
+ *
+ * If a device is switched off and the policy is changed
+ * to "auto" or "manual", the device will be switched
+ * on. For a current active device changing the policy
+ * to "off" results in powering down the device.
+ *
+ * The "ignore" policy can be set for devices that are
+ * detected, but managed by a different entity on the
+ * system. For example for complex network setups.
+ *
+ * Devices that can connect to various networks, the
+ * difference between "auto" or "manual" defines if
+ * known networks are connected automatically or not.
+ * For simple devices like Ethernet cards, setting
+ * the "manual" policy might fail.
+ *
+ * @param device_path to get property.
+ * @param policy where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_policy_set()
+ */
+bool
+e_connman_device_policy_get(const E_Connman_Element *device, const char **policy)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(policy, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_policy, NULL, policy);
+}
+
+/**
+ * Call method SetProperty("Policy", policy) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * Setting of the device power and connection policy.
+ * Possible values are "ignore", "off", "auto"
+ * and "manual".
+ *
+ * The policy defines on how the device is initialized
+ * when brought up and how it connects. The actual
+ * device power state can be changed independently to
+ * this value.
+ *
+ * If a device is switched off and the policy is changed
+ * to "auto" or "manual", the device will be switched
+ * on. For a current active device changing the policy
+ * to "off" results in powering down the device.
+ *
+ * The "ignore" policy can be set for devices that are
+ * detected, but managed by a different entity on the
+ * system. For example for complex network setups.
+ *
+ * Devices that can connect to various networks, the
+ * difference between "auto" or "manual" defines if
+ * known networks are connected automatically or not.
+ * For simple devices like Ethernet cards, setting
+ * the "manual" policy might fail.
+ *
+ * @param device_path to set property.
+ * @param policy value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_policy_get()
+ */
+bool
+e_connman_device_policy_set(E_Connman_Element *device, const char *policy, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(policy, 0);
+   return e_connman_element_property_set_full
+     (device, e_connman_prop_policy, DBUS_TYPE_STRING, policy, cb, data);
+}
+
+/**
+ * Get property "Priority" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The device priority. Higher values indicate the
+ * preference for this device.
+ *
+ * @param device_path to get property.
+ * @param priority where to store the property value, must be a pointer
+ *        to byte (unsigned char *).
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_priority_set()
+ */
+bool
+e_connman_device_priority_get(const E_Connman_Element *device, unsigned char *priority)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(priority, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_priority, NULL, priority);
+}
+
+/**
+ * Call method SetProperty("Priority", priority) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * The device priority. Higher values indicate the
+ * preference for this device.
+ *
+ * @param device_path to set property.
+ * @param priority value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_priority_get()
+ */
+bool
+e_connman_device_priority_set(E_Connman_Element *device, unsigned char priority, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   return e_connman_element_property_set_full
+     (device, e_connman_prop_priority, DBUS_TYPE_BYTE, &priority, cb, data);
+}
+
+/**
+ * Get property "Powered" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Switch a device on or off. This will also modify
+ * the list of networks in range. All known networks
+ * will be still available via the Networks property.
+ *
+ * Changing this value doesn't change the value of the
+ * Policy property.
+ *
+ * The value of this property can be changed by other
+ * parts of the system (including the kernel). An
+ * example would be modifications via the "ifconfig"
+ * command line utility.
+ *
+ * @param device_path to get property.
+ * @param powered where to store the property value, must be a pointer
+ *        to boolean (bool *).
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_powered_set()
+ */
+bool
+e_connman_device_powered_get(const E_Connman_Element *device, bool *powered)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(powered, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_powered, NULL, powered);
+}
+
+/**
+ * Call method SetProperty("Powered", powered) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * Switch a device on or off. This will also modify
+ * the list of networks in range. All known networks
+ * will be still available via the Networks property.
+ *
+ * Changing this value doesn't change the value of the
+ * Policy property.
+ *
+ * The value of this property can be changed by other
+ * parts of the system (including the kernel). An
+ * example would be modifications via the "ifconfig"
+ * command line utility.
+ *
+ * @param device_path to set property.
+ * @param powered value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_powered_get()
+ */
+bool
+e_connman_device_powered_set(E_Connman_Element *device, bool powered, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   return e_connman_element_property_set_full
+     (device, e_connman_prop_powered, DBUS_TYPE_BOOLEAN, &powered, cb, data);
+}
+
+/**
+ * Get property "ScanInterval" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The scan interval describes the time in seconds
+ * between automated scan attempts. Setting this
+ * value to 0 will disable the background scanning.
+ *
+ * The default value is 300 and so every 5 minutes
+ * a scan procedure will be triggered.
+ *
+ * This property is not available with all types
+ * of devices. Some might not support background
+ * scanning at all.
+ *
+ * @param device_path to get property.
+ * @param scan_interval where to store the property value, must be a pointer
+ *        to uint16 (unsigned short *).
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_scan_interval_set()
+ */
+bool
+e_connman_device_scan_interval_get(const E_Connman_Element *device, unsigned short *scan_interval)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(scan_interval, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_scan_interval, NULL, scan_interval);
+}
+
+/**
+ * Call method SetProperty("ScanInterval", scan_interval) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * The scan interval describes the time in seconds
+ * between automated scan attempts. Setting this
+ * value to 0 will disable the background scanning.
+ *
+ * The default value is 300 and so every 5 minutes
+ * a scan procedure will be triggered.
+ *
+ * This property is not available with all types
+ * of devices. Some might not support background
+ * scanning at all.
+ *
+ * @param device_path to set property.
+ * @param scan_interval value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_device_scan_interval_get()
+ */
+bool
+e_connman_device_scan_interval_set(E_Connman_Element *device, unsigned short scan_interval, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   return e_connman_element_property_set_full
+     (device, e_connman_prop_scan_interval, DBUS_TYPE_UINT16,
+      &scan_interval, cb, data);
+}
+
+/**
+ * Get property "Scanning" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates if a device is scanning. Not all device
+ * types might support this. Also some hardware might
+ * execute background scanning without notifying the
+ * driver about it. Use this property only for visual
+ * indication.
+ *
+ * @param device_path to get property.
+ * @param scanning where to store the property value, must be a pointer
+ *        to boolean (bool *).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_scanning_get(const E_Connman_Element *device, bool *scanning)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(scanning, 0);
+   return e_connman_element_property_get_stringshared
+     (device, e_connman_prop_scanning, NULL, scanning);
+}
+
+/**
+ * Get array of network elements.
+ *
+ * @param device_path to get property.
+ * @param count return the number of elements in array.
+ * @param elements where to store elements array, just changed if return is 1.
+ *        Elements are not referenced and in no particular order.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_device_networks_get(const E_Connman_Element *device, unsigned int *count, E_Connman_Element ***elements)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(device, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(elements, 0);
+   return e_connman_element_objects_array_get_stringshared
+     (device, e_connman_prop_networks, count, elements);
+}
diff --git a/src/lib/connman/e_connman_element.c b/src/lib/connman/e_connman_element.c
new file mode 100644 (file)
index 0000000..6c92833
--- /dev/null
@@ -0,0 +1,1689 @@
+#include "e_connman_private.h"
+#include <string.h>
+#include <errno.h>
+
+static Eina_Hash *elements = NULL;
+
+typedef struct _E_Connman_Array E_Connman_Array;
+typedef struct _E_Connman_Element_Pending E_Connman_Element_Pending;
+typedef struct _E_Connman_Element_Call_Data E_Connman_Element_Call_Data;
+typedef struct _E_Connman_Element_Property E_Connman_Element_Property;
+typedef struct _E_Connman_Element_Listener E_Connman_Element_Listener;
+
+struct _E_Connman_Array
+{
+   int type;
+   Eina_Array *array;
+};
+
+struct _E_Connman_Element_Pending
+{
+   EINA_INLIST;
+   DBusPendingCall *pending;
+   void *data;
+   E_DBus_Method_Return_Cb user_cb;
+   void *user_data;
+};
+
+struct _E_Connman_Element_Call_Data
+{
+   E_Connman_Element *element;
+   E_DBus_Method_Return_Cb cb;
+   E_Connman_Element_Pending *pending;
+   Eina_Inlist **p_list;
+};
+
+struct _E_Connman_Element_Property
+{
+   EINA_INLIST;
+   const char *name;
+   int type;
+   union {
+      bool boolean;
+      const char *str;
+      unsigned short u16;
+      unsigned int u32;
+      unsigned char byte;
+      const char *path;
+      void *variant;
+      E_Connman_Array *array;
+   } value;
+};
+
+struct _E_Connman_Element_Listener
+{
+   EINA_INLIST;
+   void (*cb)(void *data, const E_Connman_Element *element);
+   void *data;
+   void (*free_data)(void *data);
+};
+
+
+static void
+_e_connman_element_event_no_free(void *data, void *ev)
+{
+   E_Connman_Element *element = ev;
+   e_connman_element_unref(element);
+}
+
+static void
+e_connman_element_event_add(int event_type, E_Connman_Element *element)
+{
+   e_connman_element_ref(element);
+   ecore_event_add
+     (event_type, element, _e_connman_element_event_no_free, element);
+}
+
+static void
+e_connman_element_call_dispatch_and_free(void *d, DBusMessage *msg, DBusError *err)
+{
+   E_Connman_Element_Call_Data *data = d;
+   E_Connman_Element_Pending *pending;
+
+   pending = data->pending;
+   pending->pending = NULL;
+
+   if (data->cb)
+     data->cb(data->element, msg, err);
+
+   if (pending->user_cb)
+     pending->user_cb(pending->user_data, msg, err);
+
+   pending->data = NULL;
+   *data->p_list = eina_inlist_remove(*data->p_list, EINA_INLIST_GET(pending));
+   free(pending);
+   free(data);
+}
+
+static void
+e_connman_element_pending_cancel_and_free(Eina_Inlist **pending)
+{
+   while (*pending)
+     {
+       E_Connman_Element_Pending *p = (E_Connman_Element_Pending *)*pending;
+       DBusError err;
+
+       dbus_pending_call_cancel(p->pending);
+
+       dbus_error_init(&err);
+       dbus_set_error(&err, "Canceled", "Pending method call was canceled.");
+       e_connman_element_call_dispatch_and_free(p->data, NULL, &err);
+       dbus_error_free(&err);
+     }
+}
+
+void
+e_connman_element_listener_add(E_Connman_Element *element, void (*cb)(void *data, const E_Connman_Element *element), const void *data, void (*free_data)(void *data))
+{
+   E_Connman_Element_Listener *l;
+
+   if (!element)
+     {
+       ERR("safety check failed: element == NULL\n");
+       goto error;
+     }
+   if (!cb)
+     {
+       ERR("safety check failed: cb == NULL\n");
+       goto error;
+     }
+
+   l = malloc(sizeof(*l));
+   if (!l)
+     {
+       ERR("could not allocate E_Connman_Element_Listener\n");
+       goto error;
+     }
+
+   l->cb = cb;
+   l->data = (void *)data;
+   l->free_data = free_data;
+
+   element->_listeners = eina_inlist_append
+     (element->_listeners, EINA_INLIST_GET(l));
+
+   return;
+
+ error:
+   if (free_data)
+     free_data((void *)data);
+}
+
+void
+e_connman_element_listener_del(E_Connman_Element *element, void (*cb)(void *data, const E_Connman_Element *element), const void *data)
+{
+   E_Connman_Element_Listener *l;
+
+   EINA_SAFETY_ON_NULL_RETURN(element);
+   EINA_SAFETY_ON_NULL_RETURN(cb);
+
+   EINA_INLIST_FOREACH(element->_listeners, l)
+     if ((l->cb == cb) && (l->data == data))
+       {
+         element->_listeners = eina_inlist_remove
+           (element->_listeners, EINA_INLIST_GET(l));
+         if (l->free_data) l->free_data(l->data);
+         free(l);
+         return;
+       }
+}
+
+static void
+_e_connman_element_listeners_call_do(E_Connman_Element *element)
+{
+   E_Connman_Element_Listener *l, **shadow;
+   unsigned int i, count;
+
+   /* NB: iterate on a copy in order to allow listeners to be deleted
+    * from callbacks.  number of listeners should be small, so the
+    * following should do fine.
+    */
+   count = eina_inlist_count(element->_listeners);
+   if (count < 1)
+     goto end;
+
+   shadow = alloca(sizeof(*shadow) * count);
+   if (!shadow)
+     goto end;
+
+   i = 0;
+   EINA_INLIST_FOREACH(element->_listeners, l)
+     shadow[i++] = l;
+
+   for (i = 0; i < count; i++)
+     shadow[i]->cb(shadow[i]->data, element);
+
+ end:
+   e_connman_element_event_add(E_CONNMAN_EVENT_ELEMENT_UPDATED, element);
+}
+
+static int
+_e_connman_element_listeners_call_idler(void *data)
+{
+   E_Connman_Element *element = data;
+   _e_connman_element_listeners_call_do(element);
+   element->_idler.changed = NULL;
+   return 0;
+}
+
+static void
+_e_connman_element_listeners_call(E_Connman_Element *element)
+{
+   if (element->_idler.changed)
+     return;
+   element->_idler.changed = ecore_idler_add
+     (_e_connman_element_listeners_call_idler, element);
+}
+
+/***********************************************************************
+ * Property
+ ***********************************************************************/
+
+static void
+_e_connman_element_array_free(E_Connman_Array *array, E_Connman_Array *new)
+{
+   Eina_Array_Iterator iterator;
+   unsigned int i;
+   void *item;
+
+   if (!array)
+     return;
+
+   switch (array->type)
+     {
+      case DBUS_TYPE_OBJECT_PATH:
+        EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+          eina_stringshare_del(item);
+        break;
+      case DBUS_TYPE_STRING:
+        EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+          eina_stringshare_del(item);
+        break;
+      default:
+        break;
+     }
+   eina_array_free(array->array);
+   free(array);
+}
+
+static void
+_e_connman_element_property_value_free(E_Connman_Element_Property *property)
+{
+   switch (property->type)
+     {
+      case 0:
+        return;
+      case DBUS_TYPE_BOOLEAN:
+      case DBUS_TYPE_BYTE:
+      case DBUS_TYPE_UINT16:
+      case DBUS_TYPE_UINT32:
+        break;
+      case DBUS_TYPE_STRING:
+        eina_stringshare_del(property->value.str);
+        break;
+      case DBUS_TYPE_OBJECT_PATH:
+        eina_stringshare_del(property->value.path);
+        break;
+      case DBUS_TYPE_ARRAY:
+        _e_connman_element_array_free(property->value.array, NULL);
+        break;
+      default:
+        ERR("don't know how to free value of property type %c (%d)\n",
+            property->type, property->type);
+     }
+}
+
+static const char *
+_e_connman_element_get_interface(const char *key)
+{
+   const char *interface = NULL, *tail;
+   char head;
+
+   head = key[0];
+   tail = key + 1;
+
+   switch (head)
+     {
+      case 'P':
+        if (strcmp(tail, "rofiles") == 0)
+          interface = e_connman_iface_profile;
+        break;
+      case 'D':
+        if (strcmp(tail, "evices") == 0)
+          interface = e_connman_iface_device;
+        break;
+      case 'N':
+        if (strcmp(tail, "etworks") == 0)
+          interface = e_connman_iface_network;
+        break;
+      case 'C':
+        if (strcmp(tail, "onnections") == 0)
+          interface = e_connman_iface_connection;
+        break;
+      default:
+        break;
+     }
+
+   if (!interface)
+     ERR("connman reported unknown interface: %s\n", key);
+
+   return interface;
+}
+
+static void
+_e_connman_element_item_register(const char *key, const char *item)
+{
+   E_Connman_Element *element;
+   const char *interface;
+
+   interface = _e_connman_element_get_interface(key);
+   if (!interface)
+     return;
+   element = e_connman_element_register(item, interface);
+   if ((element) && (!e_connman_element_properties_sync(element)))
+     WRN("could not get properties of %s\n", element->path);
+}
+
+static void
+_e_connman_element_objects_array_register(E_Connman_Array *array, const char *name)
+{
+   Eina_Array_Iterator iterator;
+   unsigned int i;
+   void *item;
+
+   if (array->type != DBUS_TYPE_OBJECT_PATH)
+     return;
+   EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+     _e_connman_element_item_register(name, item);
+}
+
+static bool
+_e_connman_element_property_update(E_Connman_Element_Property *property, int type, void *data)
+{
+   int changed = 0;
+
+   if ((type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) && data)
+     data = (char *)eina_stringshare_add(data);
+
+   if (property->type != type)
+     {
+       if (property->type)
+         DBG("property type changed from '%c' to '%c'\n",
+             property->type, type);
+       _e_connman_element_property_value_free(property);
+       memset(&property->value, 0, sizeof(property->value));
+       property->type = type;
+       changed = 1;
+     }
+
+   switch (type)
+     {
+      case DBUS_TYPE_BOOLEAN:
+        if (changed || property->value.boolean != (bool)(long)data)
+          {
+             property->value.boolean = (bool)(long)data;
+             changed = 1;
+          }
+        break;
+      case DBUS_TYPE_BYTE:
+        if (changed || property->value.byte != (unsigned char)(long)data)
+          {
+             property->value.byte = (unsigned char)(long)data;
+             changed = 1;
+          }
+      case DBUS_TYPE_UINT16:
+        if (changed || property->value.u16 != (unsigned short)(long)data)
+          {
+             property->value.u16 = (unsigned short)(long)data;
+             changed = 1;
+          }
+        break;
+      case DBUS_TYPE_UINT32:
+        if (changed || property->value.u32 != (unsigned int)(long)data)
+          {
+             property->value.u32 = (unsigned int)(long)data;
+             changed = 1;
+          }
+        break;
+      case DBUS_TYPE_STRING:
+        if (changed)
+          property->value.str = data;
+        else
+          {
+             if (property->value.str)
+               eina_stringshare_del(property->value.str);
+             if (property->value.str != data)
+               {
+                  property->value.str = data;
+                  changed = 1;
+               }
+          }
+        break;
+      case DBUS_TYPE_OBJECT_PATH:
+        if (changed)
+          property->value.path = data;
+        else
+          {
+             if (property->value.path)
+               eina_stringshare_del(property->value.path);
+             if (property->value.path != data)
+               {
+                  property->value.path = data;
+                  changed = 1;
+               }
+          }
+        break;
+      case DBUS_TYPE_ARRAY:
+        if (!changed)
+          if (property->value.array)
+            {
+               _e_connman_element_array_free(property->value.array, data);
+               _e_connman_element_objects_array_register(data, property->name);
+            }
+        property->value.array = data;
+        changed = 1;
+        break;
+      default:
+        ERR("don't know how to update property type %c (%d)\n", type, type);
+     }
+
+   return changed;
+}
+
+static E_Connman_Element_Property *
+_e_connman_element_property_new(const char *name, int type, void *data)
+{
+   E_Connman_Element_Property *property;
+
+   property = calloc(1, sizeof(*property));
+   if (!property)
+     {
+       eina_stringshare_del(name);
+       ERR("could not allocate property: %s\n", strerror(errno));
+       return NULL;
+     }
+
+   property->name = name;
+   _e_connman_element_property_update(property, type, data);
+   return property;
+}
+
+static void
+_e_connman_element_property_free(E_Connman_Element_Property *property)
+{
+   _e_connman_element_property_value_free(property);
+   eina_stringshare_del(property->name);
+   free(property);
+}
+
+/***********************************************************************
+ * Element
+ ***********************************************************************/
+unsigned char *
+e_connman_element_bytes_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count)
+{
+   Eina_Array_Iterator iterator;
+   E_Connman_Array *array;
+   unsigned char *ret, *p;
+   unsigned int i;
+   void *item;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, NULL);
+
+   *count = 0;
+
+   if (!e_connman_element_property_get_stringshared
+       (element, property, NULL, &array))
+     return NULL;
+
+   if ((!array) || (!(array->array)))
+     return NULL;
+
+   *count = eina_array_count_get(array->array);
+   ret = malloc(*count * sizeof(unsigned char));
+   if (!ret)
+     {
+       ERR("could not allocate return array of %d bytes: %s\n",
+           *count, strerror(errno));
+       return NULL;
+     }
+   p = ret;
+
+   EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+     {
+       *p = (unsigned char)(long)item;
+       p++;
+     }
+   return ret;
+}
+
+bool
+e_connman_element_objects_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count, E_Connman_Element ***elements)
+{
+   E_Connman_Element **ret, **p;
+   Eina_Array_Iterator iterator;
+   E_Connman_Array *array;
+   unsigned int i;
+   int type;
+   void *item;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(property, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(elements, 0);
+
+   *count = 0;
+   *elements = NULL;
+
+   if (!e_connman_element_property_get_stringshared
+       (element, property, &type, &array))
+     return 0;
+
+   if (type != DBUS_TYPE_ARRAY)
+     {
+       ERR("property %s is not an array!\n", property);
+       return 0;
+     }
+
+   if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
+     return 0;
+
+   if (array->type != DBUS_TYPE_OBJECT_PATH)
+     {
+       ERR("property %s is not an array of object paths!\n", property);
+       return 0;
+     }
+
+   *count = eina_array_count_get(array->array);
+   ret = malloc(*count * sizeof(E_Connman_Element *));
+   if (!ret)
+     {
+       ERR("could not allocate return array of %d elements: %s\n",
+           *count, strerror(errno));
+       *count = 0;
+       return 0;
+     }
+   p = ret;
+
+   EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+     {
+       E_Connman_Element *e = e_connman_element_get(item);
+       if (!e)
+         continue;
+       *p = e;
+       p++;
+     }
+   *count = p - ret;
+   *elements = ret;
+   return 1;
+}
+
+void
+_e_connman_element_array_print(FILE *fp, E_Connman_Array *array)
+{
+   Eina_Array_Iterator iterator;
+   unsigned int i;
+   void *item;
+
+   if (!array)
+     return;
+
+   switch (array->type)
+     {
+      case DBUS_TYPE_OBJECT_PATH:
+        EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+          fprintf(fp, "\"%s\", ", (const char *)item);
+        break;
+      case DBUS_TYPE_BYTE:
+        EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
+          fprintf(fp, "%#02hhx (\"%c\"), ", (unsigned char)(long)item,
+                  (unsigned char)(long)item);
+        break;
+      case DBUS_TYPE_INVALID:
+        break;
+      default:
+        fprintf(fp, "<UNKNOWN ARRAY TYPE '%c'>", array->type);
+     }
+}
+
+/**
+ * Print element to file descriptor.
+ */
+void
+e_connman_element_print(FILE *fp, const E_Connman_Element *element)
+{
+   const E_Connman_Element_Property *p;
+
+   EINA_SAFETY_ON_NULL_RETURN(fp);
+   if (!element)
+     {
+       fputs("ERROR: no element to print\n", fp);
+       return;
+     }
+
+   fprintf(fp,
+          "Element %p: %s [%s]\n"
+          "\tProperties:\n",
+          element, element->path, element->interface);
+
+   EINA_INLIST_FOREACH(element->props, p)
+     {
+       fprintf(fp, "\t\t%s (%c) = ", p->name, p->type);
+
+       switch (p->type)
+         {
+          case DBUS_TYPE_STRING:
+             fprintf(fp, "\"%s\"", p->value.str);
+             break;
+          case DBUS_TYPE_OBJECT_PATH:
+             fprintf(fp, "\"%s\"", p->value.path);
+             break;
+          case DBUS_TYPE_BOOLEAN:
+             fprintf(fp, "%hhu", p->value.boolean);
+             break;
+          case DBUS_TYPE_BYTE:
+             fprintf(fp, "%#02hhx (%d), ", p->value.byte, p->value.byte);
+             break;
+          case DBUS_TYPE_UINT16:
+             fprintf(fp, "%hu", p->value.u16);
+             break;
+          case DBUS_TYPE_UINT32:
+             fprintf(fp, "%u", p->value.u32);
+             break;
+          case DBUS_TYPE_ARRAY:
+             _e_connman_element_array_print(fp, p->value.array);
+             break;
+          default:
+             fputs("don't know how to print type", fp);
+         }
+
+       fputc('\n', fp);
+     }
+}
+
+static E_Connman_Element *
+e_connman_element_new(const char *path, const char *interface)
+{
+   E_Connman_Element *element;
+
+   element = calloc(1, sizeof(*element));
+   if (!element)
+     {
+       ERR("could not allocate element: %s\n", strerror(errno));
+       return NULL;
+     }
+
+   element->path = eina_stringshare_add(path);
+   element->interface = eina_stringshare_ref(interface);
+   element->_references = 1;
+
+   return element;
+}
+
+static inline int
+_stringshare_replace(const char **str, const char *new)
+{
+   new = eina_stringshare_add(new);
+   eina_stringshare_del(*str);
+   if (*str == new)
+     return 0;
+   *str = new;
+   return 1;
+}
+
+static void
+e_connman_element_extra_properties_free(E_Connman_Element *element)
+{
+   while (element->props)
+     {
+       E_Connman_Element_Property *prop;
+       prop = (E_Connman_Element_Property *)element->props;
+       element->props = element->props->next;
+       _e_connman_element_property_free(prop);
+     }
+}
+
+static void
+e_connman_element_free(E_Connman_Element *element)
+{
+   if (element->_idler.changed)
+     ecore_idler_del(element->_idler.changed);
+
+   while (element->_listeners)
+     {
+       E_Connman_Element_Listener *l = (void *)element->_listeners;
+       element->_listeners = eina_inlist_remove
+         (element->_listeners, element->_listeners);
+
+       if (l->free_data) l->free_data(l->data);
+       free(l);
+     }
+
+   e_connman_element_pending_cancel_and_free(&element->_pending.properties_get);
+   e_connman_element_pending_cancel_and_free(&element->_pending.property_set);
+   e_connman_element_pending_cancel_and_free(&element->_pending.network_create);
+   e_connman_element_pending_cancel_and_free(&element->_pending.network_remove);
+   e_connman_element_pending_cancel_and_free(&element->_pending.network_connect);
+   e_connman_element_pending_cancel_and_free(&element->_pending.network_disconnect);
+   e_connman_element_pending_cancel_and_free(&element->_pending.agent_register);
+   e_connman_element_pending_cancel_and_free(&element->_pending.agent_unregister);
+   e_connman_element_pending_cancel_and_free(&element->_pending.device_propose_scan);
+
+   e_connman_element_extra_properties_free(element);
+   eina_stringshare_del(element->interface);
+   eina_stringshare_del(element->path);
+   free(element);
+}
+
+/**
+ * Add reference to element.
+ */
+int
+e_connman_element_ref(E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return ++element->_references;
+}
+
+/**
+ * Remove reference from element.
+ *
+ * If reference count drops to 0 element will be freed.
+ */
+int
+e_connman_element_unref(E_Connman_Element *element)
+{
+   int i;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+
+   i = --element->_references;
+   if (i == 0)
+     e_connman_element_free(element);
+   else if (i < 0)
+     ERR("element %p references %d < 0\n", element, i);
+   return i;
+}
+
+/**
+ * Send message with callbacks set to work with connman elements.
+ *
+ * If this call fails (returns 0), pending callbacks will not be called,
+ * not even with error messages.
+ *
+ * @return 1 on success, 0 on failure.
+ */
+bool
+e_connman_element_message_send(E_Connman_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, DBusMessage *msg, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
+{
+   E_Connman_Element_Call_Data *data;
+   E_Connman_Element_Pending *p;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pending, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0);
+
+   data = malloc(sizeof(*data));
+   if (!data)
+     {
+       ERR("could not alloc e_connman_element_call_data: %s\n",
+           strerror(errno));
+       dbus_message_unref(msg);
+       return 0;
+     }
+
+   p = malloc(sizeof(*p));
+   if (!p)
+     {
+       ERR("could not alloc E_Connman_Element_Pending: %s\n",
+           strerror(errno));
+       free(data);
+       dbus_message_unref(msg);
+       return 0;
+     }
+
+   data->element = element;
+   data->cb = cb;
+   data->pending = p;
+   data->p_list = pending;
+   p->user_cb = user_cb;
+   p->user_data = (void *)user_data;
+   p->data = data;
+   p->pending = e_dbus_message_send
+     (e_connman_conn, msg, e_connman_element_call_dispatch_and_free, -1, data);
+   dbus_message_unref(msg);
+
+   if (p->pending)
+     {
+       *pending = eina_inlist_append(*pending, EINA_INLIST_GET(p));
+       return 1;
+     }
+   else
+     {
+       ERR("failed to call %s (obj=%s, path=%s, iface=%s)\n",
+           method_name, e_connman_system_bus_name_get(),
+           element->path, element->interface);
+       free(data);
+       free(p);
+       return 0;
+     }
+}
+
+bool
+e_connman_element_call_full(E_Connman_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
+{
+   DBusMessage *msg;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pending, 0);
+
+   msg = dbus_message_new_method_call
+     (e_connman_system_bus_name_get(), element->path, element->interface,
+      method_name);
+
+   return e_connman_element_message_send
+     (element, method_name, cb, msg, pending, user_cb, user_data);
+}
+
+static bool
+_e_connman_element_property_value_add(E_Connman_Element *element, const char *name, int type, void *value)
+{
+   E_Connman_Element_Property *p;
+
+   name = eina_stringshare_add(name);
+   EINA_INLIST_FOREACH(element->props, p)
+     {
+       if (p->name == name)
+         {
+            eina_stringshare_del(name);
+            return _e_connman_element_property_update(p, type, value);
+         }
+     }
+
+   p = _e_connman_element_property_new(name, type, value);
+   if (!p)
+     {
+       ERR("could not create property %s (%c)\n", name, type);
+       return 0;
+     }
+
+   element->props = eina_inlist_append(element->props, EINA_INLIST_GET(p));
+   return 1;
+}
+
+static E_Connman_Array *
+_e_connman_element_iter_get_array(DBusMessageIter *itr, const char *key)
+{
+   E_Connman_Array *array;
+   DBusMessageIter e_itr;
+
+   array = malloc(sizeof(E_Connman_Array));
+   if (!array)
+     {
+       ERR("could not create new e_connman array.\n");
+       return NULL;
+     }
+   array->array = eina_array_new(16);
+   if (!(array->array))
+     {
+       ERR("could not create new eina array.\n");
+       free(array);
+       return NULL;
+     }
+
+   dbus_message_iter_recurse(itr, &e_itr);
+   array->type = dbus_message_iter_get_arg_type(&e_itr);
+   do
+     {
+       switch (array->type)
+         {
+          case DBUS_TYPE_INVALID:
+             break;
+          case DBUS_TYPE_OBJECT_PATH:
+            {
+               const char *path;
+
+               dbus_message_iter_get_basic(&e_itr, &path);
+               path = eina_stringshare_add(path);
+               eina_array_push(array->array, path);
+               _e_connman_element_item_register(key, path);
+            }
+            break;
+          case DBUS_TYPE_BYTE:
+            {
+               unsigned char byte;
+               dbus_message_iter_get_basic(&e_itr, &byte);
+               eina_array_push(array->array, (void *)(long)byte);
+            }
+            break;
+          default:
+             ERR("don't know how to get property type %c (%d)\n",
+                 array->type, array->type);
+         }
+     }
+   while (dbus_message_iter_next(&e_itr));
+   return array;
+}
+
+static void
+_e_connman_element_get_properties_callback(void *user_data, DBusMessage *msg, DBusError *err)
+{
+   E_Connman_Element *element = user_data;
+   DBusMessageIter itr, s_itr;
+   int t, changed;
+
+   DBG("get_properties msg=%p\n", msg);
+
+   if (!_dbus_callback_check_and_init(msg, &itr, err))
+     return;
+
+   t = dbus_message_iter_get_arg_type(&itr);
+   if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
+     return;
+
+   changed = 0;
+   dbus_message_iter_recurse(&itr, &s_itr);
+   do
+     {
+       DBusMessageIter e_itr, v_itr;
+       const char *key;
+       void *value;
+       int r;
+
+       t = dbus_message_iter_get_arg_type(&s_itr);
+       if (!_dbus_iter_type_check(t, DBUS_TYPE_DICT_ENTRY))
+         continue;
+
+       dbus_message_iter_recurse(&s_itr, &e_itr);
+
+       t = dbus_message_iter_get_arg_type(&e_itr);
+       if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
+         continue;
+
+       dbus_message_iter_get_basic(&e_itr, &key);
+       dbus_message_iter_next(&e_itr);
+       t = dbus_message_iter_get_arg_type(&e_itr);
+       if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
+         continue;
+
+       dbus_message_iter_recurse(&e_itr, &v_itr);
+       t = dbus_message_iter_get_arg_type(&v_itr);
+       if (t == DBUS_TYPE_ARRAY)
+         value = _e_connman_element_iter_get_array(&v_itr, key);
+       else if (t != DBUS_TYPE_INVALID)
+         dbus_message_iter_get_basic(&v_itr, &value);
+       r = _e_connman_element_property_value_add(element, key, t, value);
+       if (r < 0)
+         ERR("failed to add property value %s (%c)\n", key, t);
+       else if (r == 1)
+         {
+            INF("property value changed %s (%c)\n", key, t);
+            changed = 1;
+         }
+     }
+   while (dbus_message_iter_next(&s_itr));
+
+   if (changed)
+     _e_connman_element_listeners_call(element);
+}
+
+/**
+ * Sync element properties with server.
+ *
+ * Call method GetProperties() at the given element on server in order to sync
+ * them.
+ *
+ * @param element to call method on server.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_sync_properties_full(E_Connman_Element *element, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "GetProperties";
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return e_connman_element_call_full
+     (element, name, _e_connman_element_get_properties_callback,
+      &element->_pending.properties_get, cb, data);
+}
+
+/**
+ * Sync element properties with server, simple version.
+ *
+ * Call method GetProperties() at the given element on server in order to sync
+ * them. This is the simple version and there is no check of server reply
+ * for errors.
+ *
+ * @param element to call method on server.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_properties_sync(E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return e_connman_element_sync_properties_full(element, NULL, NULL);
+}
+
+/**
+ * Call method SetProperty(prop, value) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * @param element to call method on server.
+ * @param prop property name.
+ * @param type DBus type to use for value.
+ * @param value pointer to value, just like regular DBus, see
+ *        dbus_message_iter_append_basic().
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_property_set_full(E_Connman_Element *element, const char *prop, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "SetProperty";
+   char typestr[2];
+   DBusMessage *msg;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(prop, 0);
+
+   msg = dbus_message_new_method_call
+     (e_connman_system_bus_name_get(), element->path, element->interface, name);
+
+   if (!msg)
+     return 0;
+
+   DBusMessageIter itr, v;
+   dbus_message_iter_init_append(msg, &itr);
+   dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
+
+   typestr[0] = type;
+   typestr[1] = '\0';
+   dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &v);
+   if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
+     dbus_message_iter_append_basic(&v, type, &value);
+   else
+     dbus_message_iter_append_basic(&v, type, value);
+   dbus_message_iter_close_container(&itr, &v);
+
+   return e_connman_element_message_send
+     (element, name, NULL, msg, &element->_pending.property_set, cb, data);
+}
+
+/**
+ * Call method SetProperty(prop, value) at the given element on server.
+ *
+ * This is the simple version and there is no check of server reply
+ * for errors.
+ *
+ * @param element to call method on server.
+ * @param prop property name.
+ * @param type DBus type to use for value.
+ * @param value pointer to value, just like regular DBus, see
+ *        dbus_message_iter_append_basic().
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_property_set(E_Connman_Element *element, const char *prop, int type, const void *value)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(prop, 0);
+   return e_connman_element_property_set_full
+     (element, prop, type, value, NULL, NULL);
+}
+
+bool
+e_connman_element_call_with_path(E_Connman_Element *element, const char *method_name, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
+{
+   DBusMessageIter itr;
+   DBusMessage *msg;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(string, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pending, 0);
+
+   msg = dbus_message_new_method_call
+     (e_connman_system_bus_name_get(), element->path, element->interface,
+      method_name);
+
+   if (!msg)
+     return 0;
+
+   dbus_message_iter_init_append(msg, &itr);
+   dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &string);
+
+   return e_connman_element_message_send
+     (element, method_name, cb, msg, pending, user_cb, user_data);
+}
+
+/**
+ * Get property type.
+ *
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * @param element which element to get the property
+ * @param name property name, must be previously stringshared
+ * @param type will contain the value type.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_property_type_get_stringshared(const E_Connman_Element *element, const char *name, int *type)
+{
+   const E_Connman_Element_Property *p;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(type, 0);
+
+   EINA_INLIST_FOREACH(element->props, p)
+     {
+       if (p->name == name)
+         {
+            *type = p->type;
+            return 1;
+         }
+     }
+
+   WRN("element %s (%p) has no property with name \"%s\".\n",
+       element->path, element, name);
+   return 0;
+}
+
+/**
+ * Get property type.
+ *
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * @param element which element to get the property
+ * @param name property name
+ * @param type will contain the value type.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_property_type_get(const E_Connman_Element *element, const char *name, int *type)
+{
+   bool ret;
+   name = eina_stringshare_add(name);
+   ret = e_connman_element_property_type_get_stringshared(element, name, type);
+   eina_stringshare_del(name);
+   return ret;
+}
+
+void
+e_connman_element_list_properties(const E_Connman_Element *element, bool (*cb)(void *data, const E_Connman_Element *element, const char *name, int type, const void *value), const void *data)
+{
+   const E_Connman_Element_Property *p;
+
+   EINA_SAFETY_ON_NULL_RETURN(element);
+   EINA_SAFETY_ON_NULL_RETURN(cb);
+
+   EINA_INLIST_FOREACH(element->props, p)
+     {
+       const void *value = NULL;
+
+       switch (p->type)
+         {
+          case DBUS_TYPE_STRING:
+             value = &p->value.str;
+             break;
+          case DBUS_TYPE_OBJECT_PATH:
+             value = &p->value.path;
+             break;
+          case DBUS_TYPE_BOOLEAN:
+             value = (void *)p->value.boolean;
+             break;
+          case DBUS_TYPE_UINT16:
+             value = &p->value.u16;
+             break;
+          case DBUS_TYPE_UINT32:
+             value = &p->value.u32;
+             break;
+          default:
+             ERR("unsupported type %c\n", p->type);
+         }
+
+       if (!cb((void *)data, element, p->name, p->type, value))
+         return;
+     }
+}
+
+/**
+ * Get property value given its name.
+ *
+ * This will look into properties, to find the property.
+ * If no property is found then 0 is returned.
+ *
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * @param element which element to get the property
+ * @param name property name, must be previously stringshared
+ * @param type if provided it will contain the value type.
+ * @param value where to store the property value, must be a pointer to the
+ *        exact type, (bool *) for booleans, (char **) for strings, and so on.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_property_get_stringshared(const E_Connman_Element *element, const char *name, int *type, void *value)
+{
+   const E_Connman_Element_Property *p;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(value, 0);
+
+   EINA_INLIST_FOREACH(element->props, p)
+     {
+       if (p->name != name)
+         continue;
+
+       if (type) *type = p->type;
+
+       switch (p->type)
+         {
+          case DBUS_TYPE_BOOLEAN:
+             *(bool *)value = p->value.boolean;
+             return 1;
+          case DBUS_TYPE_BYTE:
+             *(unsigned char *)value = p->value.byte;
+             return 1;
+          case DBUS_TYPE_UINT16:
+             *(unsigned short *)value = p->value.u16;
+             return 1;
+          case DBUS_TYPE_UINT32:
+             *(unsigned int *)value = p->value.u32;
+             return 1;
+          case DBUS_TYPE_STRING:
+             *(const char **)value = p->value.str;
+             return 1;
+          case DBUS_TYPE_OBJECT_PATH:
+             *(const char **)value = p->value.path;
+             return 1;
+          case DBUS_TYPE_ARRAY:
+             *(E_Connman_Array **)value = p->value.array;
+             return 1;
+          default:
+             ERR("don't know how to get property type %c (%d)\n",
+                 p->type, p->type);
+             return 0;
+         }
+     }
+
+   WRN("element %s (%p) has no property with name \"%s\".\n",
+       element->path, element, name);
+   return 0;
+}
+
+/**
+ * Get property value given its name.
+ *
+ * This will look into properties, to find the property.
+ * If no property is found then 0 is returned.
+ *
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * @param element which element to get the property
+ * @param name property name
+ * @param type if provided it will contain the value type.
+ * @param value where to store the property value, must be a pointer to the
+ *        exact type, (bool *) for booleans, (char **) for strings, and so on.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_element_property_get(const E_Connman_Element *element, const char *name, int *type, void *value)
+{
+   bool ret;
+   name = eina_stringshare_add(name);
+   ret = e_connman_element_property_get_stringshared
+     (element, name, type, value);
+   eina_stringshare_del(name);
+   return ret;
+}
+
+
+struct e_connman_elements_for_each_data
+{
+   Eina_Hash_Foreach cb;
+   void *data;
+};
+
+Eina_Bool
+_e_connman_elements_for_each(Eina_Hash *hash, const char *key, void *data, void *fdata)
+{
+   struct e_connman_elements_for_each_data *each_data = fdata;
+
+   each_data->cb(elements, key, data, each_data->data);
+   return 1;
+}
+
+/**
+ * Call the given function for each existing element.
+ *
+ * @param cb function to call for each element. It will get as parameters,
+ *        in order: the element pointer and the given @a user_data.
+ * @param user_data data to give to @a cb for each element.
+ */
+void
+e_connman_elements_for_each(Eina_Hash_Foreach cb, const void *user_data)
+{
+   struct e_connman_elements_for_each_data data = {cb, (void *)user_data};
+
+   EINA_SAFETY_ON_NULL_RETURN(cb);
+
+   eina_hash_foreach(elements, (Eina_Hash_Foreach) _e_connman_elements_for_each,
+                    &data);
+}
+
+static bool
+_e_connman_elements_get_allocate(unsigned int *count, E_Connman_Element ***p_elements)
+{
+   *count = eina_hash_population(elements);
+   if (*count == 0)
+     {
+       *p_elements = NULL;
+       return 1;
+     }
+
+   *p_elements = malloc(*count * sizeof(E_Connman_Element *));
+   if (!*p_elements)
+     {
+       ERR("could not allocate return array of %d elements: %s\n",
+           *count, strerror(errno));
+       *count = 0;
+       return 0;
+     }
+   return 1;
+}
+
+Eina_Bool
+_e_connman_elements_get_all(Eina_Hash *hash, const char *key, void *data, void *fdata)
+{
+   E_Connman_Element *element = data;
+   E_Connman_Element ***p_ret = fdata;
+
+   **p_ret = element;
+   (*p_ret)++;
+   return 1;
+}
+
+/**
+ * Get all known elements.
+ *
+ * No reference is added to these elements, since there are no threads
+ * in the system, you are free to add references yourself right after
+ * the return of this call without race condition, elements by the
+ * system (ie: elementRemoved signal)could only be touched on the next
+ * main loop iteration.
+ *
+ * @param count return the number of elements in array.
+ * @param p_elements array with all elements, these are not referenced
+ *        and in no particular order, just set if return is 1.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_elements_get_all(unsigned int *count, E_Connman_Element ***p_elements)
+{
+   E_Connman_Element **p;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, 0);
+
+   if (!_e_connman_elements_get_allocate(count, p_elements))
+     return 0;
+   p = *p_elements;
+   eina_hash_foreach(elements, (Eina_Hash_Foreach) _e_connman_elements_get_all,
+                    &p);
+   return 1;
+}
+
+struct e_connman_elements_get_all_str_data
+{
+   E_Connman_Element **elements;
+   int count;
+   const char *str;
+};
+
+Eina_Bool
+_e_connman_elements_get_all_type(Eina_Hash *hash, const char *key, void *e, void *user_data)
+{
+   struct e_connman_elements_get_all_str_data *data = user_data;
+   E_Connman_Element *element = e;
+
+   if ((data->str) && (element->interface != data->str))
+     return 1;
+
+   data->elements[data->count] = element;
+   data->count++;
+   return 1;
+}
+
+/**
+ * Get all known elements of type.
+ *
+ * No reference is added to these elements, since there are no threads
+ * in the system, you are free to add references yourself right after
+ * the return of this call without race condition, elements by the
+ * system (ie: ElementRemoved signal) could only be touched on the next
+ * main loop iteration.
+ *
+ * @param type type to filter, or NULL to get all.
+ * @param count return the number of elements in array.
+ * @param p_elements array with all elements, these are not referenced
+ *        and in no particular order, just set if return is 1.
+ *
+ * @return 1 on success, 0 otherwise.
+ *
+ * @see e_connman_elements_get_all()
+ */
+bool
+e_connman_elements_get_all_type(const char *type, unsigned int *count, E_Connman_Element ***p_elements)
+{
+   struct e_connman_elements_get_all_str_data data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, 0);
+
+   if (!_e_connman_elements_get_allocate(count, p_elements))
+     return 0;
+
+   data.elements = *p_elements;
+   data.count = 0;
+   data.str = eina_stringshare_add(type);
+   eina_hash_foreach(elements,
+                    (Eina_Hash_Foreach) _e_connman_elements_get_all_type,
+                    &data);
+
+   eina_stringshare_del(data.str);
+   *count = data.count;
+   return 1;
+}
+
+/**
+ * Get the element registered at given path.
+ *
+ * @param path the path to query for registered object.
+ *
+ * @return element pointer if found, NULL otherwise. No references are added.
+ */
+E_Connman_Element *
+e_connman_element_get(const char *path)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
+   element = eina_hash_find(elements, path);
+
+   return element;
+}
+
+static void
+_e_connman_element_property_changed_callback(void *data, DBusMessage *msg)
+{
+   E_Connman_Element *element = (E_Connman_Element *)data;
+   DBusMessageIter itr, v_itr;
+   int t, r, changed = 0;
+   const char *name;
+   void *value;
+
+   DBG("Property changed in element %s\n", element->path);
+
+   if (!_dbus_callback_check_and_init(msg, &itr, NULL))
+     return;
+
+   t = dbus_message_iter_get_arg_type(&itr);
+   if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
+     ERR("missing name in property changed signal\n");
+   dbus_message_iter_get_basic(&itr, &name);
+
+   dbus_message_iter_next(&itr);
+   t = dbus_message_iter_get_arg_type(&itr);
+   if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
+     ERR("missing value in property changed signal\n");
+   dbus_message_iter_recurse(&itr, &v_itr);
+   t = dbus_message_iter_get_arg_type(&v_itr);
+
+   if (t == DBUS_TYPE_ARRAY)
+     value = _e_connman_element_iter_get_array(&v_itr, name);
+   else if (t != DBUS_TYPE_INVALID)
+     dbus_message_iter_get_basic(&v_itr, &value);
+   r = _e_connman_element_property_value_add(element, name, t, value);
+   if (r < 0)
+     ERR("failed to add property value %s (%c)\n", name, t);
+   else if (r == 1)
+     {
+       INF("property value changed %s (%c)\n", name, t);
+       changed = 1;
+     }
+   if (changed)
+     _e_connman_element_listeners_call(element);
+}
+
+/**
+ * Register the given path, possible creating and element and return it.
+ *
+ * This will check if path is already registered, in that case the
+ * exiting element is returned. If it was not registered yet, a new
+ * element is created, registered and returned.
+ *
+ * This call will not add extra references to the object.
+ *
+ * @param path the path to register the element
+ *
+ * @return the registered object, no references are added.
+ */
+E_Connman_Element *
+e_connman_element_register(const char *path, const char *interface)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
+
+   element = eina_hash_find(elements, path);
+   if (element)
+     return element;
+
+   element = e_connman_element_new(path, interface);
+   if (!element)
+     return NULL;
+
+   if (!eina_hash_add(elements, element->path, element))
+     {
+       ERR("could not add element %s to hash, delete it.\n", path);
+       e_connman_element_free(element);
+       return NULL;
+     }
+
+   element->signal_handler =
+     e_dbus_signal_handler_add
+     (e_connman_conn, e_connman_system_bus_name_get(),
+      element->path, element->interface, "PropertyChanged",
+      _e_connman_element_property_changed_callback, element);
+
+   e_connman_element_event_add(E_CONNMAN_EVENT_ELEMENT_ADD, element);
+
+   return element;
+}
+
+static void
+_e_connman_element_event_unregister_and_free(void *data, void *ev)
+{
+   E_Connman_Element *element = ev;
+   e_connman_element_unref(element);
+}
+
+static void
+_e_connman_element_unregister_internal(E_Connman_Element *element)
+{
+   if (element->signal_handler)
+     {
+       e_dbus_signal_handler_del(e_connman_conn, element->signal_handler);
+       element->signal_handler = NULL;
+     }
+
+   ecore_event_add(E_CONNMAN_EVENT_ELEMENT_DEL, element,
+                  _e_connman_element_event_unregister_and_free, NULL);
+}
+
+/**
+ * Forget about the given element.
+ *
+ * This will remove the element from the pool of known objects, then
+ * add an E_CONNMAN_EVENT_ELEMENT_DEL and after that will unreference it,
+ * possible freeing it.
+ *
+ * @param element element to forget about. Its reference will be removed.
+ */
+void
+e_connman_element_unregister(E_Connman_Element *element)
+{
+   if (!element)
+     return;
+
+   if (elements)
+     eina_hash_del_by_key(elements, element->path);
+
+   _e_connman_element_unregister_internal(element);
+}
+
+/**
+ * Remove all known elements.
+ *
+ * This will remove all known elements but will NOT add any
+ * E_CONNMAN_EVENT_ELEMENT_DEL to main loop.
+ *
+ * This is just useful to make sure next e_connman_manager_sync_elements()
+ * will not leave any stale elements. This is unlikely to happen, as
+ * E_Connman is supposed to catch all required events to avoid stale elements.
+ */
+void
+e_connman_manager_clear_elements(void)
+{
+   e_connman_elements_shutdown();
+   e_connman_elements_init();
+}
+
+/**
+ * Creates elements hash.
+ *
+ * This has no init counter since its already guarded by other code.
+ * @internal
+ */
+void
+e_connman_elements_init(void)
+{
+   EINA_SAFETY_ON_FALSE_RETURN(elements == NULL);
+   elements =
+     eina_hash_string_superfast_new(EINA_FREE_CB
+                                   (_e_connman_element_unregister_internal));
+}
+
+void
+e_connman_elements_shutdown(void)
+{
+   EINA_SAFETY_ON_FALSE_RETURN(elements != NULL);
+   eina_hash_free(elements);
+   elements = NULL;
+}
+
+static inline bool
+_e_connman_element_is(const E_Connman_Element *element, const char *interface)
+{
+   return element->interface == interface;
+}
+
+bool
+e_connman_element_is_manager(const E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return _e_connman_element_is(element, e_connman_iface_manager);
+}
+
+bool
+e_connman_element_is_device(const E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return _e_connman_element_is(element, e_connman_iface_device);
+}
+
+bool
+e_connman_element_is_profile(const E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return _e_connman_element_is(element, e_connman_iface_profile);
+}
+
+bool
+e_connman_element_is_connection(const E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return _e_connman_element_is(element, e_connman_iface_connection);
+}
+
+bool
+e_connman_element_is_network(const E_Connman_Element *element)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+   return _e_connman_element_is(element, e_connman_iface_network);
+}
diff --git a/src/lib/connman/e_connman_manager.c b/src/lib/connman/e_connman_manager.c
new file mode 100644 (file)
index 0000000..6da1b6d
--- /dev/null
@@ -0,0 +1,330 @@
+#include "e_connman_private.h"
+
+/**
+ * Get the element manager.
+ *
+ * @return element pointer if found, NULL otherwise.
+ */
+E_Connman_Element *
+e_connman_manager_get(void)
+{
+   return e_connman_element_get(manager_path);
+}
+
+/**
+ * Register new agent for handling user requests.
+ *
+ * Call method RegisterAgent(object) on server in order to
+ * register new agent for handling user requests.
+ *
+ * @param object_path object to be registered.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_register_agent(const char *object_path, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "RegisterAgent";
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(object_path, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+
+   return e_connman_element_call_with_path
+     (element, name, object_path, NULL,
+      &element->_pending.agent_register, cb, data);
+}
+
+/**
+ * Unregister an existing agent.
+ *
+ * Call method UnregisterAgent(object) on server in order to
+ * unregister an existing agent.
+ *
+ * @param object_path agent to be unregistered.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_unregister_agent(const char *object_path, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "UnregisterAgent";
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(object_path, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+
+   return e_connman_element_call_with_path
+     (element, name, object_path, NULL,
+      &element->_pending.agent_unregister, cb, data);
+}
+
+/**
+ * Get property "State" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The global connection state of a system. Possible
+ * values are "online" if at least one connection exists
+ * and "offline" if no device is connected.
+ *
+ * In certain situations the state might change to
+ * the value "connected". This can only be seen if
+ * previously no connection was present.
+ *
+ * @param state where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_state_get(const char **state)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(state, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_property_get_stringshared
+     (element, e_connman_prop_state, NULL, state);
+}
+
+/**
+ * Get property "Policy" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The global connection policy of a system. This
+ * allows to configure how connections are established
+ * and also when they are taken down again.
+ *
+ * Possible values are "single", "multiple" and "ask".
+ *
+ * For the single policy, the priority setting of the
+ * device defines which becomes the default connection
+ * when multiple are available.
+ *
+ * @param policy where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_manager_policy_set()
+ */
+bool
+e_connman_manager_policy_get(const char **policy)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(policy, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_property_get_stringshared
+     (element, e_connman_prop_policy, NULL, policy);
+}
+
+/**
+ * Call method SetProperty("Policy", policy) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * The global connection policy of a system. This
+ * allows to configure how connections are established
+ * and also when they are taken down again.
+ *
+ * Possible values are "single", "multiple" and "ask".
+ *
+ * For the single policy, the priority setting of the
+ * device defines which becomes the default connection
+ * when multiple are available.
+ *
+ * @param policy value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_manager_policy_get()
+ */
+bool
+e_connman_manager_policy_set(const char *policy, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(policy, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+
+   return e_connman_element_property_set_full
+     (element, e_connman_prop_policy, DBUS_TYPE_STRING, policy, cb, data);
+}
+
+/**
+ * Get property "OfflineMode" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The offline mode indicates the global setting for
+ * switching all radios on or off. Changing offline mode
+ * to true results in powering down all devices. When
+ * leaving offline mode the individual policy of each
+ * device decides to switch the radio back on or not.
+ *
+ * During offline mode, it is still possible to switch
+ * certain technologies manually back on. For example
+ * the limited usage of WiFi or Bluetooth devices might
+ * be allowed in some situations.
+ *
+ * @param offline where to store the property value, must be a pointer
+ *        to booleans (bool *).
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_manager_offline_mode_set()
+ */
+bool
+e_connman_manager_offline_mode_get(bool *offline)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(offline, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_property_get_stringshared
+     (element, e_connman_prop_offline_mode, NULL, offline);
+}
+
+/**
+ * Call method SetProperty("OfflineMode", offline) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * The offline mode indicates the global setting for
+ * switching all radios on or off. Changing offline mode
+ * to true results in powering down all devices. When
+ * leaving offline mode the individual policy of each
+ * device decides to switch the radio back on or not.
+ *
+ * During offline mode, it is still possible to switch
+ * certain technologies manually back on. For example
+ * the limited usage of WiFi or Bluetooth devices might
+ * be allowed in some situations.
+ *
+ * @param offline value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_manager_offline_mode_get()
+ */
+bool
+e_connman_manager_offline_mode_set(bool offline, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   E_Connman_Element *element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_property_set_full
+     (element, e_connman_prop_offline_mode, DBUS_TYPE_BOOLEAN,
+      &offline, cb, data);
+}
+
+/**
+ * Get array of profile elements.
+ *
+ * @param count return the number of elements in array.
+ * @param p_elements array with all elements, these are not referenced
+ *        and in no particular order, just set if return is 1.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_profiles_get(unsigned int *count, E_Connman_Element ***p_elements)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_objects_array_get_stringshared
+     (element, e_connman_prop_profiles, count, p_elements);
+}
+
+/**
+ * Get array of device elements.
+ *
+ * @param count return the number of elements in array.
+ * @param p_elements array with all elements, these are not referenced
+ *        and in no particular order, just set if return is 1.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_devices_get(unsigned int *count, E_Connman_Element ***p_elements)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_objects_array_get_stringshared
+     (element, e_connman_prop_devices, count, p_elements);
+}
+
+/**
+ * Get array of connection elements.
+ *
+ * @param count return the number of elements in array.
+ * @param p_elements array with all elements, these are not referenced
+ *        and in no particular order, just set if return is 1.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_manager_connections_get(unsigned int *count, E_Connman_Element ***p_elements)
+{
+   E_Connman_Element *element;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, 0);
+
+   element = e_connman_manager_get();
+   if (!element)
+     return 0;
+   return e_connman_element_objects_array_get_stringshared
+     (element, e_connman_prop_connections, count, p_elements);
+}
diff --git a/src/lib/connman/e_connman_network.c b/src/lib/connman/e_connman_network.c
new file mode 100644 (file)
index 0000000..b08eca7
--- /dev/null
@@ -0,0 +1,477 @@
+#include "e_connman_private.h"
+
+E_Connman_Element *
+e_connman_network_get(const char *path)
+{
+   E_Connman_Element *network;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
+
+   network = e_connman_element_get(path);
+   if (!network)
+     return NULL;
+
+   if (!e_connman_element_is_network(network))
+     {
+       WRN("path '%s' is not a network!\n", path);
+       return NULL;
+     }
+
+   return network;
+}
+
+/**
+ * Connect to network.
+ *
+ * Call method Connect() at the given network on server in order to
+ * connect to it.
+ *
+ * @param network_path to call method on server.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_connect(E_Connman_Element *network, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "Connect";
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   return e_connman_element_call_full
+     (network, name, NULL, &network->_pending.network_connect, cb, data);
+}
+
+/**
+ * Disconnect from network.
+ *
+ * Call method Disconnect() at the given network on server in order to
+ * disconnect from it.
+ *
+ * @param network_path to call method on server.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_disconnect(E_Connman_Element *network, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   const char name[] = "Disconnect";
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   return e_connman_element_call_full
+     (network, name, NULL, &network->_pending.network_disconnect, cb, data);
+}
+
+/**
+ * Get property "Name" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The pretty/long version of the network name. For
+ * example in case of WiFi this should be the UTF-8
+ * valid version of the SSID.
+ *
+ * @param network_path to get property.
+ * @param name where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_name_get(const E_Connman_Element *network, const char **name)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_name, NULL, name);
+}
+
+/**
+ * Get property "Available" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates that this network is in range and
+ * ready to be used.
+ *
+ * The scanning process can change this property.
+ *
+ * @param network_path to get property.
+ * @param available where to store the property value, must be a pointer
+ *        to boolean (bool **).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_available_get(const E_Connman_Element *network, bool *available)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(available, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_available, NULL, available);
+}
+
+/**
+ * Get property "Connected" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates that this network is currently connected.
+ *
+ * @param network_path to get property.
+ * @param connected where to store the property value, must be a pointer
+ *        to boolean (bool **).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_connected_get(const E_Connman_Element *network, bool *connected)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(connected, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_connected, NULL, connected);
+}
+
+/**
+ * Get property "Remember" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates that this network will be remembered.
+ *
+ * For manually created networks this is set by
+ * default.
+ *
+ * @param network_path to get property.
+ * @param remember where to store the property value, must be a pointer
+ *        to boolean (bool **).
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_remember_set()
+ */
+bool
+e_connman_network_remember_get(const E_Connman_Element *network, bool *remember)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(remember, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_remember, NULL, remember);
+}
+
+/**
+ * Call method SetProperty("Remember", remember) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * Indicates that this network will be remembered.
+ *
+ * For manually created networks this is set by
+ * default.
+ *
+ * @param network_path to set property.
+ * @param remember value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_remember_get()
+ */
+bool
+e_connman_network_remember_set(E_Connman_Element *network, bool remember, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   return e_connman_element_property_set_full
+     (network, e_connman_prop_remember, DBUS_TYPE_BOOLEAN, &remember, cb, data);
+}
+
+/**
+ * Get property "Strength" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * Indicates the signal strength of the network. This
+ * is a normalized value between 0 and 100.
+ *
+ * @param network_path to get property.
+ * @param strength where to store the property value, must be a pointer
+ *        to byte (unsigned char*).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_strength_get(const E_Connman_Element *network, unsigned char *strength)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(strength, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_strengh, NULL, strength);
+}
+
+/**
+ * Get the device element this network
+ * belongs to.
+ *
+ * @param network_path to get property.
+ * @param element where to store element, just changed if return is 1
+ *
+ * @return 1 on success, 0 otherwise
+ */
+bool
+e_connman_network_device_get(const E_Connman_Element *network, E_Connman_Element **element)
+{
+   char *device_path;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
+
+   if (!e_connman_element_property_get_stringshared
+       (network, e_connman_prop_device, NULL, &device_path))
+     return 0;
+   *element = e_connman_element_get(device_path);
+   return 1;
+}
+
+/**
+ * Get property "WiFi.SSID" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * If the network type is WiFi, then this property is
+ * present and contains the binary SSID value.
+ *
+ * @param network_path to get property.
+ * @param count return the number of elements in array.
+ * @param wifi_ssid where to store the property value, must be a pointer
+ *        to array of bytes (unsigned char **).
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_network_wifi_ssid_get(const E_Connman_Element *network, unsigned int *count, unsigned char **wifi_ssid)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wifi_ssid, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(count, 0);
+   *wifi_ssid = e_connman_element_bytes_array_get_stringshared
+     (network, e_connman_prop_wifi_ssid, count);
+   if (!*wifi_ssid)
+     return 0;
+   return 1;
+}
+
+/**
+ * Get property "WiFi.Mode" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * If the network type is WiFi, then this property is
+ * present and contains the mode of the network. The
+ * possible values are "managed" or "adhoc".
+ *
+ * For scanned networks this value is read only, but in
+ * case the network was manually created it is also
+ * changeable.
+ *
+ * @param network_path to get property.
+ * @param wifi_mode where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_wifi_mode_set()
+ */
+bool
+e_connman_network_wifi_mode_get(const E_Connman_Element *network, const char **wifi_mode)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wifi_mode, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_wifi_mode, NULL, wifi_mode);
+}
+
+/**
+ * Call method SetProperty("WiFi.Mode", wifi_mode) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * If the network type is WiFi, then this property is
+ * present and contains the mode of the network. The
+ * possible values are "managed" or "adhoc".
+ *
+ * For scanned networks this value is read only, but in
+ * case the network was manually created it is also
+ * changeable.
+ *
+ * @param network_path to set property.
+ * @param wifi_mode value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_wifi_mode_get()
+ */
+bool
+e_connman_network_wifi_mode_set(E_Connman_Element *network, const char *wifi_mode, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wifi_mode, 0);
+   return e_connman_element_property_set_full
+     (network, e_connman_prop_wifi_mode, DBUS_TYPE_STRING, wifi_mode, cb, data);
+}
+
+/**
+ * Get property "WiFi.Security" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * If the network type is WiFi, then this property is
+ * present and contains the security method or key
+ * management setting.
+ *
+ * For scanned networks this value is read only, but in
+ * case the network was manually created it is also
+ * changeable.
+ *
+ * Possible values are "none", "wep", "wpa" and "wpa2".
+ *
+ * @param network_path to get property.
+ * @param wifi_security where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_wifi_security_set()
+ */
+bool
+e_connman_network_wifi_security_get(const E_Connman_Element *network, const char **wifi_security)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wifi_security, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_wifi_security, NULL, wifi_security);
+}
+
+/**
+ * Call method SetProperty("WiFi.Security", wifi_security) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * If the network type is WiFi, then this property is
+ * present and contains the security method or key
+ * management setting.
+ *
+ * For scanned networks this value is read only, but in
+ * case the network was manually created it is also
+ * changeable.
+ *
+ * Possible values are "none", "wep", "wpa" and "wpa2".
+ *
+ * @param network_path to set property.
+ * @param wifi_security value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_wifi_security_get()
+ */
+bool
+e_connman_network_wifi_security_set(E_Connman_Element *network, const char *wifi_security, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wifi_security, 0);
+   return e_connman_element_property_set_full
+     (network, e_connman_prop_wifi_security, DBUS_TYPE_STRING,
+      wifi_security, cb, data);
+}
+
+/**
+ * Get property "WiFi.Passphrase" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * If the network type is WiFi and a passhrase is
+ * requires, then this property is present and contains
+ * the passphrase in clear text.
+ *
+ * For systems using PolicyKit, the access to this value
+ * will be protected by the security policy.
+ *
+ * @param network_path to get property.
+ * @param wifi_passphrase where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_wifi_passphrase_set()
+ */
+bool
+e_connman_network_wifi_passphrase_get(const E_Connman_Element *network, const char **wifi_passphrase)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wifi_passphrase, 0);
+   return e_connman_element_property_get_stringshared
+     (network, e_connman_prop_wifi_passphrase, NULL, wifi_passphrase);
+}
+
+/**
+ * Call method SetProperty("WiFi.Passphrase", wifi_passphrase) at the given element on server.
+ *
+ * This is a server call, not local, so it may fail and in that case
+ * no property is updated locally. If the value was set the event
+ * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
+ *
+ * If the network type is WiFi and a passhrase is
+ * requires, then this property is present and contains
+ * the passphrase in clear text.
+ *
+ * For systems using PolicyKit, the access to this value
+ * will be protected by the security policy.
+ *
+ * @param network_path to set property.
+ * @param wifi_passphrase value to set.
+ * @param cb function to call when server replies or some error happens.
+ * @param data data to give to cb when it is called.
+ *
+ * @return 1 on success, 0 otherwise.
+ * @see e_connman_network_wifi_passphrase_get()
+ */
+bool
+e_connman_network_wifi_passphrase_set(E_Connman_Element *network, const char *wifi_passphrase, E_DBus_Method_Return_Cb cb, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(network, 0);
+   return e_connman_element_property_set_full
+     (network, e_connman_prop_wifi_passphrase, DBUS_TYPE_STRING,
+      wifi_passphrase, cb, data);
+}
diff --git a/src/lib/connman/e_connman_private.h b/src/lib/connman/e_connman_private.h
new file mode 100644 (file)
index 0000000..2b509dd
--- /dev/null
@@ -0,0 +1,114 @@
+#include <Eina.h>
+#include <eina_safety_checks.h>
+
+#include "E_Connman.h"
+#include <stdio.h>
+
+static const char manager_path[] = "/";
+
+extern const char *e_connman_iface_manager;
+extern const char *e_connman_iface_network;
+extern const char *e_connman_iface_profile;
+extern const char *e_connman_iface_service;
+extern const char *e_connman_iface_device;
+extern const char *e_connman_iface_connection;
+
+extern const char *e_connman_prop_available;
+extern const char *e_connman_prop_connected;
+extern const char *e_connman_prop_connections;
+extern const char *e_connman_prop_default;
+extern const char *e_connman_prop_device;
+extern const char *e_connman_prop_devices;
+extern const char *e_connman_prop_interface;
+extern const char *e_connman_prop_ipv4_address;
+extern const char *e_connman_prop_ipv4_method;
+extern const char *e_connman_prop_name;
+extern const char *e_connman_prop_network;
+extern const char *e_connman_prop_networks;
+extern const char *e_connman_prop_offline_mode;
+extern const char *e_connman_prop_policy;
+extern const char *e_connman_prop_powered;
+extern const char *e_connman_prop_priority;
+extern const char *e_connman_prop_profiles;
+extern const char *e_connman_prop_remember;
+extern const char *e_connman_prop_scan_interval;
+extern const char *e_connman_prop_scanning;
+extern const char *e_connman_prop_state;
+extern const char *e_connman_prop_strengh;
+extern const char *e_connman_prop_type;
+extern const char *e_connman_prop_wifi_mode;
+extern const char *e_connman_prop_wifi_passphrase;
+extern const char *e_connman_prop_wifi_security;
+extern const char *e_connman_prop_wifi_ssid;
+
+
+#define DBG(...) EINA_ERROR_PDBG(__VA_ARGS__)
+#define INF(...) EINA_ERROR_PINFO(__VA_ARGS__)
+#define WRN(...) EINA_ERROR_PWARN(__VA_ARGS__)
+#define ERR(...) EINA_ERROR_PERR(__VA_ARGS__)
+
+static inline bool
+__dbus_callback_check_and_init(const char *file, int line, const char *function, DBusMessage *msg, DBusMessageIter *itr, DBusError *err)
+{
+   if (!msg)
+     {
+       if (err)
+         eina_error_print(EINA_ERROR_LEVEL_ERR, file, function, line,
+                          "an error was reported by server: "
+                          "name=\"%s\", message=\"%s\"\n",
+                          err->name, err->message);
+       else
+         eina_error_print(EINA_ERROR_LEVEL_ERR, file, function, line,
+                          "callback without message arguments!\n");
+
+       return 0;
+     }
+
+   if (!dbus_message_iter_init(msg, itr))
+     {
+       eina_error_print(EINA_ERROR_LEVEL_ERR, file, function, line,
+                        "could not init iterator.\n");
+       return 0;
+     }
+
+   return 1;
+}
+
+#define _dbus_callback_check_and_init(msg, itr, err)                   \
+  __dbus_callback_check_and_init(__FILE__, __LINE__, __FUNCTION__,     \
+                                msg, itr, err)
+
+static inline bool
+__dbus_iter_type_check(const char *file, int line, const char *function, int type, int expected, const char *expected_name)
+{
+   if (type == expected)
+     return 1;
+
+   eina_error_print(EINA_ERROR_LEVEL_ERR, file, function, line,
+                   "expected type %s (%c) but got %c instead!\n",
+                   expected_name, expected, type);
+
+   return 0;
+}
+#define _dbus_iter_type_check(t, e) __dbus_iter_type_check(__FILE__, __LINE__, __FUNCTION__, t, e, #e)
+
+extern E_DBus_Connection *e_connman_conn;
+
+const char *e_connman_system_bus_name_get(void);
+
+void e_connman_manager_clear_elements(void);
+
+void e_connman_elements_init(void);
+void e_connman_elements_shutdown(void);
+
+E_Connman_Element *e_connman_element_register(const char *path, const char *interface);
+void e_connman_element_unregister(E_Connman_Element *element);
+
+bool e_connman_element_objects_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count, E_Connman_Element ***elements);
+unsigned char *e_connman_element_bytes_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count);
+
+bool e_connman_element_call_with_path(E_Connman_Element *element, const char *method_name, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data);
+
+bool e_connman_element_message_send(E_Connman_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, DBusMessage *msg, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data);
+
+bool e_connman_element_call_full(E_Connman_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data);
diff --git a/src/lib/connman/e_connman_profile.c b/src/lib/connman/e_connman_profile.c
new file mode 100644 (file)
index 0000000..2cdd3d0
--- /dev/null
@@ -0,0 +1,47 @@
+#include "e_connman_private.h"
+
+E_Connman_Element *
+e_connman_profile_get(const char *path)
+{
+   E_Connman_Element *profile;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
+
+   profile = e_connman_element_get(path);
+   if (!profile)
+     return NULL;
+
+   if (!e_connman_element_is_profile(profile))
+     {
+       WRN("path '%s' is not a profile!\n", path);
+       return NULL;
+     }
+
+   return profile;
+}
+
+/**
+ * Get property "Name" value.
+ *
+ * If this property isn't found then 0 is returned.
+ * If zero is returned, then this call failed and parameter-returned
+ * values shall be considered invalid.
+ *
+ * The profile name.
+ *
+ * @param profile_path to get property.
+ * @param name where to store the property value, must be a pointer
+ *        to string (const char **), it will not be allocated or
+ *        copied and references will be valid until element changes,
+ *        so copy it if you want to use it later.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
+bool
+e_connman_profile_name_get(const E_Connman_Element *profile, const char **name)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(profile, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
+   return e_connman_element_property_get_stringshared
+     (profile, e_connman_prop_name, NULL, name);
+}