about summary refs log tree commit diff
path: root/src/devices/bluetooth/nm-bluez4-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bluetooth/nm-bluez4-manager.c')
-rw-r--r--src/devices/bluetooth/nm-bluez4-manager.c154
1 files changed, 105 insertions, 49 deletions
diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c
index a9079a2f..1fe02f18 100644
--- a/src/devices/bluetooth/nm-bluez4-manager.c
+++ b/src/devices/bluetooth/nm-bluez4-manager.c
@@ -47,6 +47,7 @@ typedef struct {
 	NMSettings *settings;
 
 	GDBusProxy *proxy;
+	GCancellable *proxy_cancellable;
 
 	NMBluez4Adapter *adapter;
 } NMBluez4ManagerPrivate;
@@ -66,6 +67,11 @@ G_DEFINE_TYPE (NMBluez4Manager, nm_bluez4_manager, G_TYPE_OBJECT)
 
 /*****************************************************************************/
 
+#define _NMLOG_DOMAIN      LOGD_BT
+#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-manager", __VA_ARGS__)
+
+/*****************************************************************************/
+
 static void
 emit_bdaddr_added (NMBluez4Manager *self, NMBluezDevice *device)
 {
@@ -119,8 +125,10 @@ adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_d
 			emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data));
 		g_slist_free (devices);
 
-		g_signal_connect (adapter, "device-added", G_CALLBACK (device_added), self);
-		g_signal_connect (adapter, "device-removed", G_CALLBACK (device_removed), self);
+		g_signal_connect (adapter, NM_BLUEZ4_ADAPTER_DEVICE_ADDED,
+		                  G_CALLBACK (device_added), self);
+		g_signal_connect (adapter, NM_BLUEZ4_ADAPTER_DEVICE_REMOVED,
+		                  G_CALLBACK (device_removed), self);
 	} else {
 		g_object_unref (priv->adapter);
 		priv->adapter = NULL;
@@ -169,49 +177,70 @@ default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *s
 	/* Add the new default adapter */
 	if (path) {
 		priv->adapter = nm_bluez4_adapter_new (path, priv->settings);
-		g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self);
+		g_signal_connect (priv->adapter, NM_BLUEZ4_ADAPTER_INITIALIZED,
+		                  G_CALLBACK (adapter_initialized), self);
 	}
 }
 
 static void
 default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
-	NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
-	GVariant *ret;
-	GError *err = NULL;
+	NMBluez4Manager *self;
+	NMBluez4ManagerPrivate *priv;
+	gs_unref_variant GVariant *ret = NULL;
+	gs_free_error GError *error = NULL;
+	const char *default_adapter;
 
 	ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
-	                                  G_VARIANT_TYPE ("(o)"), &err);
-	if (ret) {
-		const char *default_adapter;
+	                                  G_VARIANT_TYPE ("(o)"), &error);
+	if (   !ret
+	    && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
 
-		g_variant_get (ret, "(&o)", &default_adapter);
-		default_adapter_changed (priv->proxy, default_adapter, self);
-		g_variant_unref (ret);
-	} else {
+	self = NM_BLUEZ4_MANAGER (user_data);
+	priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
+
+	g_clear_object (&priv->proxy_cancellable);
+
+	if (!ret) {
 		/* Ignore "No such adapter" errors; just means bluetooth isn't active */
-		if (   !_nm_dbus_error_has_name (err, "org.bluez.Error.NoSuchAdapter")
-		    && !_nm_dbus_error_has_name (err, "org.freedesktop.systemd1.LoadFailed")
-		    && !g_error_matches (err, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
-			g_dbus_error_strip_remote_error (err);
-			nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s",
-			             err->message);
+		if (   !_nm_dbus_error_has_name (error, "org.bluez.Error.NoSuchAdapter")
+		    && !_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")
+		    && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
+			g_dbus_error_strip_remote_error (error);
+			_LOGW ("bluez error getting default adapter: %s",
+			       error->message);
 		}
-		g_error_free (err);
+		return;
 	}
+
+	g_variant_get (ret, "(&o)", &default_adapter);
+	default_adapter_changed (priv->proxy, default_adapter, self);
 }
 
 static void
-query_default_adapter (NMBluez4Manager *self)
+name_owner_changed (NMBluez4Manager *self)
 {
 	NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
+	gs_free char *owner = NULL;
+
+	nm_clear_g_cancellable (&priv->proxy_cancellable);
+
+	owner = g_dbus_proxy_get_name_owner (priv->proxy);
+	if (!owner) {
+		/* Throwing away the adapter removes all devices too */
+		g_clear_object (&priv->adapter);
+		return;
+	}
+
+	priv->proxy_cancellable = g_cancellable_new ();
 
 	g_dbus_proxy_call (priv->proxy, "DefaultAdapter",
 	                   NULL,
 	                   G_DBUS_CALL_FLAGS_NONE, -1,
-	                   NULL,
-	                   default_adapter_cb, self);
+	                   priv->proxy_cancellable,
+	                   default_adapter_cb,
+	                   self);
 }
 
 static void
