summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier Fernandez <jfernandez@igalia.com>2010-08-10 15:25:49 +0200
committerBastien Nocera <hadess@hadess.net>2010-08-20 12:42:49 +0100
commit25402eb6aae5c2ba62bd91e0514eecf3de319d53 (patch)
tree069b0ef38affe49a8803e89abf9961f37387c6c6
parent777c10b831c11ba1af0984177562a37e5eb60a8f (diff)
Implementation of the Connman support.
Connectivity interface methods implemented: - get_status - get_ap_mac - get_router_mac - get_aps https://bugs.freedesktop.org/show_bug.cgi?id=29515
-rw-r--r--configure.ac25
-rw-r--r--src/Makefile.am4
-rw-r--r--src/connectivity-connman.c739
-rw-r--r--src/connectivity-connman.h56
-rw-r--r--src/connectivity.c8
-rw-r--r--src/master.c4
6 files changed, 835 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index b496b62..265fb0f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,6 +118,31 @@ if test "x$enable_conic" = "xyes" -a "x$have_conic" != "xyes"; then
AC_MSG_ERROR([Couldn't find conic dependencies.])
fi
+AC_ARG_ENABLE(connman,
+ AS_HELP_STRING([--enable-connman=@<:@no/yes/auto@:>@],
+ [build with connman support]), ,
+ enable_connman=auto)
+
+if test "x$enable_connman" != "xno"; then
+ PKG_CHECK_MODULES(CONNMAN,
+ [
+ connman
+ ], have_connman="yes", have_connman="no")
+
+ if test "x$have_connman" = "xyes"; then
+ CONNECTIVITY="Meego LibConnMan"
+ CONNECTIVITY_LIBS=${CONNMAN_LIBS}
+ CONNECTIVITY_CFLAGS=${CONNMAN_CFLAGS}
+ AC_DEFINE(HAVE_CONNMAN, 1, [define if libconmann is installed])
+ fi
+else
+ have_connman=no
+fi
+
+if test "x$enable_connman" = "xyes" -a "x$have_connman" != "xyes"; then
+ AC_MSG_ERROR([Couldn't find connman dependencies.])
+fi
+
AC_ARG_ENABLE(networkmanager,
AS_HELP_STRING([--enable-networkmanager=@<:@no/yes/auto@:>@],
[build with NetworkManager support]), ,
diff --git a/src/Makefile.am b/src/Makefile.am
index 4924462..ec54d61 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,9 +27,11 @@ libconnectivity_la_SOURCES = \
connectivity.h \
connectivity-networkmanager.h \
connectivity-conic.h \
+ connectivity-connman.h \
connectivity.c \
connectivity-networkmanager.c \
- connectivity-conic.c
+ connectivity-conic.c \
+ connectivity-connman.c
libconnectivity_la_LIBADD = $(CONNECTIVITY_LIBS)
diff --git a/src/connectivity-connman.c b/src/connectivity-connman.c
new file mode 100644
index 0000000..42ccce0
--- /dev/null
+++ b/src/connectivity-connman.c
@@ -0,0 +1,739 @@
+/*
+ * Geoclue
+ * connectivity-connman.c
+ *
+ * Author: Javier Fernandez <jfernandez@igalia.com>
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include <config.h>
+
+#ifdef HAVE_CONNMAN
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include "connectivity-connman.h"
+
+#define CONNMAN_SERVICE "org.moblin.connman"
+#define CONNMAN_MANAGER_PATH "/"
+#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"
+#define CONNMAN_TECHNOLOGY_INTERFACE CONNMAN_SERVICE ".Technology"
+#define CONNMAN_DEVICE_INTERFACE CONNMAN_SERVICE ".Device"
+#define CONNMAN_NETWORK_INTERFACE CONNMAN_SERVICE ".Network"
+#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
+
+typedef void (*ConnmanFunc) (GeoclueConnman *self,
+ const gchar *path,
+ gpointer out);
+
+static void geoclue_connman_connectivity_init (GeoclueConnectivityInterface *iface);
+
+static int _strength_to_dbm (int strength);
+static char *_get_mac_for_gateway (const char *gateway);
+static char *_mac_strup (char *mac);
+static gchar *_get_gateway (GeoclueConnman *self, const gchar *service);
+static void _get_best_ap (GeoclueConnman *self, const gchar *network);
+static void _get_aps_info (GeoclueConnman *self, const gchar *network, GHashTable **out);
+static const GPtrArray *_get_technologies (GeoclueConnman *self, GHashTable **props);
+static const GPtrArray *_get_services (GeoclueConnman *self, GHashTable **props);
+static const GPtrArray *_get_devices (GeoclueConnman *self, GHashTable **props, const gchar *technology);
+static const GPtrArray *_get_networks (GeoclueConnman *self, GHashTable **props, const gchar *device, const gchar *type_filter);
+static void _explore_available_aps (GeoclueConnman *self, ConnmanFunc func, gpointer out);
+
+
+G_DEFINE_TYPE_WITH_CODE (GeoclueConnman, geoclue_connman, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GEOCLUE_TYPE_CONNECTIVITY,
+ geoclue_connman_connectivity_init))
+
+
+/* GeoclueConnectivity iface methods */
+static int
+_get_status (GeoclueConnectivity *iface)
+{
+ GeoclueConnman *connman = GEOCLUE_CONNMAN (iface);
+
+ return connman->status;
+}
+
+static char *
+_get_ap_mac (GeoclueConnectivity *iface)
+{
+ GeoclueConnman *connman = GEOCLUE_CONNMAN (iface);
+
+ return g_strdup (connman->cache_ap_mac);
+}
+
+static GHashTable *
+_get_aps (GeoclueConnectivity *iface)
+{
+ GeoclueConnman *self = GEOCLUE_CONNMAN (iface);
+ GHashTable *ht = NULL;
+
+ /* Explore the active networks to collect the APs. */
+ _explore_available_aps (self, (ConnmanFunc) _get_aps_info, &ht);
+
+ return ht;
+}
+
+static char *
+_get_router_mac (GeoclueConnectivity *iface)
+{
+ GeoclueConnman *self = GEOCLUE_CONNMAN (iface);
+ GHashTable *props = NULL;
+ const GPtrArray *servs = NULL;
+ const gchar *serv = NULL;
+ gchar *gateway = NULL;
+ char *mac = NULL;
+ guint i;
+
+ /* Get available services and iterate over them */
+ /* to get the MAC of the connected router. */
+ servs = _get_services (self, &props);
+ if (servs != NULL) {
+ for (i = 0; gateway == NULL && servs->len; i++) {
+ serv = g_ptr_array_index (servs, i);
+ gateway = _get_gateway (self, serv);
+ }
+ }
+
+ /* Check the result. */
+ if (gateway != NULL) {
+ mac = _get_mac_for_gateway (gateway);
+ g_free (gateway);
+ }
+
+ /* Free */
+ g_hash_table_destroy (props);
+
+ return mac;
+}
+
+/* internal private GObject methods */
+static void
+dispose (GObject *object)
+{
+ GeoclueConnman *self = GEOCLUE_CONNMAN (object);
+
+ g_object_unref (self->client);
+ self->client = NULL;
+
+ dbus_g_connection_unref (self->conn);
+ self->conn = NULL;
+
+ g_free (self->cache_ap_mac);
+ self->cache_ap_mac = NULL;
+
+ ((GObjectClass *) geoclue_connman_parent_class)->dispose (object);
+}
+
+static void
+geoclue_connman_class_init (GeoclueConnmanClass *klass)
+{
+ GObjectClass *o_class = (GObjectClass *) klass;
+
+ o_class->dispose = dispose;
+}
+
+static int
+_strength_to_dbm (int strength)
+{
+ /* Hackish linear strength to dBm conversion.
+ * 0% is -90 dBm
+ * 100% is -20 dBm */
+ return (strength * 0.7) - 90;
+}
+
+static char *
+_get_mac_for_gateway (const char *gateway)
+{
+ char *cmd, *out, *mac, **split;
+
+ cmd = g_strdup_printf ("ip neigh show %s", gateway);
+
+ if (g_spawn_command_line_sync (cmd, &out, NULL, NULL, NULL) == FALSE) {
+ g_free (out);
+ g_free (cmd);
+ return NULL;
+ }
+ g_free (cmd);
+
+ /* 192.168.1.1 dev eth0 lladdr 00:00:00:00:00:00 STALE */
+ split = g_strsplit (out, " ", -1);
+ g_free (out);
+
+ if (split == NULL)
+ return NULL;
+ if (g_strv_length (split) != 6) {
+ g_strfreev (split);
+ return NULL;
+ }
+ mac = g_strdup (split[4]);
+ g_strfreev (split);
+
+ return _mac_strup (mac);
+}
+
+static char *
+_mac_strup (char *mac)
+{
+ guint i;
+
+ g_assert (mac != NULL);
+
+ for (i = 0; mac[i] != '\0' ; i++) {
+ if (g_ascii_isalpha (mac[i]))
+ mac[i] = g_ascii_toupper (mac[i]);
+ }
+ return mac;
+}
+
+static GeoclueNetworkStatus
+connmanstatus_to_geocluenetworkstatus (const gchar *status)
+{
+ if (g_strcmp0 (status, "online")) {
+ return GEOCLUE_CONNECTIVITY_OFFLINE;
+ } else {
+ return GEOCLUE_CONNECTIVITY_ONLINE;
+ }
+}
+
+static gchar *
+_get_gateway (GeoclueConnman *self,
+ const gchar *service)
+{
+ DBusGProxy *proxy = NULL;
+ GHashTable *props = NULL;
+ gchar *gateway = NULL;
+ const GHashTable *ht = NULL;
+ const GValue *value = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+
+ /* Create proxy. */
+ proxy = dbus_g_proxy_new_for_name (self->conn,
+ CONNMAN_SERVICE,
+ service,
+ CONNMAN_SERVICE_INTERFACE);
+ if (proxy == NULL) {
+ g_warning ("%s was unable to create connection to Service iface.",
+ G_OBJECT_TYPE_NAME (self));
+ return NULL;
+ }
+
+ /* Get Service properties to get the gateway address. */
+ if (dbus_g_proxy_call (proxy, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &props,
+ G_TYPE_INVALID)) {
+
+ /* Get the mac of the connected router. */
+ value = g_hash_table_lookup (props, "IPv4");
+ if (value != NULL) {
+ ht = g_value_get_boxed (value);
+ value = g_hash_table_lookup ((GHashTable *) ht, "Gateway");
+ if (value != NULL) {
+ gateway = g_value_dup_string (value);
+ }
+ }
+ } else {
+ msg = "Error getting Service properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ /* Free */
+ g_hash_table_destroy (props);
+ g_object_unref (proxy);
+
+ return gateway;
+}
+
+static void
+_get_aps_info (GeoclueConnman *self,
+ const gchar *network,
+ GHashTable **out)
+{
+ DBusGProxy *proxy = NULL;
+ GHashTable *props = NULL;
+ gchar *ap_mac = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+ int strength;
+
+ g_assert (out != NULL);
+
+ /* Create proxy. */
+ proxy = dbus_g_proxy_new_for_name (self->conn,
+ CONNMAN_SERVICE,
+ network,
+ CONNMAN_NETWORK_INTERFACE);
+ if (proxy == NULL) {
+ g_warning ("%s was unable to create connection to Network iface.",
+ G_OBJECT_TYPE_NAME (self));
+ return;
+ }
+
+ /* Collect available APs into a HasTable. */
+ if (dbus_g_proxy_call (proxy, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &props,
+ G_TYPE_INVALID)) {
+
+ /* Store the AP information. */
+ ap_mac = g_value_dup_string (g_hash_table_lookup (props, "Address"));
+ strength = g_value_get_uchar (g_hash_table_lookup (props, "Strength"));
+ if (ap_mac != NULL) {
+ /* Create storage for the first case. */
+ if (*out == NULL) {
+ *out = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, NULL);
+ }
+ g_hash_table_insert (*out, ap_mac,
+ GINT_TO_POINTER (_strength_to_dbm (strength)));
+ }
+ } else {
+ msg = "Error getting Network properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ /* Free */
+ g_hash_table_destroy (props);
+ g_object_unref (proxy);
+}
+
+static void
+_get_best_ap (GeoclueConnman *self,
+ const gchar *network)
+{
+ DBusGProxy *proxy = NULL;
+ GHashTable *props = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+ int strength;
+
+ /* Create proxy. */
+ proxy = dbus_g_proxy_new_for_name (self->conn,
+ CONNMAN_SERVICE,
+ network,
+ CONNMAN_NETWORK_INTERFACE);
+
+ if (proxy == NULL) {
+ g_warning ("%s was unable to create connection to Network iface.",
+ G_OBJECT_TYPE_NAME (self));
+ return;
+ }
+
+ /* Evaluate Network properties and update best AP. */
+ if (dbus_g_proxy_call (proxy, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &props,
+ G_TYPE_INVALID)) {
+
+ strength = g_value_get_uchar (g_hash_table_lookup (props, "Strength"));
+ if (strength > self->ap_strength) {
+ g_free (self->cache_ap_mac);
+ self->cache_ap_mac = g_value_dup_string (g_hash_table_lookup (props, "Address"));
+ self->ap_strength = strength;
+ }
+ } else {
+ msg = "Error getting Network properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ /* Free */
+ g_hash_table_destroy (props);
+ g_object_unref (proxy);
+}
+
+static const GPtrArray *
+_get_networks (GeoclueConnman *self,
+ GHashTable **props,
+ const gchar *device,
+ const gchar *type_filter)
+{
+ DBusGProxy *proxy = NULL;
+ const GPtrArray *nets = NULL;
+ const GValue *value = NULL;
+ const gchar *type = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+
+ /* Create proxy. */
+ proxy = dbus_g_proxy_new_for_name (self->conn,
+ CONNMAN_SERVICE,
+ device,
+ CONNMAN_DEVICE_INTERFACE);
+
+ if (proxy == NULL) {
+ g_warning ("%s was unable to create connection to Device iface.",
+ G_OBJECT_TYPE_NAME (self));
+ return NULL;
+ }
+
+ /* Get available Networks for a specific Device. */
+ if (dbus_g_proxy_call (proxy, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ props,
+ G_TYPE_INVALID)) {
+
+ /* Check only specific networks. */
+ if (type_filter != NULL) {
+ type = g_value_get_string (g_hash_table_lookup (*props, "Type"));
+ if (g_strcmp0 (type, type_filter)) {
+ goto frees;
+ }
+ }
+ value = g_hash_table_lookup (*props, "Networks");
+ nets = g_value_get_boxed (value);
+ } else {
+ msg = "Error getting Device properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ /* Free */
+ frees:
+ g_object_unref (proxy);
+
+ return nets;
+}
+
+static const GPtrArray *
+_get_devices (GeoclueConnman *self,
+ GHashTable **props,
+ const gchar *technology)
+{
+ DBusGProxy *proxy = NULL;
+ const GPtrArray *devs = NULL;
+ const GValue *value = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+
+ /* Create proxy. */
+ proxy = dbus_g_proxy_new_for_name (self->conn,
+ CONNMAN_SERVICE,
+ technology,
+ CONNMAN_TECHNOLOGY_INTERFACE);
+
+ if (proxy == NULL) {
+ g_warning ("%s was unable to create connection to Technology iface.",
+ G_OBJECT_TYPE_NAME (self));
+ return NULL;
+ }
+
+ /* Get available Devices for a specific Technology. */
+ if (dbus_g_proxy_call (proxy, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ props,
+ G_TYPE_INVALID)) {
+
+ value = g_hash_table_lookup (*props, "Devices");
+ devs = g_value_get_boxed (value);
+ } else {
+ msg = "Error getting Technologies properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ /* Free */
+ g_object_unref (proxy);
+
+ return devs;
+}
+
+static const GPtrArray *
+_get_technologies (GeoclueConnman *self,
+ GHashTable **props)
+{
+ const GPtrArray *techs = NULL;
+ const GValue *value = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+
+ /* Get available technologies (Wifi, Eth, ...). */
+ if (dbus_g_proxy_call (self->client, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ props,
+ G_TYPE_INVALID)) {
+
+ value = g_hash_table_lookup (*props, "Technologies");
+ techs = g_value_get_boxed (value);
+ } else {
+ msg = "Error getting Manager properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ return techs;
+}
+
+static const GPtrArray *
+_get_services (GeoclueConnman *self,
+ GHashTable **props)
+{
+ const GPtrArray *servs = NULL;
+ const GValue *value = NULL;
+ const gchar *msg = NULL;
+ GError *error = NULL;
+
+ /* Get available services. */
+ if (dbus_g_proxy_call (self->client, "GetProperties",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ props,
+ G_TYPE_INVALID)) {
+
+ value = g_hash_table_lookup (*props, "Services");
+ servs = g_value_get_boxed (value);
+ } else {
+ msg = "Error getting Manager properties: %s";
+ if (error != NULL) {
+ g_warning (msg, error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, "Unknown error");
+ }
+ }
+
+ return servs;
+}
+
+static void
+_explore_available_aps (GeoclueConnman *self,
+ ConnmanFunc func,
+ gpointer out)
+{
+ GHashTable *mgr_props = NULL;
+ GHashTable *tech_props = NULL;
+ GHashTable *dev_props = NULL;
+ const GPtrArray *techs = NULL;
+ const GPtrArray *devs = NULL;
+ const GPtrArray *nets = NULL;
+ const gchar *tech = NULL;
+ const gchar *dev = NULL;
+ const gchar *net = NULL;
+ guint i, j, k;
+
+ techs = _get_technologies (self, &mgr_props);
+ if (techs == NULL) {
+ goto frees;
+ }
+ for (i = 0; i < techs->len; i++) {
+ tech = g_ptr_array_index (techs, i);
+ devs = _get_devices (self, &tech_props, tech);
+ if (devs == NULL) {
+ continue;
+ }
+ for (j = 0; j < devs->len; j++) {
+ dev = g_ptr_array_index (devs, j);
+ nets = _get_networks (self, &dev_props, dev, "wifi");
+ if (nets == NULL) {
+ continue;
+ }
+ for (k = 0; k < nets->len; k++) {
+ net = g_ptr_array_index (nets, k);
+
+ /* Perform specific actions. */
+ func (self, net, out);
+ }
+ }
+ }
+
+ /* Free */
+ frees:
+ if (mgr_props != NULL) {
+ g_hash_table_destroy (mgr_props);
+ }
+ if (tech_props != NULL) {
+ g_hash_table_destroy (tech_props);
+ }
+ if (dev_props != NULL) {
+ g_hash_table_destroy (dev_props);
+ }
+}
+
+static void
+_cache_ap_mac (GeoclueConnman *self)
+{
+ /* Cleanup the cache. */
+ g_free (self->cache_ap_mac);
+ self->cache_ap_mac = NULL;
+ self->ap_strength = 0;
+
+ /* Explore the active networks to get the best AP. */
+ _explore_available_aps (self, (ConnmanFunc) _get_best_ap, NULL);
+}
+
+
+
+static void
+_geoclue_connman_state_changed (DBusGProxy *proxy,
+ const gchar *status,
+ gpointer userdata)
+{
+ GeoclueConnman *self = GEOCLUE_CONNMAN (userdata);
+ GeoclueNetworkStatus gc_status;
+
+ gc_status = connmanstatus_to_geocluenetworkstatus (status);
+
+ if (gc_status != self->status) {
+ /* Update status. */
+ self->status = gc_status;
+
+ /* Update AP cache. */
+ _cache_ap_mac (self);
+
+ /* Notification. */
+ geoclue_connectivity_emit_status_changed (GEOCLUE_CONNECTIVITY (self),
+ self->status);
+ }
+}
+
+
+static void
+_method_call_notify_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ gpointer user_data)
+{
+ GeoclueConnman *self = GEOCLUE_CONNMAN (user_data);
+ const gchar *msg = NULL;
+ GError *error = NULL;
+ gchar *state = NULL;
+
+ /* Collect output data. */
+ if (dbus_g_proxy_end_call (proxy,
+ call,
+ &error,
+ G_TYPE_STRING,
+ &state,
+ G_TYPE_INVALID)) {
+
+ /* Set current status. */
+ _geoclue_connman_state_changed (proxy,
+ (const gchar *) state,
+ self);
+ } else {
+ msg = "%s was unable to get the current network status: %s.";
+ if (error != NULL) {
+ g_warning (msg, G_OBJECT_TYPE_NAME (self),
+ error->message);
+ g_error_free (error);
+ } else {
+ g_warning (msg, G_OBJECT_TYPE_NAME (self),
+ "Unknown error");
+ }
+ }
+
+ /* Free */
+ g_free (state);
+}
+
+static void
+geoclue_connman_init (GeoclueConnman *self)
+{
+ GError *error = NULL;
+
+ /* Get DBus connection to the System bus. */
+ self->conn = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (self->conn == NULL) {
+ g_warning ("%s was unable to create a connection to D-Bus: %s",
+ G_OBJECT_TYPE_NAME (self), error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* Create proxy. */
+ self->client = dbus_g_proxy_new_for_name (self->conn,
+ CONNMAN_SERVICE,
+ CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE);
+
+ if (self->client == NULL) {
+ g_warning ("%s was unable to create connection to Connman Manager.",
+ G_OBJECT_TYPE_NAME (self));
+ return;
+ }
+
+ /* Get current state (async). */
+ dbus_g_proxy_begin_call (self->client, "GetState",
+ _method_call_notify_cb,
+ self,
+ NULL,
+ G_TYPE_INVALID,
+ G_TYPE_STRING);
+
+ /* Be aware of State changes. */
+ dbus_g_proxy_add_signal (self->client, "StateChanged",
+ G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (self->client,
+ "StateChanged",
+ G_CALLBACK (_geoclue_connman_state_changed),
+ self,
+ NULL);
+}
+
+
+static void
+geoclue_connman_connectivity_init (GeoclueConnectivityInterface *iface)
+{
+ iface->get_status = _get_status;
+ iface->get_ap_mac = _get_ap_mac;
+ iface->get_router_mac = _get_router_mac;
+ iface->get_aps = _get_aps;
+}
+
+#endif /* HAVE_CONNMAN*/
diff --git a/src/connectivity-connman.h b/src/connectivity-connman.h
new file mode 100644
index 0000000..24c5907
--- /dev/null
+++ b/src/connectivity-connman.h
@@ -0,0 +1,56 @@
+/*
+ * Geoclue
+ * connectivity-connman.h
+ *
+ * Author: Javier Fernandez <jfernandez@igalia.com>
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _CONNECTIVITY_CONNMAN_H
+#define _CONNECTIVITY_CONNMAN_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "connectivity.h"
+
+G_BEGIN_DECLS
+
+#define GEOCLUE_TYPE_CONNMAN (geoclue_connman_get_type ())
+#define GEOCLUE_CONNMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_CONNMAN, GeoclueConnman))
+
+typedef struct {
+ GObject parent;
+
+ /* private */
+ GeoclueNetworkStatus status;
+ DBusGConnection *conn;
+ DBusGProxy *client;
+ gchar *cache_ap_mac;
+ int ap_strength;
+} GeoclueConnman;
+
+typedef struct {
+ GObjectClass parent_class;
+} GeoclueConnmanClass;
+
+GType geoclue_connman_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/connectivity.c b/src/connectivity.c
index 4efc865..96d83ab 100644
--- a/src/connectivity.c
+++ b/src/connectivity.c
@@ -34,6 +34,10 @@
#else
#ifdef HAVE_CONIC
#include "connectivity-conic.h"
+#else
+#ifdef HAVE_CONNMAN
+#include "connectivity-connman.h"
+#endif
#endif
#endif
@@ -96,6 +100,10 @@ geoclue_connectivity_new (void)
#else
#ifdef HAVE_CONIC
connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_CONIC, NULL));
+#else
+#ifdef HAVE_CONNMAN
+ connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_CONNMAN, NULL));
+#endif
#endif
#endif
return connectivity;
diff --git a/src/master.c b/src/master.c
index 4f2ef28..7877e61 100644
--- a/src/master.c
+++ b/src/master.c
@@ -37,6 +37,10 @@
#else
#ifdef HAVE_CONIC
#include "connectivity-conic.h"
+#else
+#ifdef HAVE_CONNMAN
+#include "connectivity-connman.h"
+#endif
#endif
#endif