summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-07-03 18:12:13 -0500
committerDan Williams <dcbw@redhat.com>2014-07-03 18:50:41 -0500
commita949c38d8e247d16ec99f14c53b2781e71de6dcf (patch)
tree6a4a8e9fe5290c827f13090475f6afd5297e4a52
parent3ee9c3be57610e613a57f585f15a9afd2a2b4999 (diff)
downloadNetworkManager-a949c38d8e247d16ec99f14c53b2781e71de6dcf.tar.gz
bluez: handle Bluez4 PropertyChanged events
The addition of Bluez5 support mistakenly broke support for Bluez4 property change events. Bluez4 uses a custom D-Bus interface that we must explicitly handle. This caused NM to ignore BT devices immediately after pairing, since the UUIDs only show up through a custom Bluez4 PropertyChanged even when pairing is complete. Only then do we finally know priv->capabilities, and only then is the NMBluezDevice usable.
-rw-r--r--src/devices/bluetooth/nm-bluez-device.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index 5630727b7e..f493b77bcb 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -761,6 +761,23 @@ adapter5_on_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
}
static void
+_take_one_variant_property (NMBluezDevice *self, const char *property, GVariant *v)
+{
+ if (v) {
+ if (!g_strcmp0 (property, "Address"))
+ _take_variant_property_address (self, v);
+ else if (!g_strcmp0 (property, "Connected"))
+ _take_variant_property_connected (self, v);
+ else if (!g_strcmp0 (property, "Name"))
+ _take_variant_property_name (self, v);
+ else if (!g_strcmp0 (property, "UUIDs"))
+ _take_variant_property_uuids (self, v);
+ else
+ g_variant_unref (v);
+ }
+}
+
+static void
_set_properties (NMBluezDevice *self, GVariant *properties)
{
GVariantIter i;
@@ -769,20 +786,8 @@ _set_properties (NMBluezDevice *self, GVariant *properties)
g_object_freeze_notify (G_OBJECT (self));
g_variant_iter_init (&i, properties);
- while (g_variant_iter_next (&i, "{&sv}", &property, &v)) {
- if (!property) {
- g_variant_unref (v);
- } else if (!strcmp (property, "Address")) {
- _take_variant_property_address (self, v);
- } else if (!strcmp (property, "Connected")) {
- _take_variant_property_connected (self, v);
- } else if (!strcmp (property, "Name")) {
- _take_variant_property_name (self, v);
- } else if (!strcmp (property, "UUIDs")) {
- _take_variant_property_uuids (self, v);
- } else
- g_variant_unref (v);
- }
+ while (g_variant_iter_next (&i, "{&sv}", &property, &v))
+ _take_one_variant_property (self, property, v);
g_object_thaw_notify (G_OBJECT (self));
}
@@ -795,10 +800,27 @@ properties_changed (GDBusProxy *proxy,
NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);
_set_properties (self, changed_properties);
-
check_emit_usable (self);
}
+static void
+bluez4_property_changed (GDBusProxy *proxy,
+ const char *sender,
+ const char *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);
+
+ if (g_strcmp0 (signal_name, "PropertyChanged") == 0) {
+ const char *property = NULL;
+ GVariant *v = NULL;
+
+ g_variant_get (parameters, "(&sv)", &property, &v);
+ _take_one_variant_property (self, property, v);
+ check_emit_usable (self);
+ }
+}
static void
get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_data)
@@ -843,7 +865,6 @@ END:
g_object_unref (self);
}
-
static void
query_properties (NMBluezDevice *self)
{
@@ -903,6 +924,11 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
} else {
g_signal_connect (priv->proxy, "g-properties-changed",
G_CALLBACK (properties_changed), self);
+ if (priv->bluez_version == 4) {
+ /* Watch for custom Bluez4 PropertyChanged signals */
+ g_signal_connect (priv->proxy, "g-signal",
+ G_CALLBACK (bluez4_property_changed), self);
+ }
query_properties (self);
}
@@ -1050,6 +1076,8 @@ finalize (GObject *object)
g_free (priv->name);
g_free (priv->bt_iface);
+ if (priv->proxy)
+ g_signal_handlers_disconnect_by_data (priv->proxy, object);
g_clear_object (&priv->proxy);
G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object);