discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=24fe43d735b26895025f2aa7706819d4a6663104

commit 24fe43d735b26895025f2aa7706819d4a6663104
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Wed Mar 2 16:58:27 2016 -0500

    add new wireless module/gadget
    
    this is the successor to the connman module/gadget. it does not use
    or depend on econnman.
---
 configure.ac                               |    2 +
 src/bin/e_module.c                         |    1 +
 src/modules/Makefile.mk                    |    2 +
 src/modules/Makefile_wireless.mk           |   27 +
 src/modules/wireless/connman.c             | 1634 ++++++++++++++++++++++++++++
 src/modules/wireless/e-module-wireless.edj |  Bin 0 -> 21146 bytes
 src/modules/wireless/mod.c                 |   33 +
 src/modules/wireless/module.desktop.in     |    8 +
 src/modules/wireless/wireless.c            | 1476 +++++++++++++++++++++++++
 src/modules/wireless/wireless.h            |  134 +++
 10 files changed, 3317 insertions(+)

diff --git a/configure.ac b/configure.ac
index 917d652..7b286c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -924,6 +924,7 @@ AC_E_OPTIONAL_MODULE([wl_weekeyboard], $have_wayland, 
[CHECK_MODULE_WL_WEEKEYBOA
 AC_E_OPTIONAL_MODULE([policy_mobile], true)
 AC_E_OPTIONAL_MODULE([geolocation], true)
 AC_E_OPTIONAL_MODULE([xwayland], $have_wayland, [CHECK_MODULE_XWAYLAND])
+AC_E_OPTIONAL_MODULE([wireless], true)
 
 if test "x${HAVE_WL_X11}" != "xyes" && test "x${have_wayland}" = "xyes" && 
test "x${HAVE_XWAYLAND}" != "xyes"; then
   AC_DEFINE_UNQUOTED([HAVE_WAYLAND_ONLY],[1],[enable wayland-only version of 
enlightenment])
@@ -1125,6 +1126,7 @@ src/modules/tiling/module.desktop
 src/modules/music-control/module.desktop
 src/modules/packagekit/module.desktop
 src/modules/wl_desktop_shell/module.desktop
+src/modules/wireless/module.desktop
 data/xsession/enlightenment.desktop
 data/etc/sysactions.conf
 data/units/enlightenment.service
diff --git a/src/bin/e_module.c b/src/bin/e_module.c
index c211b93..945788d 100644
--- a/src/bin/e_module.c
+++ b/src/bin/e_module.c
@@ -1025,6 +1025,7 @@ _e_module_whitelist_check(void)
       "temperature",
       "tiling",
       "winlist",
+      "wireless",
       "wizard",
       "wl_desktop_shell",
       "wl_x11",
diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk
index f4d5f6a..bb618da 100644
--- a/src/modules/Makefile.mk
+++ b/src/modules/Makefile.mk
@@ -127,3 +127,5 @@ include src/modules/Makefile_wl_weekeyboard.mk
 include src/modules/Makefile_policy_mobile.mk
 
 include src/modules/Makefile_geolocation.mk
+
+include src/modules/Makefile_wireless.mk
diff --git a/src/modules/Makefile_wireless.mk b/src/modules/Makefile_wireless.mk
new file mode 100644
index 0000000..0d28d40
--- /dev/null
+++ b/src/modules/Makefile_wireless.mk
@@ -0,0 +1,27 @@
+EXTRA_DIST += \
+src/modules/wireless/module.desktop.in \
+src/modules/wireless/e-module-wireless.edj
+
+if USE_MODULE_WIRELESS
+wirelessdir = $(MDIR)/wireless
+wireless_DATA = \
+src/modules/wireless/module.desktop \
+src/modules/wireless/e-module-wireless.edj
+
+wirelesspkgdir = $(MDIR)/wireless/$(MODULE_ARCH)
+wirelesspkg_LTLIBRARIES = src/modules/wireless/module.la
+
+src_modules_wireless_module_la_LDFLAGS = $(MOD_LDFLAGS)
+src_modules_wireless_module_la_SOURCES = \
+src/modules/wireless/connman.c \
+src/modules/wireless/mod.c \
+src/modules/wireless/wireless.c \
+src/modules/wireless/wireless.h
+
+src_modules_wireless_module_la_CPPFLAGS = $(MOD_CPPFLAGS)
+src_modules_wireless_module_la_LIBADD = $(MOD_LIBS)
+
+PHONIES += wireless install-wireless
+wireless: $(wirelesspkg_LTLIBRARIES) $(wireless_DATA)
+install-wireless: install-wirelessDATA install-wirelesspkgLTLIBRARIES
+endif
diff --git a/src/modules/wireless/connman.c b/src/modules/wireless/connman.c
new file mode 100644
index 0000000..662e23a
--- /dev/null
+++ b/src/modules/wireless/connman.c
@@ -0,0 +1,1634 @@
+#include "wireless.h"
+
+#define CONNMAN_BUS_NAME "net.connman"
+#define CONNMAN_MANAGER_IFACE CONNMAN_BUS_NAME ".Manager"
+#define CONNMAN_SERVICE_IFACE CONNMAN_BUS_NAME ".Service"
+#define CONNMAN_TECHNOLOGY_IFACE CONNMAN_BUS_NAME ".Technology"
+#define CONNMAN_TECHNOLOGY_PATH_ETHERNET "/net/connman/technology/ethernet"
+#define CONNMAN_TECHNOLOGY_PATH_WIFI "/net/connman/technology/wifi"
+#define CONNMAN_TECHNOLOGY_PATH_BT "/net/connman/technology/bluetooth"
+#define CONNMAN_TECHNOLOGY_PATH_CELLULAR "/net/connman/technology/cellular"
+#define CONNMAN_AGENT_IFACE "net.connman.Agent"
+#define CONNMAN_AGENT_PATH "/org/enlightenment/wireless/agent"
+
+#define CONNMAN_SERVICE_TYPE_ITER(i) \
+  for ((i) = 0; (i) < CONNMAN_SERVICE_TYPE_LAST; (i)++)
+
+#define MILLI_PER_SEC 1000
+#define CONNMAN_CONNECTION_TIMEOUT 60 * MILLI_PER_SEC
+
+#undef DBG
+#undef INF
+#undef WRN
+#undef ERR
+
+#define DBG(...) EINA_LOG_DOM_DBG(_connman_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_connman_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_connman_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_connman_log_dom, __VA_ARGS__)
+
+typedef enum
+{
+   CONNMAN_STATE_NONE = -1, /* All unknown states */
+   CONNMAN_STATE_OFFLINE,
+   CONNMAN_STATE_IDLE,
+   CONNMAN_STATE_ASSOCIATION,
+   CONNMAN_STATE_CONFIGURATION,
+   CONNMAN_STATE_READY,
+   CONNMAN_STATE_ONLINE,
+   CONNMAN_STATE_DISCONNECT,
+   CONNMAN_STATE_FAILURE,
+} Connman_State;
+
+typedef enum
+{
+   CONNMAN_SERVICE_TYPE_NONE = -1, /* All non-supported types */
+   CONNMAN_SERVICE_TYPE_ETHERNET = 0,
+   CONNMAN_SERVICE_TYPE_WIFI = 1,
+   CONNMAN_SERVICE_TYPE_BLUETOOTH = 2,
+   CONNMAN_SERVICE_TYPE_CELLULAR = 3,
+   CONNMAN_SERVICE_TYPE_LAST = 4,
+} Connman_Service_Type;
+
+typedef struct Connman_Technology
+{
+   Connman_Service_Type type;
+   Eldbus_Proxy *proxy;
+   Eina_Stringshare *tethering_ssid;
+   Eina_Stringshare *tethering_passwd;
+   Eina_Bool powered : 1;
+   Eina_Bool connected : 1;
+   Eina_Bool tethering : 1;
+} Connman_Technology;
+
+typedef struct
+{
+   EINA_INLIST;
+   Eldbus_Proxy *proxy;
+
+   /* Private */
+   struct
+   {
+      Eldbus_Pending *connect;
+      Eldbus_Pending *disconnect;
+      Eldbus_Pending *remov;
+      void *data;
+   } pending;
+   Eldbus_Signal_Handler *handler;
+
+   /* Properties */
+   Eina_Stringshare *path;
+   Eina_Stringshare *name;
+   Wireless_Network_Security security;
+   Connman_State state;
+   Connman_Service_Type type;
+   uint8_t strength;
+
+   /* Connection */
+   unsigned int method;
+   Eina_Stringshare *address;
+   Eina_Stringshare *gateway;
+   union
+   {
+      struct
+      {
+         Eina_Stringshare *netmask;
+      } v4;
+      struct
+      {
+         Eina_Stringshare *prefixlength;
+         Wireless_Network_IPv6_Privacy privacy;
+      } v6;
+   } ip;
+
+   Eina_Array *domain_servers;
+   Eina_Array *name_servers;
+   Eina_Array *time_servers;
+
+   /* Proxy */
+   unsigned int proxy_type;
+   Eina_Stringshare *proxy_url;
+   Eina_Array *proxy_servers;
+   Eina_Array *proxy_excludes;
+   Eina_Bool ipv6 : 1;
+   Eina_Bool favorite : 1;
+} Connman_Service;
+
+typedef enum
+{
+   CONNMAN_FIELD_STATE_MANDATORY,
+   CONNMAN_FIELD_STATE_OPTIONAL,
+   CONNMAN_FIELD_STATE_ALTERNATE,
+   CONNMAN_FIELD_STATE_INFO,
+} Connman_Field_State;
+
+typedef struct Connman_Field
+{
+   const char *name;
+
+   Connman_Field_State requirement;
+   const char *type;
+   const char *value;
+} Connman_Field;
+
+static int _connman_log_dom = -1;
+
+static Eldbus_Proxy *proxy_manager;
+
+static Eldbus_Pending *pending_gettechnologies;
+static Eldbus_Pending *pending_getservices;
+static Eldbus_Pending *pending_getproperties_manager;
+
+static Eina_List *signal_handlers;
+
+static Eina_Inlist *connman_services_list[CONNMAN_SERVICE_TYPE_LAST];
+static Eina_Hash *connman_services[CONNMAN_SERVICE_TYPE_LAST];
+static Eldbus_Service_Interface *agent_iface;
+
+static Connman_Service *connman_current_service[CONNMAN_SERVICE_TYPE_LAST];
+static Wireless_Connection 
*connman_current_connection[CONNMAN_SERVICE_TYPE_LAST];
+
+static Connman_Technology connman_technology[CONNMAN_SERVICE_TYPE_LAST];
+
+/* connman -> wireless */
+static Eina_Hash *connman_services_map[CONNMAN_SERVICE_TYPE_LAST];
+
+static inline Eina_Bool
+_connman_service_is_connected(const Connman_Service *cs)
+{
+   return (cs->state >= CONNMAN_STATE_ASSOCIATION) && (cs->state <= 
CONNMAN_STATE_ONLINE);
+}
+
+static void
+_eldbus_proxy_del(Eldbus_Proxy *proxy)
+{
+   Eldbus_Object *obj;
+
+   obj = eldbus_proxy_object_get(proxy);
+   eldbus_proxy_unref(proxy);
+   eldbus_object_unref(obj);
+}
+
+static void
+_connman_service_connect_cb(void *data, const Eldbus_Message *msg, 
Eldbus_Pending *pending EINA_UNUSED)
+{
+   Connman_Service *cs = data;
+   const char *error;
+
+   /* FIXME */
+   cs->pending.connect = NULL;
+   eldbus_message_error_get(msg, NULL, &error);
+}
+
+static Eina_Bool 
+_connman_service_connect(Wireless_Network *wn)
+{
+   Connman_Service *cs;
+
+   cs = eina_hash_find(connman_services[wn->type], wn->path);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cs, EINA_FALSE);
+   if (!cs->pending.connect)
+     cs->pending.connect = eldbus_proxy_call(cs->proxy, "Connect",
+                                             _connman_service_connect_cb, cs,
+                                             CONNMAN_CONNECTION_TIMEOUT, "");
+   return !!cs->pending.connect;
+}
+
+static void
+_connman_update_technologies(void)
+{
+   Eina_Bool avail[CONNMAN_SERVICE_TYPE_LAST];
+   int i;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     avail[i] = connman_technology[i].type > -1;
+   wireless_service_type_available_set(avail);
+}
+
+static void
+_connman_update_enabled_technologies(void)
+{
+   Eina_Bool enabled[CONNMAN_SERVICE_TYPE_LAST];
+   int i;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     enabled[i] = connman_technology[i].powered;
+   wireless_service_type_enabled_set(enabled);
+}
+
+static Wireless_Network_State
+_connman_wifi_state_convert(Connman_State state)
+{
+   Wireless_Network_State wifi_state;
+   switch (state)
+     {
+      case CONNMAN_STATE_ASSOCIATION:
+      case CONNMAN_STATE_CONFIGURATION:
+        wifi_state = WIRELESS_NETWORK_STATE_CONFIGURING;
+        break;
+      case CONNMAN_STATE_READY:
+        wifi_state = WIRELESS_NETWORK_STATE_CONNECTED;
+        break;
+      case CONNMAN_STATE_ONLINE:
+        wifi_state = WIRELESS_NETWORK_STATE_ONLINE;
+        break;
+      case CONNMAN_STATE_FAILURE:
+        wifi_state = WIRELESS_NETWORK_STATE_FAILURE;
+        break;
+      case CONNMAN_STATE_NONE:
+      case CONNMAN_STATE_OFFLINE:
+      case CONNMAN_STATE_IDLE:
+      case CONNMAN_STATE_DISCONNECT:
+      default:
+        wifi_state = WIRELESS_NETWORK_STATE_NONE;
+     }
+   return wifi_state;
+}
+
+static Wireless_Network *
+_connman_service_convert(Connman_Service *cs)
+{
+   Wireless_Network *wn;
+
+   wn = E_NEW(Wireless_Network, 1);
+   memcpy(wn, &cs->path, offsetof(Wireless_Network, connect_cb));
+   wn->state = _connman_wifi_state_convert(cs->state);
+   wn->connect_cb = _connman_service_connect;
+   return wn;
+}
+
+static void
+_connman_update_current_network(Connman_Service *cs, Connman_Service_Type type)
+{
+   if (connman_current_service[type] != cs)
+     {
+        E_FREE(connman_current_connection[type]);
+        if (cs)
+          connman_current_connection[type] = E_NEW(Wireless_Connection, 1);
+     }
+   connman_current_service[type] = cs;
+   if (cs)
+     {
+        connman_current_connection[type]->wn = 
eina_hash_find(connman_services_map[type], &cs);
+        memcpy(&connman_current_connection[type]->method,
+          &cs->method, sizeof(Wireless_Connection) - sizeof(void*));
+     }
+   else
+     connman_current_connection[type] = NULL;
+   wireless_wifi_current_networks_set(connman_current_connection);
+}
+
+static void
+_connman_update_networks(Connman_Service_Type type)
+{
+   Eina_Array *arr;
+   Connman_Service *cs;
+   Wireless_Network *wn;
+   Eina_Hash *map;
+   Connman_Service *services[CONNMAN_SERVICE_TYPE_LAST] = {NULL};
+
+   map = connman_services_map[type];
+   connman_services_map[type] = eina_hash_pointer_new(free);
+   arr = eina_array_new(eina_hash_population(connman_services[type]));
+   EINA_INLIST_FOREACH(connman_services_list[type], cs)
+     {
+        wn = _connman_service_convert(cs);
+        eina_hash_add(connman_services_map[type], &cs, wn);
+        eina_array_push(arr, wn);
+        if (connman_current_service[type] && _connman_service_is_connected(cs))
+          services[type] = cs;
+     }
+   memcpy(&connman_current_service, services, CONNMAN_SERVICE_TYPE_LAST * 
sizeof(void*));
+   arr = wireless_networks_set(arr);
+   _connman_update_current_network(connman_current_service[type], type);
+   eina_hash_free(map);
+   eina_array_free(arr);
+}
+
+static void
+_connman_update_airplane_mode(Eina_Bool offline)
+{
+   wireless_airplane_mode_set(offline);
+}
+
+static Connman_State
+str_to_state(const char *s)
+{
+   if (!strcmp(s, "offline"))
+     return CONNMAN_STATE_OFFLINE;
+   if (!strcmp(s, "idle"))
+     return CONNMAN_STATE_IDLE;
+   if (!strcmp(s, "association"))
+     return CONNMAN_STATE_ASSOCIATION;
+   if (!strcmp(s, "configuration"))
+     return CONNMAN_STATE_CONFIGURATION;
+   if (!strcmp(s, "ready"))
+     return CONNMAN_STATE_READY;
+   if (!strcmp(s, "online"))
+     return CONNMAN_STATE_ONLINE;
+   if (!strcmp(s, "disconnect"))
+     return CONNMAN_STATE_DISCONNECT;
+   if (!strcmp(s, "failure"))
+     return CONNMAN_STATE_FAILURE;
+
+   ERR("Unknown state %s", s);
+   return CONNMAN_STATE_NONE;
+}
+
+static Connman_Service_Type
+str_to_type(const char *s)
+{
+   if (!strcmp(s, "ethernet"))
+     return CONNMAN_SERVICE_TYPE_ETHERNET;
+   if (!strcmp(s, "wifi"))
+     return CONNMAN_SERVICE_TYPE_WIFI;
+   if (!strcmp(s, "bluetooth"))
+     return CONNMAN_SERVICE_TYPE_BLUETOOTH;
+   if (!strcmp(s, "cellular"))
+     return CONNMAN_SERVICE_TYPE_CELLULAR;
+
+   DBG("Unknown type %s", s);
+   return CONNMAN_SERVICE_TYPE_NONE;
+}
+
+static Wireless_Network_Security
+str_to_security(const char *s)
+{
+   if (!strcmp(s, "none")) return WIRELESS_NETWORK_SECURITY_NONE;
+   if (!strcmp(s, "wep")) return WIRELESS_NETWORK_SECURITY_WEP;
+   if (!strcmp(s, "psk")) return WIRELESS_NETWORK_SECURITY_PSK;
+   if (!strcmp(s, "ieee8021x")) return WIRELESS_NETWORK_SECURITY_IEEE8021X;
+   if (!strcmp(s, "wps")) return WIRELESS_NETWORK_SECURITY_WPS;
+   CRI("UNKNOWN TYPE %s", s);
+   return WIRELESS_NETWORK_SECURITY_NONE;
+}
+
+static void
+_connman_service_free(Connman_Service *cs)
+{
+   if (!cs) return;
+
+   if (cs->pending.connect)
+     {
+        eldbus_pending_cancel(cs->pending.connect);
+        free(cs->pending.data);
+     }
+   else if (cs->pending.disconnect)
+     {
+        eldbus_pending_cancel(cs->pending.disconnect);
+        free(cs->pending.data);
+     }
+   else if (cs->pending.remov)
+     {
+        eldbus_pending_cancel(cs->pending.remov);
+        free(cs->pending.data);
+     }
+   eina_stringshare_del(cs->address);
+   eina_stringshare_del(cs->gateway);
+   if (cs->ipv6)
+     eina_stringshare_del(cs->ip.v6.prefixlength);
+   else
+     eina_stringshare_del(cs->ip.v4.netmask);
+
+   eina_stringshare_del(cs->proxy_url);
+
+   array_clear(cs->domain_servers);
+   array_clear(cs->name_servers);
+   array_clear(cs->time_servers);
+
+   array_clear(cs->proxy_servers);
+   array_clear(cs->proxy_excludes);
+
+   eina_stringshare_del(cs->name);
+   eina_stringshare_del(cs->path);
+   eldbus_signal_handler_del(cs->handler);
+   DBG("service free %p || proxy %p", cs, cs->proxy);
+   _eldbus_proxy_del(cs->proxy);
+   connman_services_list[cs->type] = 
eina_inlist_remove(connman_services_list[cs->type], EINA_INLIST_GET(cs));
+
+   free(cs);
+}
+
+static void
+_connman_service_parse_stringarray(Eldbus_Message_Iter *value, Eina_Array 
**arr)
+{
+   Eldbus_Message_Iter *itr_array;
+   const char *s;
+
+   EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, "as",
+                                                         &itr_array));
+   if (*arr)
+     {
+        while (eina_array_count(*arr))
+          eina_stringshare_del(eina_array_pop(*arr));
+     }
+   else
+     *arr = eina_array_new(1);
+   while (eldbus_message_iter_get_and_next(itr_array, 's', &s))
+     eina_array_push(*arr, eina_stringshare_add(s));
+}
+
+static void
+_connman_service_parse_prop_changed(Connman_Service *cs, const char 
*prop_name, Eldbus_Message_Iter *value)
+{
+   DBG("service %p %s prop %s", cs, cs->path, prop_name);
+
+   if (!strcmp(prop_name, "State"))
+     {
+        const char *state;
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value,
+                                                                     "s",
+                                                                     &state));
+        cs->state = str_to_state(state);
+        DBG("New state: %s %d", state, cs->state);
+     }
+   if (!strcmp(prop_name, "Favorite"))
+     {
+        Eina_Bool state;
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value,
+                                                                     "b",
+                                                                     &state));
+        cs->favorite = !!state;
+        DBG("New favorite state: %d", cs->favorite);
+     }
+   else if (!strcmp(prop_name, "Name"))
+     {
+        const char *name;
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value,
+                                                                     "s",
+                                                                     &name));
+        eina_stringshare_replace(&cs->name, name);
+        DBG("New name: %s", cs->name);
+     }
+   else if (!strcmp(prop_name, "Type"))
+     {
+        const char *type;
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value,
+                                                                     "s",
+                                                                     &type));
+        cs->type = str_to_type(type);
+        DBG("New type: %s %d", type, cs->type);
+     }
+   else if (!strcmp(prop_name, "Strength"))
+     {
+        uint8_t strength;
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value,
+                                                                     "y",
+                                                                     
&strength));
+        cs->strength = strength;
+        DBG("New strength: %d", strength);
+     }
+   else if (!strcmp(prop_name, "Security"))
+     {
+        const char *s;
+        Eldbus_Message_Iter *itr_array;
+
+        DBG("Old security: %u", cs->security);
+        cs->security = WIRELESS_NETWORK_SECURITY_NONE;
+
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, 
"as",
+                                                                        
&itr_array));
+        while (eldbus_message_iter_get_and_next(itr_array, 's', &s))
+          cs->security |= str_to_security(s);
+        DBG("New security %u", cs->security);
+     }
+   else if (!strcmp(prop_name, "IPv4"))
+     {
+        Eldbus_Message_Iter *array, *dict;
+
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, 
"a{sv}", &array));
+        while (eldbus_message_iter_get_and_next(array, 'e', &dict))
+          {
+             Eldbus_Message_Iter *var;
+             const char *name, *val;
+
+             
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(dict, "sv", 
&name, &var));
+             if (!strcmp(name, "Method"))
+               {
+                  cs->method = WIRELESS_NETWORK_IPV4_METHOD_OFF;
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  if (!strcmp(val, "off"))
+                    cs->method = WIRELESS_NETWORK_IPV4_METHOD_OFF;
+                  else if (!strcmp(val, "dhcp"))
+                    cs->method = WIRELESS_NETWORK_IPV4_METHOD_DHCP;
+                  else if (!strcmp(val, "manual"))
+                    cs->method = WIRELESS_NETWORK_IPV4_METHOD_MANUAL;
+                  else if (!strcmp(val, "fixed"))
+                    cs->method = WIRELESS_NETWORK_IPV4_METHOD_FIXED;
+               }
+             else if (!strcmp(name, "Address"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->address, val);
+               }
+             else if (!strcmp(name, "Netmask"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->ip.v4.netmask, val);
+               }
+             else if (!strcmp(name, "Gateway"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->gateway, val);
+               }
+          }
+     }
+   else if (!strcmp(prop_name, "IPv6"))
+     {
+        Eldbus_Message_Iter *array, *dict;
+
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, 
"a{sv}", &array));
+        while (eldbus_message_iter_get_and_next(array, 'e', &dict))
+          {
+             Eldbus_Message_Iter *var;
+             const char *name, *val;
+
+             
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(dict, "sv", 
&name, &var));
+             if (!strcmp(name, "Method"))
+               {
+                  cs->method = WIRELESS_NETWORK_IPV6_METHOD_OFF;
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  if (!strcmp(val, "auto"))
+                    cs->method = WIRELESS_NETWORK_IPV6_METHOD_AUTO;
+                  else if (!strcmp(val, "manual"))
+                    cs->method = WIRELESS_NETWORK_IPV6_METHOD_MANUAL;
+                  else if (!strcmp(val, "6to4"))
+                    cs->method = WIRELESS_NETWORK_IPV6_METHOD_6TO4;
+                  else if (!strcmp(val, "fixed"))
+                    cs->method = WIRELESS_NETWORK_IPV6_METHOD_FIXED;
+               }
+             else if (!strcmp(name, "Privacy"))
+               {
+                  cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED;
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  if (!strcmp(val, "disabled"))
+                    cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED;
+                  else if (!strcmp(val, "enabled"))
+                    cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_ENABLED;
+                  else if (!strcmp(val, "preferred"))
+                    cs->ip.v6.privacy = 
WIRELESS_NETWORK_IPV6_PRIVACY_PREFERRED;
+               }
+             else if (!strcmp(name, "Address"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->address, val);
+               }
+             else if (!strcmp(name, "PrefixLength"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->ip.v6.prefixlength, val);
+               }
+             else if (!strcmp(name, "Gateway"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->gateway, val);
+               }
+          }
+     }
+   else if (!strcmp(prop_name, "Proxy"))
+     {
+        Eldbus_Message_Iter *array, *dict;
+
+        EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, 
"a{sv}", &array));
+        while (eldbus_message_iter_get_and_next(array, 'e', &dict))
+          {
+             Eldbus_Message_Iter *var;
+             const char *name, *val;
+
+             
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(dict, "sv", 
&name, &var));
+             if (!strcmp(name, "Method"))
+               {
+                  cs->proxy_type = WIRELESS_PROXY_TYPE_DIRECT;
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  if (!strcmp(val, "manual"))
+                    cs->proxy_type = WIRELESS_PROXY_TYPE_MANUAL;
+                  else if (!strcmp(val, "auto"))
+                    cs->proxy_type = WIRELESS_PROXY_TYPE_AUTO;
+               }
+             else if (!strcmp(name, "URL"))
+               {
+                  
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val));
+                  eina_stringshare_replace(&cs->proxy_url, val);
+               }
+             else if (!strcmp(name, "Servers"))
+               _connman_service_parse_stringarray(value, &cs->proxy_servers);
+             else if (!strcmp(name, "Excludes"))
+               _connman_service_parse_stringarray(value, &cs->proxy_excludes);
+          }
+     }
+   else if (!strcmp(prop_name, "Nameservers"))
+     _connman_service_parse_stringarray(value, &cs->name_servers);
+   else if (!strcmp(prop_name, "Timeservers"))
+     _connman_service_parse_stringarray(value, &cs->time_servers);
+   else if (!strcmp(prop_name, "Domains"))
+     _connman_service_parse_stringarray(value, &cs->domain_servers);
+}
+
+static void
+_connman_service_prop_dict_changed(Connman_Service *cs, Eldbus_Message_Iter 
*props)
+{
+   Eldbus_Message_Iter *dict;
+
+   while (eldbus_message_iter_get_and_next(props, 'e', &dict))
+     {
+        char *name;
+        Eldbus_Message_Iter *var;
+
+        if (eldbus_message_iter_arguments_get(dict, "sv", &name, &var))
+          _connman_service_parse_prop_changed(cs, name, var);
+     }
+   if (_connman_service_is_connected(cs))
+     _connman_update_current_network(cs, cs->type);
+}
+
+static void
+_connman_service_property(void *data, const Eldbus_Message *msg)
+{
+   Connman_Service *cs = data;
+   Eldbus_Message_Iter *var;
+   const char *name;
+
+   if (eldbus_message_arguments_get(msg, "sv", &name, &var))
+     _connman_service_parse_prop_changed(cs, name, var);
+   if (_connman_service_is_connected(cs))
+     _connman_update_current_network(cs, cs->type);
+}
+
+static Connman_Service *
+_connman_service_new(const char *path, Eldbus_Message_Iter *props)
+{
+   Connman_Service *cs;
+   Eldbus_Object *obj;
+
+   cs = E_NEW(Connman_Service, 1);
+   cs->path = eina_stringshare_add(path);
+
+   obj = eldbus_object_get(dbus_conn, CONNMAN_BUS_NAME, path);
+   cs->proxy = eldbus_proxy_get(obj, CONNMAN_SERVICE_IFACE);
+   cs->handler = eldbus_proxy_signal_handler_add(cs->proxy, "PropertyChanged",
+                                  _connman_service_property, cs);
+
+   _connman_service_prop_dict_changed(cs, props);
+   connman_services_list[cs->type] = 
eina_inlist_append(connman_services_list[cs->type], EINA_INLIST_GET(cs));
+   eina_hash_add(connman_services[cs->type], cs->path, cs);
+   DBG("Added service: %p %s || proxy %p", cs, path, cs->proxy);
+   return cs;
+}
+
+static void
+_connman_manager_agent_register(void *data EINA_UNUSED, const Eldbus_Message 
*msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
+{
+   /* FIXME: should this do something? */
+}
+
+static Eina_Bool
+_connman_technology_parse_prop_changed(Connman_Technology *ct, const char 
*name, Eldbus_Message_Iter *value)
+{
+   Eina_Bool val;
+   const char *str;
+   Eina_Bool ret = EINA_FALSE;
+
+   if (!strcmp(name, "Powered"))
+     {
+        eldbus_message_iter_arguments_get(value, "b", &val);
+        val = !!val;
+        if (val != ct->powered) ret = EINA_TRUE;
+        ct->powered = !!val;
+     }
+   else if (!strcmp(name, "Connected"))
+     {
+        eldbus_message_iter_arguments_get(value, "b", &val);
+        ct->connected = !!val;
+     }
+   else if (!strcmp(name, "Tethering"))
+     {
+        eldbus_message_iter_arguments_get(value, "b", &val);
+        ct->tethering = !!val;
+     }
+   else if (!strcmp(name, "TetheringIdentifier"))
+     {
+        eldbus_message_iter_arguments_get(value, "b", &str);
+        ct->tethering_ssid = eina_stringshare_add(str);
+     }
+   else if (!strcmp(name, "TetheringPassphrase"))
+     {
+        eldbus_message_iter_arguments_get(value, "b", &str);
+        ct->tethering_passwd = eina_stringshare_add(str);
+     }
+   return ret;
+}
+
+static void
+_connman_technology_event_property(void *data, const Eldbus_Message *msg)
+{
+   Eldbus_Message_Iter *var;
+   const char *name;
+   Connman_Technology *ct = NULL;
+   int i;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     if (data == connman_technology[i].proxy)
+       {
+          ct = &connman_technology[i];
+          break;
+       }
+   if (!ct) return;
+
+   if (!eldbus_message_arguments_get(msg, "sv", &name, &var))
+     ERR("Could not parse message %p", msg);
+   else if (_connman_technology_parse_prop_changed(ct, name, var))
+     _connman_update_enabled_technologies();
+}
+
+static Eina_Bool
+_connman_manager_parse_prop_changed(const char *name, Eldbus_Message_Iter 
*value)
+{
+   if (!strcmp(name, "State"))
+     {
+        const char *state;
+
+        if (!eldbus_message_iter_arguments_get(value, "s", &state))
+          return EINA_FALSE;
+        DBG("New state: %s", state);
+        //_connman_update_state(str_to_state(state));
+     }
+   else if (!strcmp(name, "OfflineMode"))
+     {
+        Eina_Bool offline;
+        if (!eldbus_message_iter_arguments_get(value, "b", &offline))
+          return EINA_FALSE;
+        _connman_update_airplane_mode(offline);
+     }
+   else
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static void
+_connman_manager_getproperties(void *data EINA_UNUSED, const Eldbus_Message 
*msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   Eldbus_Message_Iter *array, *dict;
+   const char *name, *text;
+
+   pending_getproperties_manager = NULL;
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not get properties. %s: %s", name, text);
+        return;
+     }
+
+   if (!eldbus_message_arguments_get(msg, "a{sv}", &array))
+     {
+        ERR("Error getting arguments.");
+        return;
+     }
+
+   while (eldbus_message_iter_get_and_next(array, 'e', &dict))
+     {
+        const char *key;
+        Eldbus_Message_Iter *var;
+
+        if (eldbus_message_iter_arguments_get(dict, "sv", &key, &var))
+          _connman_manager_parse_prop_changed(key, var);
+     }
+}
+
+static void
+_connman_manager_getservices(void *data EINA_UNUSED, const Eldbus_Message 
*msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   Eldbus_Message_Iter *array, *s;
+   const char *name, *text;
+   int i;
+   Eina_Bool update[CONNMAN_SERVICE_TYPE_LAST] = {0};
+
+   pending_getservices = NULL;
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     eina_hash_free_buckets(connman_services[i]);
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not get services. %s: %s", name, text);
+        return;
+     }
+
+   if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array))
+     {
+        ERR("Error getting array");
+        return;
+     }
+
+   while (eldbus_message_iter_get_and_next(array, 'r', &s))
+     {
+        const char *path;
+        Eldbus_Message_Iter *inner_array;
+        Connman_Service *cs;
+
+        if (!eldbus_message_iter_arguments_get(s, "oa{sv}", &path, 
&inner_array))
+          continue;
+
+        cs = _connman_service_new(path, inner_array);
+        update[cs->type] = 1;
+     }
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     if (update[i]) _connman_update_networks(i);
+}
+
+static void
+_connman_manager_gettechnologies(void *data EINA_UNUSED, const Eldbus_Message 
*msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   Eldbus_Message_Iter *array, *s;
+   const char *name, *text;
+
+   pending_gettechnologies = NULL;
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not get technologies. %s: %s", name, text);
+        return;
+     }
+
+   if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array))
+     {
+        ERR("Error getting array");
+        return;
+     }
+
+   while (eldbus_message_iter_get_and_next(array, 'r', &s))
+     {
+        const char *path;
+        Eldbus_Message_Iter *inner_array, *dict;
+        Connman_Technology *ct = NULL;
+        Eldbus_Object *obj;
+        int i;
+        const char *paths[] =
+        {
+           CONNMAN_TECHNOLOGY_PATH_ETHERNET,
+           CONNMAN_TECHNOLOGY_PATH_WIFI,
+           CONNMAN_TECHNOLOGY_PATH_BT,
+           CONNMAN_TECHNOLOGY_PATH_CELLULAR,
+        };
+
+        if (!eldbus_message_iter_arguments_get(s, "oa{sv}", &path, 
&inner_array))
+          continue;
+        CONNMAN_SERVICE_TYPE_ITER(i)
+          {
+             if (strcmp(path, paths[i])) continue;
+             ct = &connman_technology[i];
+             ct->type = i;
+
+             obj = eldbus_object_get(dbus_conn, CONNMAN_BUS_NAME, paths[i]);
+             ct->proxy = eldbus_proxy_get(obj, CONNMAN_TECHNOLOGY_IFACE);
+             signal_handlers = eina_list_append(signal_handlers,
+               eldbus_proxy_signal_handler_add(ct->proxy, "PropertyChanged",
+                                             
_connman_technology_event_property, ct->proxy));
+          }
+        if (!ct)
+          {
+             ERR("No handler for technology: %s", path);
+             continue;
+          }
+        while (eldbus_message_iter_get_and_next(inner_array, 'e', &dict))
+          {
+             Eldbus_Message_Iter *var;
+
+             if (eldbus_message_iter_arguments_get(dict, "sv", &name, &var))
+               _connman_technology_parse_prop_changed(ct, name, var);
+          }
+     }
+   /* scan not supported on bluetooth */
+   if (connman_technology[CONNMAN_SERVICE_TYPE_BLUETOOTH].proxy)
+     pending_getservices = eldbus_proxy_call(proxy_manager, "GetServices", 
_connman_manager_getservices,
+       NULL, -1, "");
+   else if (connman_technology[CONNMAN_SERVICE_TYPE_WIFI].proxy)
+     eldbus_proxy_call(connman_technology[CONNMAN_SERVICE_TYPE_WIFI].proxy, 
"Scan", NULL, NULL, -1, "");
+   _connman_update_technologies();
+   _connman_update_enabled_technologies();
+}
+
+static void
+_connman_manager_event_services(void *data EINA_UNUSED, const Eldbus_Message 
*msg)
+{
+   Eldbus_Message_Iter *changed, *removed, *s;
+   const char *path;
+   int i;
+   Eina_Bool update[CONNMAN_SERVICE_TYPE_LAST] = {0};
+
+   if (pending_getservices) return;
+
+   if (!eldbus_message_arguments_get(msg, "a(oa{sv})ao", &changed, &removed))
+     {
+        ERR("Error getting arguments");
+        return;
+     }
+
+   while (eldbus_message_iter_get_and_next(removed, 'o', &path))
+     {
+        CONNMAN_SERVICE_TYPE_ITER(i)
+          {
+             if (!eina_hash_del_by_key(connman_services[i], path)) continue;
+             DBG("Removed service: %s", path);
+             update[i] = 1;
+             break;
+          }
+     }
+
+   while (eldbus_message_iter_get_and_next(changed, 'r', &s))
+     {
+        Connman_Service *cs;
+        Eldbus_Message_Iter *array;
+        Eina_Bool found = EINA_FALSE;
+
+        if (!eldbus_message_iter_arguments_get(s, "oa{sv}", &path, &array))
+          continue;
+
+        CONNMAN_SERVICE_TYPE_ITER(i)
+          {
+             cs = eina_hash_find(connman_services[i], path);
+             if (!cs) continue;
+             _connman_service_prop_dict_changed(cs, array);
+             found = update[cs->type] = 1;
+             DBG("Changed service: %p %s", cs, path);
+             break;
+          }
+        if (!found)
+          {
+             cs = _connman_service_new(path, array);
+             update[cs->type] = 1;
+          }
+     }
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     if (update[i]) _connman_update_networks(i);
+}
+
+static void
+_connman_manager_event_property(void *data EINA_UNUSED, const Eldbus_Message 
*msg)
+{
+   Eldbus_Message_Iter *var;
+   const char *name;
+
+   if (pending_getproperties_manager) return;
+   if (!eldbus_message_arguments_get(msg, "sv", &name, &var))
+     {
+        ERR("Could not parse message %p", msg);
+        return;
+     }
+
+   _connman_manager_parse_prop_changed(name, var);
+}
+
+static Eldbus_Message *
+_connman_agent_release(const Eldbus_Service_Interface *iface EINA_UNUSED, 
const Eldbus_Message *msg)
+{
+   DBG("Agent released");
+   wireless_authenticate_cancel();
+   return eldbus_message_method_return_new(msg);
+}
+
+static Eldbus_Message *
+_connman_agent_report_error(const Eldbus_Service_Interface *iface EINA_UNUSED, 
const Eldbus_Message *msg EINA_UNUSED)
+{
+#warning FIXME
+   return NULL;
+}
+
+static Eldbus_Message *
+_connman_agent_request_browser(const Eldbus_Service_Interface *iface 
EINA_UNUSED, const Eldbus_Message *msg)
+{
+   const char *path, *url;
+   int i;
+   Connman_Service *cs;
+   Wireless_Network *wn;
+
+   if (!eldbus_message_arguments_get(msg, "ss", &path, &url))
+     {
+        ERR("Could not parse message %p", msg);
+        return NULL;
+     }
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   if (!cs) return NULL;
+   wn = eina_hash_find(connman_services_map[i], &cs);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wn, NULL);
+   wireless_authenticate_external(wn, url);
+   return NULL;
+}
+
+static Eina_Bool
+_connman_field_parse_value(Connman_Field *field, const char *key, 
Eldbus_Message_Iter *value, const char *signature)
+{
+   if (!strcmp(key, "Type"))
+     {
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 's', EINA_FALSE);
+        eldbus_message_iter_basic_get(value, &field->type);
+        return EINA_TRUE;
+     }
+
+   if (!strcmp(key, "Requirement"))
+     {
+        const char *req;
+        const char *types[] =
+        {
+           [CONNMAN_FIELD_STATE_MANDATORY] = "mandatory",
+           [CONNMAN_FIELD_STATE_OPTIONAL] = "optional",
+           [CONNMAN_FIELD_STATE_ALTERNATE] = "alternate",
+           [CONNMAN_FIELD_STATE_INFO] = "informational",
+        };
+        int i;
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 's', EINA_FALSE);
+        eldbus_message_iter_basic_get(value, &req);
+        for (i = 0; i <= CONNMAN_FIELD_STATE_INFO; i++)
+          if (!strcmp(req, types[i]))
+            {
+               field->requirement = i;
+               break;
+            }
+        return EINA_TRUE;
+     }
+
+   if (!strcmp(key, "Alternates"))
+     {
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 'a', EINA_FALSE);
+        /* ignore alternates */
+        return EINA_TRUE;
+     }
+
+   if (!strcmp(key, "Value"))
+     {
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 's', EINA_FALSE);
+        eldbus_message_iter_basic_get(value, &field->value);
+        return EINA_TRUE;
+     }
+
+   DBG("Ignored unknown argument: %s", key);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_connman_field_parse(Connman_Field *field, Eldbus_Message_Iter *value, const 
char *signature EINA_UNUSED)
+{
+   Eldbus_Message_Iter *array, *dict;
+
+   eldbus_message_iter_arguments_get(value, "a{sv}", &array);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE);
+
+   while (eldbus_message_iter_get_and_next(array, 'e', &dict))
+     {
+        Eldbus_Message_Iter *var;
+        const char *key;
+        char *sig2;
+
+        if (!eldbus_message_iter_arguments_get(dict, "sv", &key, &var))
+          return EINA_FALSE;
+        sig2 = eldbus_message_iter_signature_get(var);
+        if (!sig2)
+          return EINA_FALSE;
+
+        if (!_connman_field_parse_value(field, key, var, sig2))
+          {
+             free(sig2);
+             return EINA_FALSE;
+          }
+        free(sig2);
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_connman_dbus_dict_append_array(Eldbus_Message_Iter *array, const char *key, 
Eina_Array *val)
+{
+   Eldbus_Message_Iter *dict, *variant, *array2;
+   Eina_Stringshare *str;
+   unsigned int i;
+   Eina_Array_Iterator it;
+
+   eldbus_message_iter_arguments_append(array, "{sv}", &dict);
+   eldbus_message_iter_basic_append(dict, 's', key);
+   variant = eldbus_message_iter_container_new(dict, 'v', "as");
+   array2 = eldbus_message_iter_container_new(variant, 'a', "s");
+   EINA_ARRAY_ITER_NEXT(val, i, str, it)
+     eldbus_message_iter_basic_append(array2, 's', str ?: "");
+   eldbus_message_iter_container_close(variant, array2);
+   eldbus_message_iter_container_close(dict, variant);
+   eldbus_message_iter_container_close(array, dict);
+}
+
+static void
+_connman_dbus_dict_append_string(Eldbus_Message_Iter *array, const char *key, 
const char *val)
+{
+   Eldbus_Message_Iter *dict, *variant;
+
+   eldbus_message_iter_arguments_append(array, "{sv}", &dict);
+   eldbus_message_iter_basic_append(dict, 's', key);
+   variant = eldbus_message_iter_container_new(dict, 'v', "s");
+   eldbus_message_iter_basic_append(variant, 's', val ?: "");
+   eldbus_message_iter_container_close(dict, variant);
+   eldbus_message_iter_container_close(array, dict);
+}
+
+static void
+_connman_dbus_dict_append_bool(Eldbus_Message_Iter *array, const char *key, 
Eina_Bool val)
+{
+   Eldbus_Message_Iter *dict, *variant;
+
+   eldbus_message_iter_arguments_append(array, "{sv}", &dict);
+   eldbus_message_iter_basic_append(dict, 's', key);
+   variant = eldbus_message_iter_container_new(dict, 'v', "b");
+   eldbus_message_iter_basic_append(variant, 'b', !!val);
+   eldbus_message_iter_container_close(dict, variant);
+   eldbus_message_iter_container_close(array, dict);
+}
+
+static void
+_connman_agent_auth_send(void *data, const Eina_Array *fields)
+{
+   Eldbus_Message *reply;
+   Eldbus_Message_Iter *iter, *array;
+   const char *f, *fprev;
+   unsigned int i;
+   Eina_Array_Iterator it;
+
+   if (!fields)
+     {
+        reply = eldbus_message_error_new(data,
+                                       "net.connman.Agent.Error.Canceled",
+                                       "User canceled dialog");
+        eldbus_connection_send(dbus_conn, reply, NULL, NULL, -1);
+        return;
+     }
+   reply = eldbus_message_method_return_new(data);
+   iter = eldbus_message_iter_get(reply);
+   eldbus_message_iter_arguments_append(iter, "a{sv}", &array);
+
+   EINA_ARRAY_ITER_NEXT(fields, i, f, it)
+     {
+        if (i % 2)
+          _connman_dbus_dict_append_string(array, fprev, f);
+        else
+          fprev = f;
+     }
+   eldbus_message_iter_container_close(iter, array);
+
+   eldbus_connection_send(dbus_conn, reply, NULL, NULL, -1);
+}
+
+static Eldbus_Message *
+_connman_agent_request_input(const Eldbus_Service_Interface *iface 
EINA_UNUSED, const Eldbus_Message *msg)
+{
+   Eldbus_Message_Iter *array, *dict;
+   const char *path;
+   Eina_Array *arr = NULL;
+
+   if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &array))
+     return eldbus_message_method_return_new(msg);
+
+   /* FIXME: WISPr - net.connman.Agent.Error.LaunchBrowser */
+   while (eldbus_message_iter_get_and_next(array, 'e', &dict))
+     {
+        Eldbus_Message_Iter *var;
+        char *signature;
+        Connman_Field field = { NULL };
+
+        if (!eldbus_message_iter_arguments_get(dict, "sv", &field.name, &var))
+          goto err;
+        signature = eldbus_message_iter_signature_get(var);
+        if (!signature) goto err;
+
+        if (!_connman_field_parse(&field, var, signature))
+          {
+             free(signature);
+             goto err;
+          }
+        free(signature);
+
+        DBG("AGENT Got field:\n"
+            "\tName: %s\n"
+            "\tType: %s\n"
+            "\tRequirement: %d\n"
+            "\tAlternates: (omit array)\n"
+            "\tValue: %s",
+            field.name, field.type, field.requirement, field.value);
+
+        if (field.requirement != CONNMAN_FIELD_STATE_MANDATORY) continue;
+        if (!arr) arr = eina_array_new(1);
+        eina_array_push(arr, eina_stringshare_add(field.name));
+     }
+   wireless_authenticate(arr, _connman_agent_auth_send, 
eldbus_message_ref((Eldbus_Message *)msg));
+   array_clear(arr);
+   return NULL;
+
+err:
+   eina_array_free(arr);
+   WRN("Failed to parse msg");
+   return eldbus_message_method_return_new(msg);
+}
+
+static Eldbus_Message *
+_connman_agent_cancel(const Eldbus_Service_Interface *iface EINA_UNUSED, const 
Eldbus_Message *msg)
+{
+   Eldbus_Message *reply = eldbus_message_method_return_new(msg);
+
+   DBG("Agent canceled");
+   wireless_authenticate_cancel();
+
+   return reply;
+}
+
+static const Eldbus_Method methods[] = {
+   { "Release", NULL, NULL, _connman_agent_release, 0 },
+   {
+    "ReportError", ELDBUS_ARGS({"o", "service"}, {"s", "error"}), NULL,
+    _connman_agent_report_error, 0
+   },
+   //{
+    //"ReportPeerError", ELDBUS_ARGS({"o", "peer"}, {"s", "error"}), NULL,
+    //_connman_agent_report_peer_error, 0
+   //},
+   {
+    "RequestBrowser", ELDBUS_ARGS({"o", "service"}, {"s", "url"}), NULL,
+     _connman_agent_request_browser, 0
+   },
+   {
+    "RequestInput", ELDBUS_ARGS({"o", "service"}, {"a{sv}", "fields"}),
+    ELDBUS_ARGS({"a{sv}", ""}), _connman_agent_request_input, 0
+   },
+   //{
+    //"RequestPeerAuthorization", ELDBUS_ARGS({"o", "peer"}, {"a{sv}", 
"fields"}),
+    //ELDBUS_ARGS({"a{sv}", ""}), _connman_agent_request_peer_auth, 0
+   //},
+   { "Cancel", NULL, NULL, _connman_agent_cancel, 0 },
+   { NULL, NULL, NULL, NULL, 0 }
+};
+
+static const Eldbus_Service_Interface_Desc desc = {
+   CONNMAN_AGENT_IFACE, methods, NULL, NULL, NULL, NULL
+};
+
+static void
+_connman_start(void)
+{
+   Eldbus_Object *obj;
+   int i;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     connman_services[i] = 
eina_hash_string_superfast_new((Eina_Free_Cb)_connman_service_free);
+
+   obj = eldbus_object_get(dbus_conn, CONNMAN_BUS_NAME, "/");
+   proxy_manager = eldbus_proxy_get(obj, CONNMAN_MANAGER_IFACE);
+
+   signal_handlers = eina_list_append(signal_handlers,
+     eldbus_proxy_signal_handler_add(proxy_manager, "PropertyChanged",
+                                   _connman_manager_event_property, NULL));
+   signal_handlers = eina_list_append(signal_handlers,
+     eldbus_proxy_signal_handler_add(proxy_manager, "ServicesChanged",
+                                   _connman_manager_event_services, NULL));
+
+   pending_gettechnologies = eldbus_proxy_call(proxy_manager, 
"GetTechnologies", _connman_manager_gettechnologies,
+     NULL, -1, "");
+   pending_getproperties_manager = eldbus_proxy_call(proxy_manager, 
"GetProperties", _connman_manager_getproperties,
+     NULL, -1, "");
+
+   agent_iface = eldbus_service_interface_register(dbus_conn, 
CONNMAN_AGENT_PATH, &desc);
+   eldbus_proxy_call(proxy_manager, "RegisterAgent",
+                       _connman_manager_agent_register, NULL, -1, "o", 
CONNMAN_AGENT_PATH);
+}
+
+static void
+_connman_end(void)
+{
+   int i;
+
+   if (!proxy_manager) return;
+   eldbus_proxy_call(proxy_manager, "UnregisterAgent", NULL, NULL, -1, "o", 
CONNMAN_AGENT_PATH);
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        E_FREE_FUNC(connman_services[i], eina_hash_free);
+        if (!connman_technology[i].proxy) continue;
+        E_FREE_FUNC(connman_technology[i].proxy, _eldbus_proxy_del);
+     }
+   E_FREE_FUNC(pending_getservices, eldbus_pending_cancel);
+   E_FREE_FUNC(pending_getproperties_manager, eldbus_pending_cancel);
+   signal_handlers = eina_list_free(signal_handlers);
+
+   E_FREE_FUNC(proxy_manager, _eldbus_proxy_del);
+   E_FREE_FUNC(agent_iface, eldbus_service_object_unregister);
+}
+
+static void
+_connman_name_owner_changed(void *data EINA_UNUSED, const char *bus 
EINA_UNUSED, const char *from EINA_UNUSED, const char *to)
+{
+   if (to[0])
+     _connman_start();
+   else
+     _connman_end();
+}
+
+EINTERN void
+connman_init(void)
+{
+   int i;
+
+   if (_connman_log_dom > -1) return;
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     connman_technology[i].type = -1;
+   eldbus_name_owner_changed_callback_add(dbus_conn, CONNMAN_BUS_NAME,
+                                         _connman_name_owner_changed,
+                                         NULL, EINA_TRUE);
+   _connman_log_dom = eina_log_domain_register("wireless.connman", 
EINA_COLOR_ORANGE);
+}
+
+EINTERN void
+connman_shutdown(void)
+{
+   int i;
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        E_FREE_FUNC(connman_services_map[i], eina_hash_free);
+        E_FREE(connman_current_connection[i]);
+        connman_current_service[i] = NULL;
+     }
+   _connman_end();
+   eldbus_name_owner_changed_callback_del(dbus_conn, CONNMAN_BUS_NAME, 
_connman_name_owner_changed, NULL);
+   eina_log_domain_unregister(_connman_log_dom);
+   _connman_log_dom = -1;
+}
+
+EINTERN void
+connman_technology_enabled_set(Wireless_Service_Type type, Eina_Bool state)
+{
+   Eldbus_Message_Iter *main_iter, *var;
+   Eldbus_Message *msg;
+
+   EINA_SAFETY_ON_NULL_RETURN(connman_technology[type].proxy);
+   msg = eldbus_proxy_method_call_new(connman_technology[type].proxy, 
"SetProperty");
+   main_iter = eldbus_message_iter_get(msg);
+   eldbus_message_iter_basic_append(main_iter, 's', "Powered");
+   var = eldbus_message_iter_container_new(main_iter, 'v', "b");
+   eldbus_message_iter_basic_append(var, 'b', state);
+   eldbus_message_iter_container_close(main_iter, var);
+
+   eldbus_proxy_send(connman_technology[type].proxy, msg, NULL, NULL, -1);
+}
+
+static void
+_connman_service_edit_timeservers_cb(void *data EINA_UNUSED, const 
Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *name, *text;
+   /* FIXME */
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not set properties. %s: %s", name, text);
+     }
+}
+
+static void
+_connman_service_edit_nameservers_cb(void *data EINA_UNUSED, const 
Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *name, *text;
+   /* FIXME */
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not set properties. %s: %s", name, text);
+     }
+}
+
+static void
+_connman_service_edit_domains_cb(void *data EINA_UNUSED, const Eldbus_Message 
*msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *name, *text;
+   /* FIXME */
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not set properties. %s: %s", name, text);
+     }
+}
+
+static void
+_connman_service_edit_proxy_cb(void *data EINA_UNUSED, const Eldbus_Message 
*msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *name, *text;
+   /* FIXME */
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not set properties. %s: %s", name, text);
+     }
+}
+
+static void
+_connman_service_edit_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, 
Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *name, *text;
+   /* FIXME */
+   if (eldbus_message_error_get(msg, &name, &text))
+     {
+        ERR("Could not set properties. %s: %s", name, text);
+     }
+}
+
+static void
+_connman_service_remove_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, 
Eldbus_Pending *pending EINA_UNUSED)
+{
+   const char *name, *text;
+
+   if (eldbus_message_error_get(msg, &name, &text))
+     ERR("Could not remove service. %s: %s", name, text);
+}
+
+EINTERN void
+connman_service_edit(const char *path, Wireless_Connection *wc)
+{
+   int i;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *variant, *array;
+   Connman_Service *cs = NULL;
+   const char *prop[] =
+   {
+      "IPv4.Configuration",
+      "IPv6.Configuration",
+   };
+   const char *method[] =
+   {
+      "off",
+      "manual",
+      "dhcp",
+      "fixed",
+   };
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   EINA_SAFETY_ON_NULL_RETURN(cs);
+
+   msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty");
+   iter = eldbus_message_iter_get(msg);
+   eldbus_message_iter_basic_append(iter, 's', prop[cs->ipv6]);
+   variant = eldbus_message_iter_container_new(iter, 'v', "a{sv}");
+   eldbus_message_iter_arguments_append(variant, "a{sv}", &array);
+   _connman_dbus_dict_append_string(array, "Method", method[wc->method]);
+   _connman_dbus_dict_append_string(array, "Address", wc->address);
+   _connman_dbus_dict_append_string(array, "Gateway", wc->gateway);
+   if (wc->ipv6)
+     {
+        const char *privacy[] =
+        {
+           [WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED] = "disabled",
+           [WIRELESS_NETWORK_IPV6_PRIVACY_ENABLED] = "enabled",
+           [WIRELESS_NETWORK_IPV6_PRIVACY_PREFERRED] = "preferred",
+        };
+        _connman_dbus_dict_append_string(array, "PrefixLength", 
wc->ip.v6.prefixlength);
+        if (wc->method == WIRELESS_NETWORK_IPV6_METHOD_AUTO)
+          _connman_dbus_dict_append_string(array, "Privacy", 
privacy[wc->ip.v6.privacy]);
+     }
+   else
+     _connman_dbus_dict_append_string(array, "Netmask", wc->ip.v4.netmask);
+   eldbus_message_iter_container_close(variant, array);
+   eldbus_message_iter_container_close(iter, variant);
+
+   eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_cb, NULL, -1);
+}
+
+EINTERN void
+connman_service_edit_proxy(const char *path, Wireless_Connection *wc)
+{
+   int i;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *variant, *array;
+   Connman_Service *cs = NULL;
+   const char *method[] =
+   {
+      "direct",
+      "manual",
+      "auto",
+   };
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   EINA_SAFETY_ON_NULL_RETURN(cs);
+
+   msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty");
+   iter = eldbus_message_iter_get(msg);
+   eldbus_message_iter_basic_append(iter, 's', "Proxy");
+   variant = eldbus_message_iter_container_new(iter, 'v', "a{sv}");
+   eldbus_message_iter_arguments_append(variant, "a{sv}", &array);
+   _connman_dbus_dict_append_string(array, "Method", method[wc->proxy_type]);
+   switch (wc->proxy_type)
+     {
+      case WIRELESS_PROXY_TYPE_DIRECT: break;
+      case WIRELESS_PROXY_TYPE_MANUAL:
+        _connman_dbus_dict_append_array(array, "Servers", wc->proxy_servers);
+        _connman_dbus_dict_append_array(array, "Excludes", wc->proxy_excludes);
+        break;
+      case WIRELESS_PROXY_TYPE_AUTO:
+        _connman_dbus_dict_append_string(array, "Address", wc->proxy_url);
+        break;
+     }
+   eldbus_message_iter_container_close(variant, array);
+   eldbus_message_iter_container_close(iter, variant);
+
+   eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_proxy_cb, NULL, -1);
+}
+
+EINTERN void
+connman_service_edit_domains(const char *path, Wireless_Connection *wc)
+{
+   int i;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter;
+   Connman_Service *cs = NULL;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   EINA_SAFETY_ON_NULL_RETURN(cs);
+
+   msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty");
+   iter = eldbus_message_iter_get(msg);
+   _connman_dbus_dict_append_array(iter, "Domains.Configuration", 
wc->domain_servers);
+
+   eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_domains_cb, NULL, 
-1);
+}
+
+EINTERN void
+connman_service_edit_nameservers(const char *path, Wireless_Connection *wc)
+{
+   int i;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter;
+   Connman_Service *cs = NULL;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   EINA_SAFETY_ON_NULL_RETURN(cs);
+
+   msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty");
+   iter = eldbus_message_iter_get(msg);
+   _connman_dbus_dict_append_array(iter, "Nameservers.Configuration", 
wc->name_servers);
+
+   eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_nameservers_cb, 
NULL, -1);
+}
+
+EINTERN void
+connman_service_edit_timeservers(const char *path, Wireless_Connection *wc)
+{
+   int i;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter;
+   Connman_Service *cs = NULL;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   EINA_SAFETY_ON_NULL_RETURN(cs);
+
+   msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty");
+   iter = eldbus_message_iter_get(msg);
+   _connman_dbus_dict_append_array(iter, "Timeservers.Configuration", 
wc->time_servers);
+
+   eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_timeservers_cb, 
NULL, -1);
+}
+
+EINTERN void
+connman_service_remove(const char *path)
+{
+   int i;
+   Eldbus_Message *msg;
+   Connman_Service *cs = NULL;
+
+   CONNMAN_SERVICE_TYPE_ITER(i)
+     {
+        cs = eina_hash_find(connman_services[i], path);
+        if (cs) break;
+     }
+   EINA_SAFETY_ON_NULL_RETURN(cs);
+
+   msg = eldbus_proxy_method_call_new(cs->proxy, "Remove");
+   eldbus_proxy_send(cs->proxy, msg, _connman_service_remove_cb, NULL, -1);
+}
+
+EINTERN void
+connman_airplane_mode_set(Eina_Bool set)
+{
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter;
+
+   msg = eldbus_proxy_method_call_new(proxy_manager, "SetProperty");
+   iter = eldbus_message_iter_get(msg);
+   _connman_dbus_dict_append_bool(iter, "OfflineMode", set);
+   eldbus_proxy_send(proxy_manager, msg, NULL, NULL, -1);
+}
diff --git a/src/modules/wireless/e-module-wireless.edj 
b/src/modules/wireless/e-module-wireless.edj
new file mode 100644
index 0000000..2b7ed6f
Binary files /dev/null and b/src/modules/wireless/e-module-wireless.edj differ
diff --git a/src/modules/wireless/mod.c b/src/modules/wireless/mod.c
new file mode 100644
index 0000000..3934ef6
--- /dev/null
+++ b/src/modules/wireless/mod.c
@@ -0,0 +1,33 @@
+#include "e.h"
+
+EINTERN void wireless_gadget_init(void);
+EINTERN void wireless_gadget_shutdown(void);
+
+EINTERN void connman_init(void);
+EINTERN void connman_shutdown(void);
+
+EINTERN Eldbus_Connection *dbus_conn;
+
+E_API E_Module_Api e_modapi =
+{
+   E_MODULE_API_VERSION,
+   "Wireless"
+};
+
+E_API void *
+e_modapi_init(E_Module *m)
+{
+   dbus_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
+   connman_init();
+   wireless_gadget_init();
+   return m;
+}
+
+E_API int
+e_modapi_shutdown(E_Module *m EINA_UNUSED)
+{
+   wireless_gadget_shutdown();
+   connman_shutdown();
+   E_FREE_FUNC(dbus_conn, eldbus_connection_unref);
+   return 1;
+}
diff --git a/src/modules/wireless/module.desktop.in 
b/src/modules/wireless/module.desktop.in
new file mode 100644
index 0000000..0efa788
--- /dev/null
+++ b/src/modules/wireless/module.desktop.in
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Link
+Name=Wireless
+GenericName=Wireless
+Comment=Manage wifi connections
+Icon=e-module-wireless
+X-Enlightenment-ModuleType=system
diff --git a/src/modules/wireless/wireless.c b/src/modules/wireless/wireless.c
new file mode 100644
index 0000000..4102653
--- /dev/null
+++ b/src/modules/wireless/wireless.c
@@ -0,0 +1,1476 @@
+#include "wireless.h"
+
+
+/* FIXME */
+void connman_technology_enabled_set(Wireless_Service_Type type, Eina_Bool 
state);
+
+static const char *wireless_theme_groups[] =
+{
+  [WIRELESS_SERVICE_TYPE_ETHERNET] = "e/gadget/wireless/ethernet",
+  [WIRELESS_SERVICE_TYPE_WIFI] = "e/gadget/wireless/wifi",
+  [WIRELESS_SERVICE_TYPE_BLUETOOTH] = "e/gadget/wireless/bluetooth",
+  [WIRELESS_SERVICE_TYPE_CELLULAR] = "e/gadget/wireless/cellular",
+};
+
+static const char *wireless_ipv4_methods[] =
+{
+   N_("Disabled"),
+   N_("Manual"),
+   "DHCP",
+   N_("Fixed"),
+};
+
+static const char *wireless_ipv6_methods[] =
+{
+   N_("Off"),
+   N_("Manual"),
+   N_("Auto"),
+   "6to4",
+   N_("Fixed"),
+};
+
+static const char *wireless_proxy_methods[] =
+{
+   N_("Direct"),
+   N_("Manual"),
+   N_("Auto"),
+};
+
+typedef struct Instance
+{
+   int id;
+   E_Gadget_Site_Orient orient;
+   Evas_Object *box;
+   Evas_Object *icon[WIRELESS_SERVICE_TYPE_LAST];
+
+   Eina_Bool popup;
+
+   struct
+   {
+      Evas_Object *error;
+      Evas_Object *address;
+      Evas_Object *method;
+      Evas_Object *signal;
+      Wireless_Service_Type type;
+   } tooltip;
+} Instance;
+
+typedef struct Wireless_Auth_Popup
+{
+   Evas_Object *popup;
+   Wireless_Auth_Cb cb;
+   void *data;
+   Eina_Bool sent : 1;
+} Wireless_Auth_Popup;
+
+static Eina_Array *wireless_networks;
+static Wireless_Connection *wireless_current[WIRELESS_SERVICE_TYPE_LAST];
+static Eina_Bool wireless_type_enabled[WIRELESS_SERVICE_TYPE_LAST];
+static Eina_Bool wireless_type_available[WIRELESS_SERVICE_TYPE_LAST];
+static Eina_List *instances;
+static Eina_List *wireless_auth_pending;
+static Wireless_Auth_Popup *wireless_auth_popup;
+static Eina_Bool wireless_offline;
+static Evas_Object *wireless_edit_popup;
+static Wireless_Connection *wireless_edit[2];
+static unsigned int wireless_network_count[WIRELESS_SERVICE_TYPE_LAST];
+
+static struct
+{
+   Evas_Object *popup;
+   Evas_Object *box;
+   Evas_Object *content;
+   Eina_Stringshare *name_servers;
+   Eina_Stringshare *time_servers;
+   Eina_Stringshare *domain_servers;
+   Eina_Stringshare *proxy_servers;
+   Eina_Stringshare *proxy_excludes;
+   Eina_Hash *items;
+   Eina_List *entries;
+   Wireless_Service_Type type;
+} wireless_popup;
+
+static Eina_Bool auth_popup;
+
+#undef DBG
+#undef INF
+#undef WRN
+#undef ERR
+
+#define DBG(...) EINA_LOG_DOM_DBG(_wireless_gadget_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_wireless_gadget_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_wireless_gadget_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_wireless_gadget_log_dom, __VA_ARGS__)
+static int _wireless_gadget_log_dom = -1;
+
+static void
+_wifi_icon_signal(Evas_Object *icon, int state, int strength)
+{
+   Edje_Message_Int_Set *msg;
+
+   DBG("icon msg: %d %d%%", state, strength);
+   msg = alloca(sizeof(Edje_Message_Int_Set) + sizeof(int));
+   msg->count = 2;
+   msg->val[0] = state;
+   msg->val[1] = strength;
+   edje_object_message_send(elm_layout_edje_get(icon), EDJE_MESSAGE_INT_SET, 
1, msg);
+}
+
+static void
+_wifi_icon_init(Evas_Object *icon, Wireless_Network *wn, int type)
+{
+   int state = 0, strength = 0;
+
+   if (wn)
+     {
+        state = wn->state;
+        strength = wn->strength;
+     }
+   _wifi_icon_signal(icon, state, strength);
+
+   if (!wn)
+     {
+        if (wireless_type_available[type])
+          elm_object_signal_emit(icon, "e,state,default", "e");
+        else
+          elm_object_signal_emit(icon, "e,state,error", "e");
+        elm_object_signal_emit(icon, "e,state,unsecured", "e");
+        return;
+     }
+   if (wn->state == WIRELESS_NETWORK_STATE_FAILURE)
+     {
+        elm_object_signal_emit(icon, "e,state,error", "e");
+        return;
+     }
+   elm_object_signal_emit(icon, "e,state,default", "e");
+   switch (wn->type)
+     {
+      case WIRELESS_SERVICE_TYPE_WIFI:
+        if (wn->security > WIRELESS_NETWORK_SECURITY_WEP)
+          elm_object_signal_emit(icon, "e,state,secure", "e");
+        else if (wn->security == WIRELESS_NETWORK_SECURITY_WEP)
+          elm_object_signal_emit(icon, "e,state,insecure", "e");
+        else if (!wn->security)
+          elm_object_signal_emit(icon, "e,state,unsecured", "e");
+        break;
+      default: break;
+     }
+}
+
+static void
+_wireless_popup_toggle(void *data EINA_UNUSED, Evas_Object *obj, void 
*event_info EINA_UNUSED)
+{
+   connman_technology_enabled_set(wireless_popup.type, 
elm_check_state_get(obj));
+}
+
+static void
+_wireless_popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Instance *inst = data;
+   inst->popup = 0;
+   E_FREE_FUNC(wireless_popup.items, eina_hash_free);
+   E_FREE_FUNC(wireless_popup.entries, eina_list_free);
+   eina_stringshare_replace(&wireless_popup.proxy_servers, NULL);
+   eina_stringshare_replace(&wireless_popup.proxy_excludes, NULL);
+   wireless_popup.box = NULL;
+   wireless_popup.content = NULL;
+   wireless_popup.popup = NULL;
+   wireless_popup.type = -1;
+}
+
+static void
+_wireless_edit_basic_entries_update(void)
+{
+   Eina_List *l;
+   Evas_Object *ent;
+   Eina_Bool disabled;
+
+   if (wireless_edit[1]->ipv6)
+     disabled = wireless_edit[1]->method != 
WIRELESS_NETWORK_IPV6_METHOD_MANUAL;
+   else
+     disabled = wireless_edit[1]->method != 
WIRELESS_NETWORK_IPV4_METHOD_MANUAL;
+   EINA_LIST_FOREACH(wireless_popup.entries, l, ent)
+     elm_object_disabled_set(ent, disabled);
+}
+
+static Evas_Object *
+_wireless_popup_table_entry_row(Evas_Object *tb, const char *name, 
Evas_Smart_Cb cb, void *data, int *row)
+{
+   Evas_Object *fr, *entry;
+
+   fr = elm_frame_add(tb);
+   evas_object_show(fr);
+   E_EXPAND(fr);
+   E_FILL(fr);
+   elm_object_text_set(fr, name);
+   elm_table_pack(tb, fr, 0, *row, 2, 2);
+   *row += 2;
+
+   entry = elm_entry_add(tb);
+   evas_object_show(entry);
+   elm_entry_single_line_set(entry, 1);
+   elm_entry_scrollable_set(entry, 1);
+   evas_object_data_set(entry, "table", tb);
+   evas_object_smart_callback_add(entry, "activated", cb, data);
+   elm_object_content_set(fr, entry);
+   return entry;
+}
+
+static void
+_wireless_edit_entry_changed(void *data, Evas_Object *obj, void *event_info 
EINA_UNUSED)
+{
+   Eina_Stringshare **str = data;
+
+   eina_stringshare_replace(str, elm_entry_entry_get(obj));
+}
+
+static void
+_wireless_gadget_edit_array_entry(Eina_Array *arr, Eina_Stringshare **ptr)
+{
+   Eina_Stringshare *str;
+   unsigned int i;
+   Eina_Array_Iterator it;
+   Eina_Strbuf *buf;
+
+   if (!arr) return;
+   buf = eina_strbuf_new();
+   EINA_ARRAY_ITER_NEXT(arr, i, str, it)
+     {
+        if (eina_strbuf_length_get(buf)) eina_strbuf_append(buf, ", ");
+        eina_strbuf_append(buf, str);
+     }
+   eina_stringshare_replace(ptr, eina_strbuf_string_get(buf));
+   eina_strbuf_free(buf);
+}
+
+static void
+_wireless_gadget_edit_proxy_method_update(void)
+{
+   Evas_Object *ent, *tb = wireless_popup.content;
+   int row = 1;
+   Wireless_Connection *wc = wireless_edit[1];
+
+   evas_object_del(elm_table_child_get(wireless_popup.content, 0, 1));
+   evas_object_del(elm_table_child_get(wireless_popup.content, 0, 3));
+   evas_object_del(elm_table_child_get(wireless_popup.content, 0, 5));
+   switch (wc->proxy_type)
+     {
+      case WIRELESS_PROXY_TYPE_DIRECT:
+        _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+        evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 1));
+        _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+        evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 3));
+        _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+        evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 5));
+        break;
+      case WIRELESS_PROXY_TYPE_MANUAL:
+        ent = _wireless_popup_table_entry_row(tb, _("Proxy Servers"), NULL, 
NULL, &row);
+        elm_entry_entry_set(ent, wireless_popup.proxy_servers);
+        evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_popup.proxy_servers);
+        ent = _wireless_popup_table_entry_row(tb, _("Proxy Excludes"), NULL, 
NULL, &row);
+        elm_entry_entry_set(ent, wireless_popup.proxy_excludes);
+        evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_popup.proxy_excludes);
+        _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+        evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 5));
+        break;
+      case WIRELESS_PROXY_TYPE_AUTO:
+        ent = _wireless_popup_table_entry_row(tb, _("Proxy Address"), NULL, 
NULL, &row);
+        elm_entry_entry_set(ent, wc->proxy_url);
+        evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_edit[1]->address);
+        _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+        evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 3));
+        _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+        evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 5));
+        break;
+     }
+}
+
+static void
+_wireless_gadget_edit_proxy_method(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info)
+{
+   wireless_edit[1]->proxy_type = 
(intptr_t)elm_object_item_data_get(event_info);
+   _wireless_gadget_edit_proxy_method_update();
+}
+
+static void
+_wireless_gadget_edit_method(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info)
+{
+   wireless_edit[1]->method = (intptr_t)elm_object_item_data_get(event_info);
+   _wireless_edit_basic_entries_update();
+}
+
+static void
+_wireless_gadget_edit_method_open(void *data EINA_UNUSED, Evas_Object *obj, 
void *event_info EINA_UNUSED)
+{
+   int i, fixed;
+   const char **methods;
+
+   elm_hoversel_clear(obj);
+   evas_object_layer_set(obj, E_LAYER_MENU);
+   if (wireless_edit[1]->ipv6)
+     {
+        fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED;
+        methods = wireless_ipv6_methods;
+     }
+   else
+     {
+        fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED;
+        methods = wireless_ipv4_methods;
+     }
+   for (i = 0; i < fixed; i++)
+     {
+        if ((int)wireless_edit[1]->method != i)
+          elm_hoversel_item_add(obj, methods[i], NULL, ELM_ICON_NONE, NULL, 
(intptr_t*)(long)i);
+     }
+}
+
+static void
+_wireless_edit_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   int i;
+
+   wireless_popup.entries = eina_list_free(wireless_popup.entries);
+   eina_stringshare_del(wireless_edit[0]->wn->path);
+   free(wireless_edit[0]->wn);
+   for (i = 0; i <= 1; i++)
+     {
+        eina_stringshare_del(wireless_edit[i]->address);
+        eina_stringshare_del(wireless_edit[i]->gateway);
+        if (wireless_edit[i]->ipv6)
+          eina_stringshare_del(wireless_edit[i]->ip.v6.prefixlength);
+        else
+          eina_stringshare_del(wireless_edit[i]->ip.v4.netmask);
+        eina_stringshare_del(wireless_edit[i]->proxy_url);
+        array_clear(wireless_edit[i]->proxy_excludes);
+        array_clear(wireless_edit[i]->proxy_servers);
+        E_FREE(wireless_edit[i]);
+     }
+   wireless_edit_popup = NULL;
+}
+
+static Eina_Array *
+string_to_array(const char *str)
+{
+   const char *p = str;
+   Eina_Array *arr;
+
+   arr = eina_array_new(1);
+   do
+     {
+        const char *start, *end;
+
+        start = p;
+        p = strchr(p, ',');
+        if (!p) break;
+        end = p - 1;
+        while (isspace(start[0])) start++;
+        while (isspace(end[0])) end--;
+        end++;
+
+        if (start == end) break;
+        eina_array_push(arr, eina_stringshare_add_length(start, end - start));
+        p++;
+     } while (p[0]);
+   return arr;
+}
+
+static Eina_Bool
+_wireless_array_notequal(Eina_Array *a, Eina_Array *b)
+{
+   unsigned int i;
+
+   if ((!!a) != (!!b)) return EINA_TRUE;
+   if (eina_array_count(a) != eina_array_count(b)) return EINA_TRUE;
+   for (i = 0; i < eina_array_count(a); i++)
+     if (eina_array_data_get(a, i) != eina_array_data_get(b, i)) return 
EINA_TRUE;
+   return EINA_FALSE;
+}
+
+static void
+_wireless_edit_send()
+{
+   Eina_Bool basic = EINA_FALSE, proxy = EINA_FALSE;
+
+   EINTERN void connman_service_edit(const char *path, Wireless_Connection 
*wc);
+   EINTERN void connman_service_edit_proxy(const char *path, 
Wireless_Connection *wc);
+   EINTERN void connman_service_edit_domains(const char *path, 
Wireless_Connection *wc);
+   EINTERN void connman_service_edit_nameservers(const char *path, 
Wireless_Connection *wc);
+   EINTERN void connman_service_edit_timeservers(const char *path, 
Wireless_Connection *wc);
+
+   if (wireless_edit[0]->method == wireless_edit[1]->method)
+     {
+        if (wireless_edit[1]->ipv6)
+          switch (wireless_edit[1]->method)
+            {
+             case WIRELESS_NETWORK_IPV6_METHOD_AUTO:
+               basic = wireless_edit[0]->ip.v6.privacy != 
wireless_edit[1]->ip.v6.privacy;
+               break;
+             case WIRELESS_NETWORK_IPV6_METHOD_MANUAL:
+               basic = wireless_edit[0]->address != wireless_edit[1]->address;
+               if (basic) break;
+               basic = wireless_edit[0]->gateway != wireless_edit[1]->gateway;
+               if (basic) break;
+               basic = wireless_edit[0]->ip.v6.prefixlength != 
wireless_edit[1]->ip.v6.prefixlength;
+               break;
+             default: break;
+            }
+        else
+          switch (wireless_edit[1]->method)
+            {
+             case WIRELESS_NETWORK_IPV4_METHOD_MANUAL:
+               basic = wireless_edit[0]->address != wireless_edit[1]->address;
+               if (basic) break;
+               basic = wireless_edit[0]->gateway != wireless_edit[1]->gateway;
+               if (basic) break;
+               basic = wireless_edit[0]->ip.v4.netmask != 
wireless_edit[1]->ip.v4.netmask;
+               break;
+             default: break;
+            }
+     }
+   else
+     basic = EINA_TRUE;
+
+   if (basic)
+     connman_service_edit(wireless_edit[1]->wn->path, wireless_edit[1]);
+
+   if (wireless_edit[1]->proxy_type == WIRELESS_PROXY_TYPE_MANUAL)
+     {
+        array_clear(wireless_edit[1]->proxy_servers);
+        array_clear(wireless_edit[1]->proxy_excludes);
+        if (wireless_popup.proxy_servers)
+          wireless_edit[1]->proxy_servers = 
string_to_array(wireless_popup.proxy_servers);
+        if (wireless_popup.proxy_excludes)
+          wireless_edit[1]->proxy_excludes = 
string_to_array(wireless_popup.proxy_excludes);
+     }
+   if (wireless_edit[0]->proxy_type == wireless_edit[1]->proxy_type)
+     {
+        switch (wireless_edit[0]->proxy_type)
+          {
+            case WIRELESS_PROXY_TYPE_MANUAL:
+              proxy = _wireless_array_notequal(wireless_edit[0]->proxy_servers,
+                wireless_edit[1]->proxy_servers);
+              if (proxy) break;
+              proxy = 
_wireless_array_notequal(wireless_edit[0]->proxy_excludes,
+                wireless_edit[1]->proxy_excludes);
+              break;
+            case WIRELESS_PROXY_TYPE_AUTO:
+              proxy = wireless_edit[0]->proxy_url != 
wireless_edit[1]->proxy_url;
+              break;
+            break;
+           default: break;
+          }
+        
+     }
+   else
+     proxy = EINA_TRUE;
+   if (proxy)
+     connman_service_edit_proxy(wireless_edit[1]->wn->path, wireless_edit[1]);
+
+   array_clear(wireless_edit[1]->domain_servers);
+   if (wireless_popup.domain_servers)
+     wireless_edit[1]->domain_servers = 
string_to_array(wireless_popup.domain_servers);
+   array_clear(wireless_edit[1]->name_servers);
+   if (wireless_popup.name_servers)
+     wireless_edit[1]->name_servers = 
string_to_array(wireless_popup.name_servers);
+   array_clear(wireless_edit[1]->name_servers);
+   if (wireless_popup.name_servers)
+     wireless_edit[1]->name_servers = 
string_to_array(wireless_popup.name_servers);
+
+   if (_wireless_array_notequal(wireless_edit[0]->domain_servers, 
wireless_edit[1]->domain_servers))
+     connman_service_edit_domains(wireless_edit[1]->wn->path, 
wireless_edit[1]);
+   if (_wireless_array_notequal(wireless_edit[0]->name_servers, 
wireless_edit[1]->name_servers))
+     connman_service_edit_nameservers(wireless_edit[1]->wn->path, 
wireless_edit[1]);
+   if (_wireless_array_notequal(wireless_edit[0]->time_servers, 
wireless_edit[1]->time_servers))
+     connman_service_edit_timeservers(wireless_edit[1]->wn->path, 
wireless_edit[1]);
+}
+
+static void
+_wireless_edit_send_button()
+{
+   e_comp_object_util_autoclose(NULL, NULL, NULL, NULL);
+   _wireless_edit_send();
+}
+
+static void
+_wireless_edit_remove()
+{
+   EINTERN void connman_service_remove(const char *path);
+   e_comp_object_util_autoclose(NULL, NULL, NULL, NULL);
+   connman_service_remove(wireless_edit[1]->wn->path);
+}
+
+static Eina_Bool
+_wireless_edit_key(void *d EINA_UNUSED, Ecore_Event_Key *ev)
+{
+   if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
+     {
+        _wireless_edit_send();
+        return EINA_FALSE;
+     }
+   return strcmp(ev->key, "Escape");
+}
+
+static void
+_wireless_gadget_edit_proxy_method_open(void *data EINA_UNUSED, Evas_Object 
*obj, void *event_info EINA_UNUSED)
+{
+   int i;
+
+   elm_hoversel_clear(obj);
+   for (i = 0; i <= WIRELESS_PROXY_TYPE_AUTO; i++)
+     {
+        if ((int)wireless_edit[1]->proxy_type != i)
+          elm_hoversel_item_add(obj, wireless_proxy_methods[i], NULL, 
ELM_ICON_NONE, NULL, (intptr_t*)(long)i);
+     }
+}
+
+static void
+_wireless_gadget_edit_proxy(void)
+{
+   Evas_Object *tb, *fr, *hoversel;
+   int row = 0;
+   Wireless_Connection *wc = wireless_edit[1];
+
+   wireless_popup.content = tb = elm_table_add(wireless_popup.popup);
+   E_FILL(tb);
+   E_EXPAND(tb);
+   evas_object_show(tb);
+   elm_box_pack_end(wireless_popup.box, tb);
+
+   fr = elm_frame_add(tb);
+   E_EXPAND(fr);
+   E_FILL(fr);
+   evas_object_show(fr);
+   elm_object_text_set(fr, _("Proxy Type"));
+   elm_table_pack(tb, fr, 0, row++, 2, 1);
+
+   hoversel = elm_hoversel_add(tb);
+   elm_hoversel_hover_parent_set(hoversel, wireless_popup.popup);
+   elm_hoversel_auto_update_set(hoversel, 1);
+   evas_object_show(hoversel);
+   elm_object_content_set(fr, hoversel);
+   evas_object_smart_callback_add(hoversel, "selected", 
_wireless_gadget_edit_proxy_method, NULL);
+   evas_object_smart_callback_add(hoversel, "clicked", 
_wireless_gadget_edit_proxy_method_open, NULL);
+   elm_object_text_set(hoversel, wireless_proxy_methods[wc->proxy_type]);
+   _wireless_gadget_edit_proxy_method_update();
+}
+
+static void
+_wireless_gadget_edit_dnstime(void)
+{
+   Evas_Object *tb, *ent;
+   int row = 0;
+
+   wireless_popup.content = tb = elm_table_add(wireless_popup.popup);
+   E_FILL(tb);
+   E_EXPAND(tb);
+   evas_object_show(tb);
+   elm_box_pack_end(wireless_popup.box, tb);
+
+   ent = _wireless_popup_table_entry_row(tb, _("Nameservers"), NULL, NULL, 
&row);
+   elm_entry_entry_set(ent, wireless_popup.name_servers);
+   evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_popup.name_servers);
+
+   ent = _wireless_popup_table_entry_row(tb, _("Timeservers"), NULL, NULL, 
&row);
+   elm_entry_entry_set(ent, wireless_popup.time_servers);
+   evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_popup.time_servers);
+
+   ent = _wireless_popup_table_entry_row(tb, _("Search Domains"), NULL, NULL, 
&row);
+   elm_entry_entry_set(ent, wireless_popup.domain_servers);
+   evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_popup.domain_servers);
+
+   _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row);
+   evas_object_hide(elm_table_child_get(tb, 0, 6));
+}
+
+static Evas_Object *
+_wireless_gadget_edit_basic(void)
+{
+   Evas_Object *tb, *fr, *hoversel, *ent, *entry;
+   Eina_Bool disabled;
+   int row = 0, fixed;
+   const char **methods;
+   Wireless_Connection *wc = wireless_edit[1];
+
+   wireless_popup.content = tb = elm_table_add(wireless_popup.box);
+   E_FILL(tb);
+   E_EXPAND(tb);
+   evas_object_show(tb);
+   elm_box_pack_end(wireless_popup.box, tb);
+
+   fr = elm_frame_add(tb);
+   E_EXPAND(fr);
+   E_FILL(fr);
+   evas_object_show(fr);
+   elm_object_text_set(fr, _("Method"));
+   elm_table_pack(tb, fr, 0, row++, 2, 1);
+
+   hoversel = elm_hoversel_add(tb);
+   elm_hoversel_hover_parent_set(hoversel, wireless_popup.popup);
+   elm_hoversel_auto_update_set(hoversel, 1);
+   evas_object_show(hoversel);
+   elm_object_content_set(fr, hoversel);
+   evas_object_smart_callback_add(hoversel, "selected", 
_wireless_gadget_edit_method, NULL);
+   if (wc->ipv6)
+     {
+        fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED;
+        methods = wireless_ipv6_methods;
+     }
+   else
+     {
+        fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED;
+        methods = wireless_ipv4_methods;
+     }
+   disabled = (int)wc->method == fixed;
+   elm_object_disabled_set(hoversel, disabled);
+   if (disabled)
+     elm_hoversel_item_add(hoversel, _("Fixed"), NULL, ELM_ICON_NONE, NULL, 
NULL);
+   else
+     {
+        elm_object_text_set(hoversel, methods[wc->method]);
+        evas_object_smart_callback_add(hoversel, "clicked", 
_wireless_gadget_edit_method_open, NULL);
+     }
+   
+   ent = entry = _wireless_popup_table_entry_row(tb, _("Address"), NULL, NULL, 
&row);
+   elm_object_disabled_set(ent, disabled);
+   wireless_popup.entries = eina_list_append(wireless_popup.entries, ent);
+   elm_entry_entry_set(ent, wc->address);
+   evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_edit[1]->address);
+   if (wc->ipv6)
+     {
+        ent = _wireless_popup_table_entry_row(tb, _("PrefixLength"), NULL, 
NULL, &row);
+        elm_entry_entry_set(ent, wc->ip.v6.prefixlength);
+        evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_edit[1]->ip.v6.prefixlength);
+     }
+   else
+     {
+        ent = _wireless_popup_table_entry_row(tb, _("Netmask"), NULL, NULL, 
&row);
+        elm_entry_entry_set(ent, wc->ip.v4.netmask);
+        evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_edit[1]->ip.v4.netmask);
+     }
+   elm_object_disabled_set(ent, disabled);
+   wireless_popup.entries = eina_list_append(wireless_popup.entries, ent);
+   ent = _wireless_popup_table_entry_row(tb, _("Gateway"), NULL, NULL, &row);
+   elm_entry_entry_set(ent, wc->gateway);
+   elm_object_disabled_set(ent, disabled);
+   evas_object_smart_callback_add(ent, "changed,user", 
_wireless_edit_entry_changed, &wireless_edit[1]->gateway);
+   wireless_popup.entries = eina_list_append(wireless_popup.entries, ent);
+   _wireless_edit_basic_entries_update();
+
+   return entry;
+}
+
+static void
+_wireless_gadget_edit_select_pre(void)
+{
+   elm_box_unpack(wireless_popup.box, wireless_popup.content);
+   evas_object_del(wireless_popup.content);
+   wireless_popup.entries = eina_list_free(wireless_popup.entries);
+}
+
+static void
+_wireless_gadget_edit_select_basic(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   _wireless_gadget_edit_select_pre();
+   _wireless_gadget_edit_basic();
+}
+
+static void
+_wireless_gadget_edit_select_proxy(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   _wireless_gadget_edit_select_pre();
+   _wireless_gadget_edit_proxy();
+}
+
+static void
+_wireless_gadget_edit_select_dnstime(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   _wireless_gadget_edit_select_pre();
+   _wireless_gadget_edit_dnstime();
+}
+
+static void
+_wireless_gadget_edit(int type)
+{
+   Evas_Object *popup, *entry, *box1, *box, *list, *lbl, *bt;
+   Elm_Object_Item *it;
+   Eina_Bool disabled;
+   int i;
+   char buf[1024] = {0};
+   Wireless_Connection *wc = wireless_current[type];
+   Wireless_Network *wn;
+
+   if (!wc) return;
+   wireless_edit[0] = E_NEW(Wireless_Connection, 1);
+   wireless_edit[1] = E_NEW(Wireless_Connection, 1);
+   wn = E_NEW(Wireless_Network, 1);
+   wn->path = eina_stringshare_ref(wc->wn->path);
+   for (i = 0; i <= 1; i++)
+     {
+        Eina_Array *arrays[] =
+          { wc->domain_servers, wc->name_servers, wc->time_servers, 
wc->proxy_servers,
+            wc->proxy_excludes, NULL };
+        Eina_Array **arrays2[] =
+          { &wireless_edit[i]->domain_servers, &wireless_edit[i]->name_servers,
+            &wireless_edit[i]->time_servers, &wireless_edit[i]->proxy_servers,
+            &wireless_edit[i]->proxy_excludes, NULL };
+        unsigned int ii;
+
+        wireless_edit[i]->wn = wn;
+        wireless_edit[i]->method = wc->method;
+        wireless_edit[i]->address = eina_stringshare_ref(wc->address);
+        wireless_edit[i]->gateway = eina_stringshare_ref(wc->gateway);
+        wireless_edit[i]->ipv6 = wc->ipv6;
+        if (wc->ipv6)
+          {
+             wireless_edit[i]->ip.v6.prefixlength = 
eina_stringshare_ref(wc->ip.v6.prefixlength);
+             wireless_edit[i]->ip.v6.privacy = wc->ip.v6.privacy;
+          }
+        else
+          wireless_edit[i]->ip.v4.netmask = 
eina_stringshare_ref(wc->ip.v4.netmask);
+        wireless_edit[i]->proxy_type = wc->proxy_type;
+        wireless_edit[i]->proxy_url = eina_stringshare_ref(wc->proxy_url);
+        /* fuuuuck thiiiiiiis */
+        for (ii = 0; ii < EINA_C_ARRAY_LENGTH(arrays); ii++)
+          {
+             unsigned int iii;
+             Eina_Stringshare *str;
+             Eina_Array_Iterator itr;
+
+             if (!arrays[ii]) continue;
+             *arrays2[ii] = eina_array_new(eina_array_count(arrays[ii]));
+             EINA_ARRAY_ITER_NEXT(arrays[ii], iii, str, itr)
+               eina_array_push(*arrays2[ii], eina_stringshare_ref(str));
+          }
+     }
+   _wireless_gadget_edit_array_entry(wc->domain_servers, 
&wireless_popup.domain_servers);
+   _wireless_gadget_edit_array_entry(wc->name_servers, 
&wireless_popup.name_servers);
+   _wireless_gadget_edit_array_entry(wc->time_servers, 
&wireless_popup.time_servers);
+   _wireless_gadget_edit_array_entry(wc->proxy_servers, 
&wireless_popup.proxy_servers);
+   _wireless_gadget_edit_array_entry(wc->proxy_excludes, 
&wireless_popup.proxy_excludes);
+
+   wireless_popup.popup = popup = elm_popup_add(e_comp->elm);
+   evas_object_layer_set(popup, E_LAYER_MENU);
+   elm_popup_allow_events_set(popup, 1);
+   elm_popup_scrollable_set(popup, 1);
+
+   box = elm_box_add(popup);
+   E_EXPAND(box);
+   E_FILL(box);
+   evas_object_show(box);
+   elm_object_content_set(popup, box);
+
+   lbl = elm_label_add(box);
+   elm_object_style_set(lbl, "marker");
+   evas_object_show(lbl);
+   if (wireless_popup.type == WIRELESS_SERVICE_TYPE_ETHERNET)
+     strncpy(buf, _("Edit Connection Details: <b>Ethernet</b>"), sizeof(buf) - 
1);
+   else
+     snprintf(buf, sizeof(buf), "%s: <hilight>%s</hilight>", _("Edit 
Connection Details"), wc->wn->name);
+   elm_object_text_set(lbl, buf);
+   elm_box_pack_end(box, lbl);
+
+   wireless_popup.box = box1 = elm_box_add(popup);
+   E_EXPAND(box1);
+   E_FILL(box1);
+   elm_box_horizontal_set(box1, 1);
+   evas_object_show(box1);
+   elm_box_pack_end(box, box1);
+
+   list = elm_list_add(box1);
+   E_ALIGN(list, 0, EVAS_HINT_FILL);
+   E_WEIGHT(list, 0, EVAS_HINT_EXPAND);
+   elm_box_pack_end(box1, list);
+   elm_list_select_mode_set(list, ELM_OBJECT_SELECT_MODE_ALWAYS);
+   elm_scroller_content_min_limit(list, 1, 1);
+
+   entry = _wireless_gadget_edit_basic();
+   it = elm_list_item_append(list, _("Basic"), NULL, NULL, 
_wireless_gadget_edit_select_basic, NULL);
+   elm_list_item_selected_set(it, 1);
+   elm_list_item_append(list, _("Proxy"), NULL, NULL, 
_wireless_gadget_edit_select_proxy, NULL);
+   elm_list_item_append(list, _("DNS/Time"), NULL, NULL, 
_wireless_gadget_edit_select_dnstime, NULL);
+   elm_list_go(list);
+   evas_object_show(list);
+
+   if (wc->ipv6)
+     disabled = wc->method == WIRELESS_NETWORK_IPV4_METHOD_FIXED;
+   else
+     disabled = wc->method == WIRELESS_NETWORK_IPV6_METHOD_FIXED;
+   if (!disabled)
+     {
+        bt = elm_button_add(box);
+        E_EXPAND(bt);
+        E_FILL(bt);
+        evas_object_show(bt);
+        elm_object_text_set(bt, _("Deal with it"));
+        evas_object_smart_callback_add(bt, "clicked", 
_wireless_edit_send_button, NULL);
+        elm_box_pack_end(box, bt);
+
+        bt = elm_button_add(box);
+        E_EXPAND(bt);
+        E_FILL(bt);
+        evas_object_show(bt);
+        elm_object_text_set(bt, _("Forget Network"));
+        evas_object_smart_callback_add(bt, "clicked", _wireless_edit_remove, 
NULL);
+        elm_box_pack_end(box, bt);
+     }
+   wireless_edit_popup = e_comp_object_util_add(popup, 
E_COMP_OBJECT_TYPE_NONE);
+   evas_object_layer_set(wireless_edit_popup, E_LAYER_POPUP);
+   evas_object_resize(wireless_edit_popup, e_zone_current_get()->w / 3, 
e_zone_current_get()->h / 2);
+   e_comp_object_util_center(wireless_edit_popup);
+   evas_object_show(wireless_edit_popup);
+   e_comp_object_util_autoclose(wireless_edit_popup, NULL, _wireless_edit_key, 
NULL);
+   evas_object_event_callback_add(wireless_edit_popup, EVAS_CALLBACK_DEL, 
_wireless_edit_del, NULL);
+   elm_object_focus_set(entry, 1);
+}
+
+static void
+_wireless_popup_network_click(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   Wireless_Network *wn = data;
+
+   if ((wn->state == WIRELESS_NETWORK_STATE_CONNECTED) || (wn->state == 
WIRELESS_NETWORK_STATE_ONLINE))
+     {
+        int type = wireless_popup.type;
+
+        evas_object_hide(wireless_popup.popup);
+        evas_object_del(wireless_popup.popup);
+        _wireless_gadget_edit(type);
+     }
+   else
+     {
+        /* FIXME */
+        if (!wn->connect_cb(wn))
+          {}
+     }
+}
+
+static void
+_wireless_popup_list_populate(void)
+{
+   Eina_Iterator *it;
+   Wireless_Network *wn;
+
+   if (!wireless_networks) return;
+   it = eina_array_iterator_new(wireless_networks);
+   EINA_ITERATOR_FOREACH(it, wn)
+     {
+        Evas_Object *icon;
+        Elm_Object_Item *item;
+        const char *name = wn->name;
+
+        if (wn->type != wireless_popup.type) continue;
+        icon = elm_layout_add(wireless_popup.content);
+        e_theme_edje_object_set(icon, NULL, 
wireless_theme_groups[wireless_popup.type]);
+        _wifi_icon_init(icon, wn, wn->type);
+        if (!name)
+          name = _("<SSID hidden>");
+        item = elm_list_item_append(wireless_popup.content, name, icon, NULL, 
_wireless_popup_network_click, wn);
+        eina_hash_add(wireless_popup.items, &wn, item);
+     }
+   eina_iterator_free(it);
+}
+
+static void
+_wireless_gadget_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, 
void *event_info)
+{
+   Evas_Event_Mouse_Down *ev = event_info;
+   Instance *inst = data;
+   Evas_Object *ctx, *box, *list, *toggle;
+   int type;
+   E_Zone *zone;
+   const char *names[] =
+   {
+      _("Ethernet"),
+      _("Wifi"),
+      _("Bluetooth"),
+      _("Cellular"),
+   };
+
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   if (auth_popup) return;
+   for (type = 0; type < WIRELESS_SERVICE_TYPE_LAST; type++)
+     if (obj == inst->icon[type])
+       break;
+   if (ev->button == 2) connman_technology_enabled_set(type, 
!wireless_type_enabled[type]);
+   if (ev->button == 3) _wireless_gadget_edit(type);
+   if (ev->button != 1) return;
+   if (wireless_popup.popup)
+     {
+        evas_object_hide(wireless_popup.popup);
+        evas_object_del(wireless_popup.popup);
+        if (wireless_popup.type == type)
+          return;
+     }
+   inst->popup = 1;
+   wireless_popup.type = type;
+   wireless_popup.items = eina_hash_pointer_new(NULL);
+   ctx = elm_ctxpopup_add(e_comp->elm);
+   elm_object_style_set(ctx, "noblock");
+
+   box = elm_box_add(ctx);
+   E_EXPAND(box);
+   E_FILL(box);
+
+   wireless_popup.content = list = elm_list_add(ctx);
+   elm_list_mode_set(list, ELM_LIST_LIMIT);
+   E_EXPAND(list);
+   E_FILL(list);
+   _wireless_popup_list_populate();
+   elm_list_go(list);
+   evas_object_show(list);
+   elm_box_pack_end(box, list);
+   toggle = elm_check_add(ctx);
+   evas_object_show(toggle);
+   elm_object_style_set(toggle, "toggle");
+   elm_object_text_set(toggle, names[type]);
+   elm_object_part_text_set(toggle, "on", _("On"));
+   elm_object_part_text_set(toggle, "off", _("Off"));
+   elm_check_state_set(toggle, wireless_type_enabled[type]);
+   evas_object_smart_callback_add(toggle, "changed", _wireless_popup_toggle, 
inst);
+   elm_box_pack_end(box, toggle);
+   elm_object_content_set(ctx, box);
+   e_gadget_util_ctxpopup_place(inst->box, ctx, inst->icon[type]);
+   wireless_popup.popup = e_comp_object_util_add(ctx, E_COMP_OBJECT_TYPE_NONE);
+   evas_object_layer_set(wireless_popup.popup, E_LAYER_POPUP);
+   e_comp_object_util_autoclose(wireless_popup.popup, NULL, 
e_comp_object_util_autoclose_on_escape, NULL);
+
+   zone = e_zone_current_get();
+   evas_object_resize(wireless_popup.popup, zone->w / 5, zone->h / 3);
+   evas_object_show(wireless_popup.popup);
+   evas_object_event_callback_add(wireless_popup.popup, EVAS_CALLBACK_DEL, 
_wireless_popup_del, inst);
+}
+
+static Evas_Object *
+_wireless_tooltip_row(Evas_Object *tb, const char *label, const char *value, 
int row)
+{
+   Evas_Object *lbl;
+
+   lbl = elm_label_add(tb);
+   evas_object_show(lbl);
+   E_ALIGN(lbl, 0, 0.5);
+   elm_object_text_set(lbl, label);
+   elm_table_pack(tb, lbl, 0, row, 1, 1);
+
+   lbl = elm_label_add(tb);
+   evas_object_show(lbl);
+   E_ALIGN(lbl, 0, 0.5);
+   elm_object_text_set(lbl, value);
+   elm_table_pack(tb, lbl, 1, row, 1, 1);
+   return lbl;
+}
+
+static const char *
+_wireless_tooltip_method_name(void)
+{
+   if (wireless_current[WIRELESS_SERVICE_TYPE_WIFI]->ipv6)
+     return 
wireless_ipv6_methods[wireless_current[WIRELESS_SERVICE_TYPE_WIFI]->method];
+   return 
wireless_ipv4_methods[wireless_current[WIRELESS_SERVICE_TYPE_WIFI]->method];
+}
+
+static void
+_wireless_tooltip_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Instance *inst = data;
+
+   inst->tooltip.error = inst->tooltip.address =
+     inst->tooltip.method = inst->tooltip.signal = NULL;
+   inst->tooltip.type = -1;
+}
+
+static Evas_Object *
+_wireless_tooltip(void *data, Evas_Object *obj EINA_UNUSED, Evas_Object 
*tooltip)
+{
+   Instance *inst = data;
+   Evas_Object *tb;
+   int row = 0;
+   char buf[1024];
+   int type = WIRELESS_SERVICE_TYPE_WIFI;
+
+   if (!wireless_current[type])
+     {
+        if (!wireless_type_available[type])//connman not found
+          {
+             inst->tooltip.error = elm_label_add(tooltip);
+             elm_object_text_set(inst->tooltip.error, _("Error: Connman not 
detected!"));
+             evas_object_event_callback_add(inst->tooltip.error, 
EVAS_CALLBACK_DEL, _wireless_tooltip_del, inst);
+             return inst->tooltip.error;
+          }
+        return NULL;
+     }
+   tb = elm_table_add(tooltip);
+   elm_table_padding_set(tb, 5, 1);
+
+   _wireless_tooltip_row(tb, _("Name:"), wireless_current[type]->wn->name, 
row++);
+   inst->tooltip.method = _wireless_tooltip_row(tb, _("Method:"), 
_wireless_tooltip_method_name(), row++);
+
+   inst->tooltip.address = _wireless_tooltip_row(tb, _("Address:"), 
wireless_current[type]->address, row++);
+   snprintf(buf, sizeof(buf), "%u%%", wireless_current[type]->wn->strength);
+   inst->tooltip.signal = _wireless_tooltip_row(tb, _("Signal:"), buf, row++);
+
+   evas_object_event_callback_add(tb, EVAS_CALLBACK_DEL, 
_wireless_tooltip_del, inst);
+   return tb;
+}
+
+static void
+wireless_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+{
+   Instance *inst = data;
+
+   if (inst->popup)
+     {
+        evas_object_hide(wireless_popup.popup);
+        evas_object_del(wireless_popup.popup);
+     }
+
+   instances = eina_list_remove(instances, inst);
+   evas_object_hide(wireless_popup.popup);
+   evas_object_del(wireless_popup.popup);
+   free(inst);
+
+   if (instances) return;
+   eina_log_domain_unregister(_wireless_gadget_log_dom);
+   _wireless_gadget_log_dom = -1;
+}
+
+static void
+_wireless_gadget_icon_add(Instance *inst, int type)
+{
+   if (!inst->icon[type])
+     {
+        Evas_Object *g;
+
+        inst->icon[type] = g = elm_layout_add(inst->box);
+        E_EXPAND(g);
+        E_FILL(g);
+        e_theme_edje_object_set(g, NULL, wireless_theme_groups[type]);
+        elm_object_tooltip_content_cb_set(g, _wireless_tooltip, inst, NULL);
+        evas_object_event_callback_add(g, EVAS_CALLBACK_MOUSE_DOWN, 
_wireless_gadget_mouse_down, inst);
+     }
+   DBG("Updating icon for %d", type);
+   _wifi_icon_init(inst->icon[type], wireless_current[type] ? 
wireless_current[type]->wn : NULL, type);
+   evas_object_hide(inst->icon[type]);
+}
+
+static void
+_wireless_gadget_refresh(Instance *inst)
+{
+   int type;
+   int avail = 0;
+
+   if (inst->id < 0) return;
+   for (type = 0; type < WIRELESS_SERVICE_TYPE_LAST; type++)
+     {
+        if (wireless_type_available[type])
+          _wireless_gadget_icon_add(inst, type);
+        else
+          {
+             if (inst->tooltip.type == type)
+               elm_object_tooltip_hide(inst->icon[type]);
+             if (wireless_popup.type == type)
+               {
+                  evas_object_hide(wireless_popup.popup);
+                  evas_object_del(wireless_popup.popup);
+               }
+             E_FREE_FUNC(inst->icon[type], evas_object_del);
+          }
+     }
+   elm_box_unpack_all(inst->box);
+   type = WIRELESS_SERVICE_TYPE_ETHERNET;
+   if (inst->icon[type])
+     {
+        /* only show ethernet if it's connected or there's no wifi available */
+        if ((!inst->icon[WIRELESS_SERVICE_TYPE_WIFI]) ||
+            wireless_network_count[WIRELESS_SERVICE_TYPE_ETHERNET] ||
+            (wireless_current[type] &&
+             wireless_current[type]->wn &&
+            (wireless_current[type]->wn->state == 
WIRELESS_NETWORK_STATE_ONLINE)))
+          {
+             elm_box_pack_end(inst->box, inst->icon[type]);
+             evas_object_show(inst->icon[type]);
+             avail++;
+          }
+     }
+   for (type = WIRELESS_SERVICE_TYPE_WIFI; type < WIRELESS_SERVICE_TYPE_LAST; 
type++)
+     {
+        if (!inst->icon[type]) continue;
+        if (wireless_type_enabled[type] && (!wireless_network_count[type])) 
continue;
+        
+        elm_box_pack_end(inst->box, inst->icon[type]);
+        evas_object_show(inst->icon[type]);
+        avail++;
+     }
+   if (!avail)
+     {
+        type = WIRELESS_SERVICE_TYPE_ETHERNET;
+        _wireless_gadget_icon_add(inst, type);
+        elm_box_pack_end(inst->box, inst->icon[type]);
+        evas_object_show(inst->icon[type]);
+        avail++;
+     }
+   if (inst->orient == E_GADGET_SITE_ORIENT_VERTICAL)
+     evas_object_size_hint_aspect_set(inst->box, EVAS_ASPECT_CONTROL_BOTH, 1, 
avail);
+   else
+     evas_object_size_hint_aspect_set(inst->box, EVAS_ASPECT_CONTROL_BOTH, 
avail, 1);
+}
+
+static Evas_Object *
+wireless_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
+{
+   Evas_Object *g;
+   Instance *inst;
+
+   if (!instances)
+     _wireless_gadget_log_dom = eina_log_domain_register("wireless", 
EINA_COLOR_CYAN);
+   inst = E_NEW(Instance, 1);
+   inst->id = *id;
+   inst->orient = orient;
+   wireless_popup.type = inst->tooltip.type = -1;
+   inst->box = elm_box_add(parent);
+   elm_box_horizontal_set(inst->box, orient != E_GADGET_SITE_ORIENT_VERTICAL);
+   elm_box_homogeneous_set(inst->box, 1);
+   evas_object_event_callback_add(inst->box, EVAS_CALLBACK_DEL, wireless_del, 
inst);
+
+   if (*id < 0)
+     {
+        inst->icon[WIRELESS_SERVICE_TYPE_WIFI] = g = elm_layout_add(inst->box);
+        E_EXPAND(g);
+        E_FILL(g);
+        e_theme_edje_object_set(g, NULL, "e/gadget/wireless/wifi");
+        elm_object_signal_emit(g, "e,state,default", "e");
+        _wifi_icon_signal(g, WIRELESS_NETWORK_STATE_ONLINE, 100);
+        evas_object_show(g);
+        elm_box_pack_end(inst->box, g);
+        evas_object_size_hint_aspect_set(inst->box, EVAS_ASPECT_CONTROL_BOTH, 
1, 1);
+     }
+   else
+     _wireless_gadget_refresh(inst);
+   instances = eina_list_append(instances, inst);
+
+   return inst->box;
+}
+
+static Ecore_Event_Handler *handler;
+
+static Eina_Bool
+_wireless_mode_change()
+{
+   EINTERN void connman_airplane_mode_set(Eina_Bool set);
+
+   if (wireless_offline != e_config->mode.offline)
+     connman_airplane_mode_set(e_config->mode.offline);
+   return ECORE_CALLBACK_RENEW;
+}
+
+EINTERN void
+wireless_gadget_init(void)
+{
+   e_gadget_type_add("Wireless", wireless_create, NULL);
+   handler = ecore_event_handler_add(E_EVENT_CONFIG_MODE_CHANGED, 
_wireless_mode_change, NULL);
+}
+
+EINTERN void
+wireless_gadget_shutdown(void)
+{
+   e_gadget_type_del("Wireless");
+   E_FREE_FUNC(handler, ecore_event_handler_del);
+}
+
+EINTERN void
+wireless_service_type_available_set(Eina_Bool *avail)
+{
+   if (!memcmp(avail, &wireless_type_available, 
sizeof(wireless_type_available))) return;
+   memcpy(&wireless_type_available, avail, WIRELESS_SERVICE_TYPE_LAST * 
sizeof(Eina_Bool));
+   E_LIST_FOREACH(instances, _wireless_gadget_refresh);
+}
+
+EINTERN void
+wireless_service_type_enabled_set(Eina_Bool *avail)
+{
+   if (!memcmp(avail, &wireless_type_enabled, sizeof(wireless_type_enabled))) 
return;
+   memcpy(&wireless_type_enabled, avail, WIRELESS_SERVICE_TYPE_LAST * 
sizeof(Eina_Bool));
+   E_LIST_FOREACH(instances, _wireless_gadget_refresh);
+}
+
+EINTERN void
+wireless_wifi_current_networks_set(Wireless_Connection **current)
+{
+   Eina_List *l;
+   Instance *inst;
+   Wireless_Connection *prev[WIRELESS_SERVICE_TYPE_LAST] = {NULL};
+   int type;
+
+   memcpy(&prev, &wireless_current, WIRELESS_SERVICE_TYPE_LAST * 
sizeof(void*));
+   memcpy(&wireless_current, current, WIRELESS_SERVICE_TYPE_LAST * 
sizeof(void*));
+   type = wireless_popup.type;
+   if ((type > -1) && wireless_popup.items)
+     {
+        Elm_Object_Item *it;
+        Evas_Object *icon;
+
+        if (wireless_current[type])
+          {
+             it = eina_hash_find(wireless_popup.items, 
&wireless_current[type]->wn);
+             icon = elm_object_item_content_get(it);
+             _wifi_icon_init(icon, wireless_current[type]->wn, type);
+          }
+        if (prev[type])
+          {
+             it = eina_hash_find(wireless_popup.items, &prev[type]->wn);
+             if (it)
+               {
+                  icon = elm_object_item_content_get(it);
+                  _wifi_icon_init(icon, prev[type]->wn, type);
+               }
+          }
+     }
+   else if ((type > -1) && wireless_popup.popup && (!wireless_current[type]))
+     {
+        evas_object_hide(wireless_popup.popup);
+        evas_object_del(wireless_popup.popup);
+     }
+   EINA_LIST_FOREACH(instances, l, inst)
+     {
+        _wireless_gadget_refresh(inst);
+        type = inst->tooltip.type;
+        if (type < 0) continue;
+        if (prev[type] &&
+          ((!wireless_current[type]) ||
+            ((wireless_current[type] != prev[type]) && 
(!eina_streq(wireless_current[type]->wn->name, prev[type]->wn->name)))))
+          {
+             elm_object_tooltip_hide(inst->icon[type]);
+             continue;
+          }
+        if (inst->tooltip.method)
+          elm_object_text_set(inst->tooltip.method, 
_wireless_tooltip_method_name());
+        if (inst->tooltip.address)
+          elm_object_text_set(inst->tooltip.address, 
wireless_current[type]->address);
+        if (inst->tooltip.signal)
+          {
+             char buf[32];
+
+             snprintf(buf, sizeof(buf), "%u%%", 
wireless_current[type]->wn->strength);
+             elm_object_text_set(inst->tooltip.signal, buf);
+          }
+     }
+}
+
+static Eina_Bool
+_wireless_networks_count(const void *cont EINA_UNUSED, void *data, void *fdata 
EINA_UNUSED)
+{
+   Wireless_Network *wn = data;
+
+   wireless_network_count[wn->type]++;
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Array *
+wireless_networks_set(Eina_Array *networks)
+{
+   Eina_Array *prev = wireless_networks;
+
+   wireless_networks = networks;
+   memset(&wireless_network_count, 0, sizeof(wireless_network_count));
+   eina_array_foreach(networks, _wireless_networks_count, NULL);
+   if (wireless_popup.popup && wireless_popup.items)
+     {
+        elm_list_clear(wireless_popup.content);
+        eina_hash_free_buckets(wireless_popup.items);
+        _wireless_popup_list_populate();
+     }
+
+   return prev;
+}
+
+EINTERN void
+wireless_airplane_mode_set(Eina_Bool enabled)
+{
+   wireless_offline = enabled;
+   if (enabled == e_config->mode.offline) return;
+   e_config->mode.offline = !!enabled;
+   e_config_mode_changed();
+   e_config_save_queue();
+}
+
+static void
+_wireless_auth_del(void *data, Evas_Object *popup)
+{
+   Wireless_Auth_Popup *p = data;
+
+   if (!p->sent)
+     p->cb(p->data, NULL);
+   free(p);
+   wireless_auth_popup = NULL;
+   evas_object_hide(popup);
+   evas_object_del(popup);
+   if (!wireless_auth_pending) return;
+   wireless_auth_popup = eina_list_data_get(wireless_auth_pending);
+   wireless_auth_pending = eina_list_remove_list(wireless_auth_pending, 
wireless_auth_pending);
+   evas_object_show(wireless_auth_popup->popup);
+   e_comp_object_util_autoclose(wireless_auth_popup->popup,
+     _wireless_auth_del, e_comp_object_util_autoclose_on_escape, 
wireless_auth_popup);
+}
+
+static void
+_wireless_auth_send(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   Wireless_Auth_Popup *p = data;
+   Eina_Array *arr = NULL;
+   Evas_Object *tb, *o;
+   unsigned int row = 1;
+
+   tb = evas_object_data_get(obj, "table");
+   do
+     {
+        const char *txt;
+
+        o = elm_table_child_get(tb, 0, row);
+        if (!o) break;
+        if (!arr) arr = eina_array_new(2);
+        txt = elm_object_text_get(o);
+        eina_array_push(arr, txt);
+        o = elm_object_content_get(o);
+        /* skip checkboxes */
+        if (!strncmp(txt, "Pass", 4)) row++;
+        eina_array_push(arr, elm_object_text_get(o));
+        row += 2;
+     } while (1);
+   p->cb(p->data, arr);
+   p->sent = 1;
+   eina_array_free(arr);
+   e_comp_object_util_autoclose(NULL, NULL, NULL, NULL);
+}
+
+static void
+_wireless_auth_password_toggle(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   elm_entry_password_set(data, !elm_entry_password_get(data));
+}
+
+EINTERN void
+wireless_authenticate(const Eina_Array *fields, Wireless_Auth_Cb cb, void 
*data)
+{
+   Evas_Object *popup, *tb, *lbl, *entry = NULL;
+   Eina_Iterator *it;
+   const char *f;
+   Wireless_Auth_Popup *p;
+   int row = 0;
+
+   p = E_NEW(Wireless_Auth_Popup, 1);
+   p->cb = cb;
+   p->data = data;
+   if (wireless_popup.popup)
+     {
+        evas_object_hide(wireless_popup.popup);
+        evas_object_del(wireless_popup.popup);
+     }
+
+   popup = elm_popup_add(e_comp->elm);
+   elm_popup_allow_events_set(popup, 1);
+   elm_popup_scrollable_set(popup, 1);
+
+   tb = elm_table_add(popup);
+   evas_object_show(tb);
+   elm_object_content_set(popup, tb);
+
+   lbl = elm_label_add(popup);
+   evas_object_show(lbl);
+   elm_object_text_set(lbl, _("Authentication Required"));
+   elm_table_pack(tb, lbl, 0, row++, 2, 1);
+
+   it = eina_array_iterator_new(fields);
+   EINA_ITERATOR_FOREACH(it, f)
+     {
+        Evas_Object *o;
+        char buf[1024];
+        Evas_Object *ck;
+
+        o = _wireless_popup_table_entry_row(tb, f, _wireless_auth_send, p, 
&row);
+        if (strncmp(f, "Pass", 4)) continue;
+        if (!entry) entry = o;
+        elm_entry_password_set(o, 1);
+
+        ck = elm_check_add(tb);
+        evas_object_show(ck);
+        E_ALIGN(ck, 0, -1);
+        snprintf(buf, sizeof(buf), _("Show %s"), f);
+        evas_object_smart_callback_add(ck, "changed", 
_wireless_auth_password_toggle, o);
+        elm_object_text_set(ck, buf);
+        elm_table_pack(tb, ck, 0, row++, 2, 1);
+     }
+   popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE);
+   p->popup = popup;
+   evas_object_resize(popup, e_zone_current_get()->w / 4, 
e_zone_current_get()->h / 3);
+   evas_object_layer_set(popup, E_LAYER_POPUP);
+   e_comp_object_util_center(popup);
+   if (wireless_auth_popup)
+     wireless_auth_pending = eina_list_append(wireless_auth_pending, p);
+   else
+     {
+        wireless_auth_popup = p;
+        evas_object_show(popup);
+        e_comp_object_util_autoclose(popup, _wireless_auth_del,
+          e_comp_object_util_autoclose_on_escape, p);
+        elm_object_focus_set(entry, 1);
+     }
+}
+
+EINTERN void
+wireless_authenticate_cancel(void)
+{
+   if (!wireless_auth_popup) return;
+   evas_object_hide(wireless_auth_popup->popup);
+   evas_object_del(wireless_auth_popup->popup);
+}
+
+static void
+_wireless_auth_external_deny(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   /* FIXME */
+   free(data);
+   auth_popup = 0;
+}
+
+static void
+_wireless_auth_external_allow(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   char *sb, *uri = data;
+   const char *bindir;
+   size_t size = PATH_MAX, len;
+
+   bindir = e_prefix_bin_get();
+   len = strlen(bindir);
+   sb = malloc(size);
+   snprintf(sb, size, "%s/enlightenment_open", bindir);
+   sb = e_util_string_append_quoted(sb, &size, &len, uri);
+   DBG("launched command: %s", sb);
+   ecore_exe_run(sb, NULL);
+   free(sb);
+   free(uri);
+   auth_popup = 0;
+}
+
+EINTERN void
+wireless_authenticate_external(Wireless_Network *wn, const char *url)
+{
+   char buf[1024];
+   Eina_List *l;
+   Instance *inst;
+
+   EINA_LIST_FOREACH(instances, l, inst)
+     if (wireless_popup.popup)
+       {
+          evas_object_hide(wireless_popup.popup);
+          evas_object_del(wireless_popup.popup);
+       }
+   if (wn->type == WIRELESS_SERVICE_TYPE_ETHERNET)
+     snprintf(buf, sizeof(buf), _("Ethernet connection wants to open a 
url:<br>%s"), url);
+   else
+     snprintf(buf, sizeof(buf), _("Network '%s' wants to open a url:<br>%s"), 
wn->name, url);
+   EINA_LIST_FOREACH(instances, l, inst)
+     {
+        if (!inst->icon[wn->type]) continue;
+        e_gadget_util_allow_deny_ctxpopup(inst->box, buf, 
_wireless_auth_external_allow, _wireless_auth_external_deny, strdup(url));
+        auth_popup = 1;
+        break;
+     }
+}
diff --git a/src/modules/wireless/wireless.h b/src/modules/wireless/wireless.h
new file mode 100644
index 0000000..883f80f
--- /dev/null
+++ b/src/modules/wireless/wireless.h
@@ -0,0 +1,134 @@
+#ifndef E_WIRELESS_H
+# define E_WIRELESS_H
+
+#include "e.h"
+
+typedef enum
+{
+   WIRELESS_SERVICE_TYPE_NONE = -1,
+   WIRELESS_SERVICE_TYPE_ETHERNET,
+   WIRELESS_SERVICE_TYPE_WIFI,
+   WIRELESS_SERVICE_TYPE_BLUETOOTH,
+   WIRELESS_SERVICE_TYPE_CELLULAR,
+   WIRELESS_SERVICE_TYPE_LAST,
+} Wireless_Service_Type;
+
+typedef enum
+{
+   WIRELESS_NETWORK_STATE_NONE,
+   WIRELESS_NETWORK_STATE_CONFIGURING,
+   WIRELESS_NETWORK_STATE_CONNECTED,
+   WIRELESS_NETWORK_STATE_ONLINE,
+   WIRELESS_NETWORK_STATE_FAILURE,
+} Wireless_Network_State;
+
+typedef enum
+{
+   WIRELESS_NETWORK_SECURITY_NONE = 0,
+   WIRELESS_NETWORK_SECURITY_WEP = (1 << 0),
+   WIRELESS_NETWORK_SECURITY_PSK = (1 << 1),
+   WIRELESS_NETWORK_SECURITY_IEEE8021X = (1 << 2),
+   WIRELESS_NETWORK_SECURITY_WPS = (1 << 3),
+} Wireless_Network_Security;
+
+typedef enum
+{
+   WIRELESS_NETWORK_IPV4_METHOD_OFF,
+   WIRELESS_NETWORK_IPV4_METHOD_MANUAL,
+   WIRELESS_NETWORK_IPV4_METHOD_DHCP,
+   WIRELESS_NETWORK_IPV4_METHOD_FIXED,
+} Wireless_Network_IPv4_Method;
+
+typedef enum
+{
+   WIRELESS_NETWORK_IPV6_METHOD_OFF,
+   WIRELESS_NETWORK_IPV6_METHOD_MANUAL,
+   WIRELESS_NETWORK_IPV6_METHOD_AUTO,
+   WIRELESS_NETWORK_IPV6_METHOD_6TO4,
+   WIRELESS_NETWORK_IPV6_METHOD_FIXED,
+} Wireless_Network_IPv6_Method;
+
+typedef enum
+{
+   WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED,
+   WIRELESS_NETWORK_IPV6_PRIVACY_ENABLED,
+   WIRELESS_NETWORK_IPV6_PRIVACY_PREFERRED,
+} Wireless_Network_IPv6_Privacy;
+
+typedef enum
+{
+   WIRELESS_PROXY_TYPE_DIRECT,
+   WIRELESS_PROXY_TYPE_MANUAL,
+   WIRELESS_PROXY_TYPE_AUTO,
+} Wireless_Proxy_Type;
+
+typedef struct Wireless_Network Wireless_Network;
+
+typedef Eina_Bool (*Wireless_Network_Connect_Cb)(Wireless_Network *);
+
+struct Wireless_Network
+{
+   Eina_Stringshare *path;//dbus path
+   Eina_Stringshare *name;
+   Wireless_Network_Security security;
+   Wireless_Network_State state;
+   Wireless_Service_Type type;
+   uint8_t strength;
+
+   Wireless_Network_Connect_Cb connect_cb;
+};
+
+typedef struct Wireless_Connection
+{
+   Wireless_Network *wn;
+   unsigned int method;
+   Eina_Stringshare *address;
+   Eina_Stringshare *gateway;
+   union
+   {
+      struct
+      {
+         Eina_Stringshare *netmask;
+      } v4;
+      struct
+      {
+         Eina_Stringshare *prefixlength;
+         Wireless_Network_IPv6_Privacy privacy;
+      } v6;
+   } ip;
+
+   Eina_Array *domain_servers;
+   Eina_Array *name_servers;
+   Eina_Array *time_servers;
+
+   Wireless_Proxy_Type proxy_type;
+   Eina_Stringshare *proxy_url;
+   Eina_Array *proxy_servers;
+   Eina_Array *proxy_excludes;
+   Eina_Bool ipv6 : 1;
+   Eina_Bool favorite : 1;
+} Wireless_Connection;
+
+typedef void (*Wireless_Auth_Cb)(void *data, const Eina_Array *fields);
+
+extern Eldbus_Connection *dbus_conn;
+
+EINTERN void wireless_service_type_available_set(Eina_Bool *avail);
+EINTERN void wireless_service_type_enabled_set(Eina_Bool *enabled);
+EINTERN void wireless_wifi_current_networks_set(Wireless_Connection **current);
+EINTERN Eina_Array *wireless_networks_set(Eina_Array *networks);
+EINTERN void wireless_airplane_mode_set(Eina_Bool enabled);
+EINTERN void wireless_authenticate(const Eina_Array *fields, Wireless_Auth_Cb 
cb, void *data);
+EINTERN void wireless_authenticate_cancel(void);
+EINTERN void wireless_authenticate_external(Wireless_Network *wn, const char 
*url);
+
+static inline void
+array_clear(Eina_Array *arr)
+{
+   if (arr)
+     while (eina_array_count(arr))
+       eina_stringshare_del(eina_array_pop(arr));
+   eina_array_free(arr);
+}
+
+#endif

-- 


Reply via email to