@@ -219,34 +248,35 @@ name_owner_changed_cb (GObject *object,
                        GParamSpec *pspec,
                        gpointer user_data)
 {
-	NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
-	NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
-	char *owner;
-
-	owner = g_dbus_proxy_get_name_owner (priv->proxy);
-	if (owner) {
-		query_default_adapter (self);
-		g_free (owner);
-	} else {
-		/* Throwing away the adapter removes all devices too */
-		g_clear_object (&priv->adapter);
-	}
+	name_owner_changed (user_data);
 }
 
-/*****************************************************************************/
-
 static void
-nm_bluez4_manager_init (NMBluez4Manager *self)
+_proxy_new_cb (GObject *source_object,
+               GAsyncResult *result,
+               gpointer user_data)
 {
-	NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
+	NMBluez4Manager *self;
+	NMBluez4ManagerPrivate *priv;
+	gs_free_error GError *error = NULL;
+	GDBusProxy *proxy;
+
+	proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
+	if (   !proxy
+	    && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = user_data;
+	priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
+
+	if (!proxy) {
+		_LOGW ("bluez error creating D-Bus proxy: %s", error->message);
+		g_clear_object (&priv->proxy_cancellable);
+		return;
+	}
+
+	priv->proxy = proxy;
 
-	priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-	                                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
-	                                             NULL,
-	                                             BLUEZ_SERVICE,
-	                                             BLUEZ_MANAGER_PATH,
-	                                             BLUEZ4_MANAGER_INTERFACE,
-	                                             NULL, NULL);
 	_nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"),
 	                         G_CALLBACK (adapter_removed), self);
 	_nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"),
@@ -254,7 +284,27 @@ nm_bluez4_manager_init (NMBluez4Manager *self)
 	g_signal_connect (priv->proxy, "notify::g-name-owner",
 	                  G_CALLBACK (name_owner_changed_cb), self);
 
-	query_default_adapter (self);
+	name_owner_changed (self);
+}
+
+/*****************************************************************************/
+
+static void
+nm_bluez4_manager_init (NMBluez4Manager *self)
+{
+	NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
+
+	priv->proxy_cancellable = g_cancellable_new ();
+
+	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+	                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+	                          NULL,
+	                          NM_BLUEZ_SERVICE,
+	                          NM_BLUEZ_MANAGER_PATH,
+	                          NM_BLUEZ4_MANAGER_INTERFACE,
+	                          priv->proxy_cancellable,
+	                          _proxy_new_cb,
+	                          self);
 }
 
 NMBluez4Manager *
@@ -275,7 +325,13 @@ dispose (GObject *object)
 	NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object);
 	NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
 
-	g_clear_object (&priv->proxy);
+	nm_clear_g_cancellable (&priv->proxy_cancellable);
+
+	if (priv->proxy) {
+		g_signal_handlers_disconnect_by_data (priv->proxy, self);
+		g_clear_object (&priv->proxy);
+	}
+
 	g_clear_object (&priv->adapter);
 
 	G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object);