From f422acc9d3dac9667f6c17da3e5a534c565d3ab4 Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Thu, 30 May 2013 10:33:43 +0200 Subject: [PATCH 01/29] bluez: pass the NMBluezDevice down to the NMDeviceBt So that the latter can use the former instead of listening for changes over dbus. --- src/bluez-manager/nm-bluez-manager.c | 4 +++- src/devices/nm-device-bt.c | 25 ++++++++++++++++++++++++- src/devices/nm-device-bt.h | 5 ++++- src/nm-manager.c | 5 ++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c index 78a41f8527..81dfe940ae 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-manager.c @@ -61,6 +61,7 @@ static void emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) { g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, nm_bluez_device_get_address (device), nm_bluez_device_get_name (device), nm_bluez_device_get_path (device), @@ -370,7 +371,8 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), NULL, NULL, NULL, - G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); signals[BDADDR_REMOVED] = g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index 09c1284c42..ae8707bf53 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -29,6 +29,7 @@ #include "nm-glib-compat.h" #include "nm-bluez-common.h" +#include "nm-bluez-device.h" #include "nm-dbus-manager.h" #include "nm-device-bt.h" #include "nm-device-private.h" @@ -61,6 +62,8 @@ typedef struct { guint mm_watch_id; gboolean mm_running; + NMBluezDevice *bt_device; + char *bdaddr; char *name; guint32 capabilities; @@ -82,6 +85,7 @@ enum { PROP_0, PROP_BT_NAME, PROP_BT_CAPABILITIES, + PROP_BT_DEVICE, LAST_PROP }; @@ -1111,7 +1115,8 @@ mm_name_owner_changed (NMDBusManager *dbus_mgr, /*****************************************************************************/ NMDevice * -nm_device_bt_new (const char *udi, +nm_device_bt_new (NMBluezDevice *bt_device, + const char *udi, const char *bdaddr, const char *name, guint32 capabilities) @@ -1120,12 +1125,14 @@ nm_device_bt_new (const char *udi, g_return_val_if_fail (bdaddr != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL); + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (bt_device), NULL); return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT, NM_DEVICE_UDI, udi, NM_DEVICE_IFACE, bdaddr, NM_DEVICE_DRIVER, "bluez", NM_DEVICE_HW_ADDRESS, bdaddr, + NM_DEVICE_BT_DEVICE, bt_device, NM_DEVICE_BT_NAME, name, NM_DEVICE_BT_CAPABILITIES, capabilities, NM_DEVICE_TYPE_DESC, "Bluetooth", @@ -1185,6 +1192,10 @@ set_property (GObject *object, guint prop_id, /* Construct only */ priv->capabilities = g_value_get_uint (value); break; + case PROP_BT_DEVICE: + /* Construct only */ + priv->bt_device = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1204,6 +1215,9 @@ get_property (GObject *object, guint prop_id, case PROP_BT_CAPABILITIES: g_value_set_uint (value, priv->capabilities); break; + case PROP_BT_DEVICE: + g_value_set_object (value, priv->bt_device); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1229,6 +1243,7 @@ dispose (GObject *object) g_clear_object (&priv->type_proxy); g_clear_object (&priv->dev_proxy); g_clear_object (&priv->modem); + g_clear_object (&priv->bt_device); G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object); } @@ -1289,6 +1304,14 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) NM_BT_CAPABILITY_NONE, G_MAXUINT, NM_BT_CAPABILITY_NONE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property + (object_class, PROP_BT_DEVICE, + g_param_spec_object (NM_DEVICE_BT_DEVICE, + "NMBluezDevice object for the Device", + "NMBluezDevice object for the Device", + NM_TYPE_BLUEZ_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /* Signals */ signals[PPP_STATS] = g_signal_new ("ppp-stats", diff --git a/src/devices/nm-device-bt.h b/src/devices/nm-device-bt.h index bcc9f822bc..d983285fb7 100644 --- a/src/devices/nm-device-bt.h +++ b/src/devices/nm-device-bt.h @@ -22,6 +22,7 @@ #define NM_DEVICE_BT_H #include +#include "nm-bluez-device.h" #include "nm-modem.h" G_BEGIN_DECLS @@ -41,6 +42,7 @@ typedef enum { #define NM_DEVICE_BT_NAME "name" #define NM_DEVICE_BT_CAPABILITIES "bt-capabilities" +#define NM_DEVICE_BT_DEVICE "bt-device" typedef struct { NMDevice parent; @@ -55,7 +57,8 @@ typedef struct { GType nm_device_bt_get_type (void); -NMDevice *nm_device_bt_new (const char *udi, +NMDevice *nm_device_bt_new (NMBluezDevice *bt_device, + const char *udi, const char *bdaddr, const char *name, guint32 capabilities); diff --git a/src/nm-manager.c b/src/nm-manager.c index 11e3b5e0b1..f395f03302 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -139,6 +139,7 @@ static void impl_manager_check_connectivity (NMManager *manager, #include "nm-manager-glue.h" static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, + NMBluezDevice *bt_device, const char *bdaddr, const char *name, const char *object_path, @@ -2184,6 +2185,7 @@ add_device (NMManager *self, NMDevice *device) static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, + NMBluezDevice *bt_device, const char *bdaddr, const char *name, const char *object_path, @@ -2198,12 +2200,13 @@ bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, g_return_if_fail (name != NULL); g_return_if_fail (object_path != NULL); g_return_if_fail (capabilities != NM_BT_CAPABILITY_NONE); + g_return_if_fail (NM_IS_BLUEZ_DEVICE (bt_device)); /* Make sure the device is not already in the device list */ if (nm_manager_get_device_by_udi (manager, object_path)) return; - device = nm_device_bt_new (object_path, bdaddr, name, capabilities); + device = nm_device_bt_new (bt_device, object_path, bdaddr, name, capabilities); if (device) { nm_log_info (LOGD_HW, "BT device %s (%s) added (%s%s%s)", name, From 180503eb1a74b11bc5c0f166f518c8b53cbc88c4 Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Thu, 30 May 2013 10:42:14 +0200 Subject: [PATCH 02/29] bluez: listen to Connected changes in NMBluezDevice --- src/bluez-manager/nm-bluez-device.c | 27 +++++++++++++++++++++++++++ src/bluez-manager/nm-bluez-device.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 83175da154..ba7403addf 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -48,6 +48,7 @@ typedef struct { char *name; guint32 capabilities; gint rssi; + gboolean connected; NMConnectionProvider *provider; GSList *connections; @@ -62,6 +63,7 @@ enum { PROP_CAPABILITIES, PROP_RSSI, PROP_USABLE, + PROP_CONNECTED, LAST_PROP }; @@ -131,6 +133,14 @@ nm_bluez_device_get_rssi (NMBluezDevice *self) return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; } +gboolean +nm_bluez_device_get_connected (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; +} + static void check_emit_usable (NMBluezDevice *self) { @@ -297,6 +307,12 @@ property_changed (DBusGProxy *proxy, priv->capabilities = uint_val; g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); } + } else if (!strcmp (property, "Connected")) { + gboolean connected = g_value_get_boolean (value); + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } } check_emit_usable (self); @@ -494,6 +510,9 @@ get_property (GObject *object, guint prop_id, case PROP_USABLE: g_value_set_boolean (value, priv->usable); break; + case PROP_CONNECTED: + g_value_set_boolean (value, priv->connected); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -579,6 +598,14 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) FALSE, G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_CONNECTED, + g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, + "Connected", + "Connected", + FALSE, + G_PARAM_READABLE)); + /* Signals */ signals[INITIALIZED] = g_signal_new ("initialized", G_OBJECT_CLASS_TYPE (object_class), diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index 18f9fc30a6..e659dce7ef 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -40,6 +40,7 @@ #define NM_BLUEZ_DEVICE_CAPABILITIES "capabilities" #define NM_BLUEZ_DEVICE_RSSI "rssi" #define NM_BLUEZ_DEVICE_USABLE "usable" +#define NM_BLUEZ_DEVICE_CONNECTED "connected" typedef struct { GObject parent; @@ -74,5 +75,7 @@ guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); gint nm_bluez_device_get_rssi (NMBluezDevice *self); +gboolean nm_bluez_device_get_connected (NMBluezDevice *self); + #endif /* NM_BLUEZ_DEVICE_H */ From 4be056f5046e4531baae51f381222759e4e461b8 Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Thu, 30 May 2013 10:56:59 +0200 Subject: [PATCH 03/29] bluez: listen to Connected changes through NMBluezDevice --- src/devices/nm-device-bt.c | 62 ++++++++++---------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index ae8707bf53..1350a6ebdc 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -69,10 +69,10 @@ typedef struct { guint32 capabilities; gboolean connected; + guint32 connected_id; gboolean have_iface; DBusGProxy *type_proxy; - DBusGProxy *dev_proxy; char *rfcomm_iface; NMModem *modem; @@ -759,33 +759,17 @@ bluez_connect_cb (DBusGProxy *proxy, } static void -bluez_property_changed (DBusGProxy *proxy, - const char *property, - GValue *value, - gpointer user_data) +bluez_connected_changed (NMBluezDevice *bt_device, + GParamSpec *pspec, + NMDevice *device) { - NMDevice *device = NM_DEVICE (user_data); - NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); gboolean connected; NMDeviceState state; - const char *prop_str = "(unknown)"; - - if (G_VALUE_HOLDS_STRING (value)) - prop_str = g_value_get_string (value); - else if (G_VALUE_HOLDS_BOOLEAN (value)) - prop_str = g_value_get_boolean (value) ? "true" : "false"; - - nm_log_dbg (LOGD_BT, "(%s): bluez property '%s' changed to '%s'", - nm_device_get_iface (device), - property, - prop_str); - - if (strcmp (property, "Connected")) - return; state = nm_device_get_state (device); - connected = g_value_get_boolean (value); + connected = nm_bluez_device_get_connected (bt_device); if (connected) { if (state == NM_DEVICE_STATE_CONFIG) { nm_log_dbg (LOGD_BT, "(%s): connected to the device", @@ -861,24 +845,6 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) g_assert_not_reached (); bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - priv->dev_proxy = dbus_g_proxy_new_for_name (bus, - BLUEZ_SERVICE, - nm_device_get_udi (device), - BLUEZ_DEVICE_INTERFACE); - if (!priv->dev_proxy) { - // FIXME: set a reason code - return NM_ACT_STAGE_RETURN_FAILURE; - } - - /* Watch for BT device property changes */ - dbus_g_object_register_marshaller (g_cclosure_marshal_generic, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_VALUE, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->dev_proxy, "PropertyChanged", - G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->dev_proxy, "PropertyChanged", - G_CALLBACK (bluez_property_changed), device, NULL); priv->type_proxy = dbus_g_proxy_new_for_name (bus, BLUEZ_SERVICE, @@ -991,11 +957,6 @@ deactivate (NMDevice *device) } } - if (priv->dev_proxy) { - g_object_unref (priv->dev_proxy); - priv->dev_proxy = NULL; - } - if (priv->timeout_id) { g_source_remove (priv->timeout_id); priv->timeout_id = 0; @@ -1175,6 +1136,11 @@ constructed (GObject *object) g_assert (my_hwaddr); g_assert_cmpint (my_hwaddr_len, ==, ETH_ALEN); priv->bdaddr = nm_utils_hwaddr_ntoa (my_hwaddr, ARPHRD_ETHER); + + /* Watch for BT device property changes */ + priv->connected_id = g_signal_connect (priv->bt_device, "notify::connected", + G_CALLBACK (bluez_connected_changed), + object); } static void @@ -1234,6 +1200,11 @@ dispose (GObject *object) priv->timeout_id = 0; } + if (priv->connected_id) { + g_source_remove (priv->connected_id); + priv->connected_id = 0; + } + if (priv->dbus_mgr && priv->mm_watch_id) { g_signal_handler_disconnect (priv->dbus_mgr, priv->mm_watch_id); priv->mm_watch_id = 0; @@ -1241,7 +1212,6 @@ dispose (GObject *object) priv->dbus_mgr = NULL; g_clear_object (&priv->type_proxy); - g_clear_object (&priv->dev_proxy); g_clear_object (&priv->modem); g_clear_object (&priv->bt_device); From e45fdcfd2dd3e2e9a6413ac2eaa8ef2b776865d3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 18 Sep 2013 20:08:42 +0200 Subject: [PATCH 04/29] bluez: get rid of connected_id for disconnecting from signal Signed-off-by: Thomas Haller --- src/devices/nm-device-bt.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index 1350a6ebdc..6a066c0eac 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -69,7 +69,6 @@ typedef struct { guint32 capabilities; gboolean connected; - guint32 connected_id; gboolean have_iface; DBusGProxy *type_proxy; @@ -1138,9 +1137,9 @@ constructed (GObject *object) priv->bdaddr = nm_utils_hwaddr_ntoa (my_hwaddr, ARPHRD_ETHER); /* Watch for BT device property changes */ - priv->connected_id = g_signal_connect (priv->bt_device, "notify::connected", - G_CALLBACK (bluez_connected_changed), - object); + g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, + G_CALLBACK (bluez_connected_changed), + object); } static void @@ -1200,10 +1199,9 @@ dispose (GObject *object) priv->timeout_id = 0; } - if (priv->connected_id) { - g_source_remove (priv->connected_id); - priv->connected_id = 0; - } + g_signal_handlers_disconnect_by_func (priv->bt_device, + G_CALLBACK (bluez_connected_changed), + object); if (priv->dbus_mgr && priv->mm_watch_id) { g_signal_handler_disconnect (priv->dbus_mgr, priv->mm_watch_id); From 7aa5128b41cdfdf6c8cd1f96ef4cf01c79b670ba Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Thu, 30 May 2013 12:59:08 +0200 Subject: [PATCH 05/29] bluez: move org.bluez Connection() handling to NMBluezDevice --- src/bluez-manager/nm-bluez-common.h | 3 + src/bluez-manager/nm-bluez-device.c | 123 ++++++++++++++++++++++++++++ src/bluez-manager/nm-bluez-device.h | 16 ++++ src/devices/nm-device-bt.c | 77 ++++------------- 4 files changed, 158 insertions(+), 61 deletions(-) diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h index 612962552f..26ef1e31a7 100644 --- a/src/bluez-manager/nm-bluez-common.h +++ b/src/bluez-manager/nm-bluez-common.h @@ -21,6 +21,9 @@ #ifndef NM_BLUEZ_COMMON_H #define NM_BLUEZ_COMMON_H +#define BLUETOOTH_CONNECT_DUN "dun" +#define BLUETOOTH_CONNECT_NAP "nap" + #define BLUEZ_SERVICE "org.bluez" #define BLUEZ_MANAGER_PATH "/" diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index ba7403addf..434c85ffd3 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -40,6 +41,8 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; DBusGProxy *proxy; + DBusGProxy *type_proxy; + gboolean initialized; gboolean usable; @@ -50,6 +53,8 @@ typedef struct { gint rssi; gboolean connected; + char *rfcomm_iface; + NMConnectionProvider *provider; GSList *connections; } NMBluezDevicePrivate; @@ -246,6 +251,121 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) /***********************************************************/ +void +nm_bluez_device_call_disconnect (NMBluezDevice *self, gboolean dun) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (!priv->type_proxy) + return; + + if (dun) { + /* Don't ever pass NULL through dbus; rfcomm_iface + * might happen to be NULL for some reason. + */ + if (priv->rfcomm_iface) + dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", + G_TYPE_STRING, priv->rfcomm_iface, + G_TYPE_INVALID); + } else { + dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", + G_TYPE_INVALID); + } + + g_clear_object (&priv->type_proxy); +} + +static void +bluez_connect_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + char *device; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, + G_TYPE_STRING, &device, + G_TYPE_INVALID) == FALSE) + g_simple_async_result_take_error (result, error); + else if (!device || !strlen (device)) { + g_simple_async_result_set_error(result, G_IO_ERROR, G_IO_ERROR_FAILED, + "Invalid argument received"); + } else { + g_simple_async_result_set_op_res_gpointer (result, + g_strdup (device), + g_free); + priv->rfcomm_iface = device; + } + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + gboolean dun, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + DBusGConnection *connection; + + connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); + + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); + + priv->type_proxy = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + priv->path, + dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); + if (!priv->type_proxy) + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Unable to create proxy"); + else + dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", + bluez_connect_cb, + simple, + NULL, + 20000, + G_TYPE_STRING, dun ? BLUETOOTH_CONNECT_DUN : BLUETOOTH_CONNECT_NAP, + G_TYPE_INVALID); +} + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + const char *device; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (self), + nm_bluez_device_connect_async), + NULL); + + simple = (GSimpleAsyncResult *) result; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); + return device; +} + +/***********************************************************/ + static guint32 convert_uuids_to_capabilities (const char **strings) { @@ -469,6 +589,8 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); + g_clear_object (&priv->type_proxy); + G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } @@ -480,6 +602,7 @@ finalize (GObject *object) g_free (priv->path); g_free (priv->address); g_free (priv->name); + g_free (priv->rfcomm_iface); g_object_unref (priv->proxy); G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index e659dce7ef..b49f56b5cb 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -23,6 +23,7 @@ #include #include +#include #include "nm-connection.h" #include "nm-connection-provider.h" @@ -77,5 +78,20 @@ gint nm_bluez_device_get_rssi (NMBluezDevice *self); gboolean nm_bluez_device_get_connected (NMBluezDevice *self); +void +nm_bluez_device_connect_async (NMBluezDevice *self, + gboolean dun, + GAsyncReadyCallback callback, + gpointer user_data); + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error); + +void +nm_bluez_device_call_disconnect (NMBluezDevice *self, + gboolean dun); + #endif /* NM_BLUEZ_DEVICE_H */ diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index 6a066c0eac..8b9c704f2f 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -26,6 +26,7 @@ #include #include +#include #include "nm-glib-compat.h" #include "nm-bluez-common.h" @@ -48,8 +49,6 @@ #define MM_OLD_DBUS_SERVICE "org.freedesktop.ModemManager" #define MM_NEW_DBUS_SERVICE "org.freedesktop.ModemManager1" -#define BLUETOOTH_DUN_UUID "dun" -#define BLUETOOTH_NAP_UUID "nap" G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) @@ -71,8 +70,6 @@ typedef struct { gboolean connected; gboolean have_iface; - DBusGProxy *type_proxy; - char *rfcomm_iface; NMModem *modem; guint32 timeout_id; @@ -711,18 +708,19 @@ check_connect_continue (NMDeviceBt *self) } static void -bluez_connect_cb (DBusGProxy *proxy, - DBusGProxyCall *call_id, +bluez_connect_cb (GObject *object, + GAsyncResult *res, void *user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); GError *error = NULL; - char *device; + const char *device; - if (dbus_g_proxy_end_call (proxy, call_id, &error, - G_TYPE_STRING, &device, - G_TYPE_INVALID) == FALSE) { + device = nm_bluez_device_connect_finish (NM_BLUEZ_DEVICE (object), + res, &error); + + if (!device) { nm_log_warn (LOGD_BT, "Error connecting with bluez: %s", error && error->message ? error->message : "(unknown)"); g_clear_error (&error); @@ -733,20 +731,11 @@ bluez_connect_cb (DBusGProxy *proxy, return; } - if (!device || !strlen (device)) { - nm_log_warn (LOGD_BT, "Invalid network device returned by bluez"); - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - } - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { g_free (priv->rfcomm_iface); - priv->rfcomm_iface = device; + priv->rfcomm_iface = g_strdup (device); } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { nm_device_set_ip_iface (NM_DEVICE (self), device); - g_free (device); } nm_log_dbg (LOGD_BT, "(%s): connect request successful", @@ -819,7 +808,6 @@ static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - DBusGConnection *bus; gboolean dun = FALSE; NMConnection *connection; @@ -843,28 +831,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) else g_assert_not_reached (); - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - - priv->type_proxy = dbus_g_proxy_new_for_name (bus, - BLUEZ_SERVICE, - nm_device_get_udi (device), - dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); - if (!priv->type_proxy) { - // FIXME: set a reason code - return NM_ACT_STAGE_RETURN_FAILURE; - } - nm_log_dbg (LOGD_BT, "(%s): requesting connection to the device", nm_device_get_iface (device)); /* Connect to the BT device */ - dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", - bluez_connect_cb, - device, - NULL, - 20000, - G_TYPE_STRING, dun ? BLUETOOTH_DUN_UUID : BLUETOOTH_NAP_UUID, - G_TYPE_INVALID); + nm_bluez_device_connect_async (priv->bt_device, dun, bluez_connect_cb, device); if (priv->timeout_id) g_source_remove (priv->timeout_id); @@ -915,11 +886,14 @@ static void deactivate (NMDevice *device) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + gboolean dun; + + dun = priv->bt_type == NM_BT_CAPABILITY_DUN; priv->have_iface = FALSE; priv->connected = FALSE; - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + if (dun) { if (priv->modem) { nm_modem_deactivate (priv->modem, device); @@ -934,28 +908,10 @@ deactivate (NMDevice *device) g_object_unref (priv->modem); priv->modem = NULL; } - - if (priv->type_proxy) { - /* Don't ever pass NULL through dbus; rfcomm_iface - * might happen to be NULL for some reason. - */ - if (priv->rfcomm_iface) { - dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", - G_TYPE_STRING, priv->rfcomm_iface, - G_TYPE_INVALID); - } - g_object_unref (priv->type_proxy); - priv->type_proxy = NULL; - } - } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { - if (priv->type_proxy) { - dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", - G_TYPE_INVALID); - g_object_unref (priv->type_proxy); - priv->type_proxy = NULL; - } } + nm_bluez_device_call_disconnect (priv->bt_device, dun); + if (priv->timeout_id) { g_source_remove (priv->timeout_id); priv->timeout_id = 0; @@ -1209,7 +1165,6 @@ dispose (GObject *object) } priv->dbus_mgr = NULL; - g_clear_object (&priv->type_proxy); g_clear_object (&priv->modem); g_clear_object (&priv->bt_device); From ed966c7e3fc595ecee0571ec0dfc57596dd3d16e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 18 Sep 2013 22:59:03 +0200 Subject: [PATCH 06/29] bluez: pass NMBluetoothCapabilities to nm_bluez_device Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 21 +++++++++++++++------ src/bluez-manager/nm-bluez-device.h | 5 ++--- src/devices/nm-device-bt.c | 14 ++++---------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 434c85ffd3..ccfa43137c 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -45,6 +45,7 @@ typedef struct { gboolean initialized; gboolean usable; + NMBluetoothCapabilities connection_bt_type; char *address; guint8 bin_address[ETH_ALEN]; @@ -252,14 +253,16 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) /***********************************************************/ void -nm_bluez_device_call_disconnect (NMBluezDevice *self, gboolean dun) +nm_bluez_device_call_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); + if (!priv->type_proxy) return; - if (dun) { + if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { /* Don't ever pass NULL through dbus; rfcomm_iface * might happen to be NULL for some reason. */ @@ -273,6 +276,7 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self, gboolean dun) } g_clear_object (&priv->type_proxy); + priv->connection_bt_type = NM_BT_CAPABILITY_NONE; } static void @@ -306,7 +310,7 @@ bluez_connect_cb (DBusGProxy *proxy, void nm_bluez_device_connect_async (NMBluezDevice *self, - gboolean dun, + NMBluetoothCapabilities connection_bt_type, GAsyncReadyCallback callback, gpointer user_data) { @@ -314,6 +318,8 @@ nm_bluez_device_connect_async (NMBluezDevice *self, NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); DBusGConnection *connection; + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); + connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); simple = g_simple_async_result_new (G_OBJECT (self), @@ -324,7 +330,7 @@ nm_bluez_device_connect_async (NMBluezDevice *self, priv->type_proxy = dbus_g_proxy_new_for_name (connection, BLUEZ_SERVICE, priv->path, - dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); + connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); if (!priv->type_proxy) g_simple_async_report_error_in_idle (G_OBJECT (self), callback, @@ -332,14 +338,17 @@ nm_bluez_device_connect_async (NMBluezDevice *self, G_IO_ERROR, G_IO_ERROR_FAILED, "Unable to create proxy"); - else + else { dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", bluez_connect_cb, simple, NULL, 20000, - G_TYPE_STRING, dun ? BLUETOOTH_CONNECT_DUN : BLUETOOTH_CONNECT_NAP, + G_TYPE_STRING, + connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUETOOTH_CONNECT_DUN : BLUETOOTH_CONNECT_NAP, G_TYPE_INVALID); + priv->connection_bt_type = connection_bt_type; + } } const char * diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index b49f56b5cb..54a7e1cd59 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -80,7 +80,7 @@ gboolean nm_bluez_device_get_connected (NMBluezDevice *self); void nm_bluez_device_connect_async (NMBluezDevice *self, - gboolean dun, + NMBluetoothCapabilities connection_bt_type, GAsyncReadyCallback callback, gpointer user_data); @@ -90,8 +90,7 @@ nm_bluez_device_connect_finish (NMBluezDevice *self, GError **error); void -nm_bluez_device_call_disconnect (NMBluezDevice *self, - gboolean dun); +nm_bluez_device_call_disconnect (NMBluezDevice *self); #endif /* NM_BLUEZ_DEVICE_H */ diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index 8b9c704f2f..cb8c790979 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -808,7 +808,6 @@ static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - gboolean dun = FALSE; NMConnection *connection; connection = nm_device_get_connection (device); @@ -824,18 +823,13 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_FAILURE; } - if (priv->bt_type == NM_BT_CAPABILITY_DUN) - dun = TRUE; - else if (priv->bt_type == NM_BT_CAPABILITY_NAP) - dun = FALSE; - else - g_assert_not_reached (); - nm_log_dbg (LOGD_BT, "(%s): requesting connection to the device", nm_device_get_iface (device)); /* Connect to the BT device */ - nm_bluez_device_connect_async (priv->bt_device, dun, bluez_connect_cb, device); + nm_bluez_device_connect_async (priv->bt_device, + priv->bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP), + bluez_connect_cb, device); if (priv->timeout_id) g_source_remove (priv->timeout_id); @@ -910,7 +904,7 @@ deactivate (NMDevice *device) } } - nm_bluez_device_call_disconnect (priv->bt_device, dun); + nm_bluez_device_call_disconnect (priv->bt_device); if (priv->timeout_id) { g_source_remove (priv->timeout_id); From 816347d3e0ad5071d5ca5983fd33f8878630bf3f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 18 Sep 2013 20:38:27 +0200 Subject: [PATCH 07/29] bluez: fail if connect_async is called when already being connected. Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 31 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index ccfa43137c..3e37e8cb04 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -322,23 +322,32 @@ nm_bluez_device_connect_async (NMBluezDevice *self, connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - simple = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - nm_bluez_device_connect_async); + if (priv->type_proxy) { + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Already connected to bluez service"); + return; + } priv->type_proxy = dbus_g_proxy_new_for_name (connection, BLUEZ_SERVICE, priv->path, connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); - if (!priv->type_proxy) + if (!priv->type_proxy) { g_simple_async_report_error_in_idle (G_OBJECT (self), - callback, - user_data, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unable to create proxy"); - else { + callback, + user_data, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Unable to create proxy"); + } else { + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", bluez_connect_cb, simple, From a26271841c1ba65aace1fd216ad1ae6d103a35fd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 18 Sep 2013 20:58:06 +0200 Subject: [PATCH 08/29] trivial: rename variable and fix whitespace errors Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 3e37e8cb04..18c166ad85 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -41,7 +41,7 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; DBusGProxy *proxy; - DBusGProxy *type_proxy; + DBusGProxy *connection_proxy; gboolean initialized; gboolean usable; @@ -259,7 +259,7 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); - if (!priv->type_proxy) + if (!priv->connection_proxy) return; if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { @@ -267,15 +267,15 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) * might happen to be NULL for some reason. */ if (priv->rfcomm_iface) - dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", - G_TYPE_STRING, priv->rfcomm_iface, - G_TYPE_INVALID); + dbus_g_proxy_call_no_reply (priv->connection_proxy, "Disconnect", + G_TYPE_STRING, priv->rfcomm_iface, + G_TYPE_INVALID); } else { - dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", + dbus_g_proxy_call_no_reply (priv->connection_proxy, "Disconnect", G_TYPE_INVALID); } - g_clear_object (&priv->type_proxy); + g_clear_object (&priv->connection_proxy); priv->connection_bt_type = NM_BT_CAPABILITY_NONE; } @@ -295,8 +295,8 @@ bluez_connect_cb (DBusGProxy *proxy, G_TYPE_INVALID) == FALSE) g_simple_async_result_take_error (result, error); else if (!device || !strlen (device)) { - g_simple_async_result_set_error(result, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid argument received"); + g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, + "Invalid argument received"); } else { g_simple_async_result_set_op_res_gpointer (result, g_strdup (device), @@ -323,7 +323,7 @@ nm_bluez_device_connect_async (NMBluezDevice *self, connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - if (priv->type_proxy) { + if (priv->connection_proxy) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, @@ -332,11 +332,11 @@ nm_bluez_device_connect_async (NMBluezDevice *self, "Already connected to bluez service"); return; } - priv->type_proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); - if (!priv->type_proxy) { + priv->connection_proxy = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + priv->path, + connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); + if (!priv->connection_proxy) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, @@ -348,7 +348,7 @@ nm_bluez_device_connect_async (NMBluezDevice *self, callback, user_data, nm_bluez_device_connect_async); - dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", + dbus_g_proxy_begin_call_with_timeout (priv->connection_proxy, "Connect", bluez_connect_cb, simple, NULL, @@ -607,7 +607,7 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); - g_clear_object (&priv->type_proxy); + g_clear_object (&priv->connection_proxy); G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } From 1013caba7530d7c6106accfc1b4f4838586ac89a Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Wed, 29 May 2013 20:45:41 +0200 Subject: [PATCH 09/29] bluez: add configure switch for BlueZ 5 --- configure.ac | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/configure.ac b/configure.ac index be15f7986a..c17db5d4f6 100644 --- a/configure.ac +++ b/configure.ac @@ -267,6 +267,17 @@ else fi AC_SUBST(UDEV_BASE_DIR) +# BlueZ +AC_ARG_ENABLE(bluez5, AS_HELP_STRING([--enable-bluez5], + [build with BlueZ 5 support instead of BlueZ 4]), + [enable_bluez5=${enableval}]) +if (test "${enable_bluez5}" = "yes"); then + AC_DEFINE(WITH_BLUEZ5, 1, [Define if you have BlueZ 5 support]) +else + AC_DEFINE(WITH_BLUEZ5, 0, [Define if you have BlueZ 5 support]) +fi +AM_CONDITIONAL(WITH_BLUEZ5, test "${enable_bluez5}" = "yes") + # systemd unit support AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])) @@ -814,6 +825,7 @@ echo " modemmanager-1: $with_modem_manager_1" echo " concheck: $enable_concheck" echo " libndp: $libndp_location" echo " libteamdctl: $enable_teamdctl" +echo " bluez 5: $enable_bluez5" echo echo "Configuration plugins" From 1ae5d53354178666c7754457e1ef5e4b69bc29ec Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Wed, 29 May 2013 21:39:13 +0200 Subject: [PATCH 10/29] bluez: add support for BlueZ 5 At this moment we only support one of BlueZ 4 and 5, which has to be defined at build time. Patch rewritten by Thomas Haller Signed-off-by: Thomas Haller --- src/Makefile.am | 25 +- src/bluez-manager/nm-bluez-common.h | 14 + src/bluez-manager/nm-bluez-device.c | 1 + src/bluez-manager/nm-bluez-device.h | 7 +- src/bluez-manager/nm-bluez-manager.h | 9 +- src/bluez-manager/nm-bluez5-device.c | 658 ++++++++++++++++++++++++++ src/bluez-manager/nm-bluez5-manager.c | 424 +++++++++++++++++ src/nm-manager.c | 6 +- 8 files changed, 1133 insertions(+), 11 deletions(-) create mode 100644 src/bluez-manager/nm-bluez5-device.c create mode 100644 src/bluez-manager/nm-bluez5-manager.c diff --git a/src/Makefile.am b/src/Makefile.am index b9ca94bb20..9791102cdb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,14 +49,6 @@ NetworkManager_LDADD = libNetworkManager.la $(top_builddir)/libgsystem.la $(LIBN noinst_LTLIBRARIES = libNetworkManager.la nm_sources = \ - bluez-manager/nm-bluez-adapter.c \ - bluez-manager/nm-bluez-adapter.h \ - bluez-manager/nm-bluez-common.h \ - bluez-manager/nm-bluez-device.c \ - bluez-manager/nm-bluez-device.h \ - bluez-manager/nm-bluez-manager.c \ - bluez-manager/nm-bluez-manager.h \ - \ config/nm-config.c \ config/nm-config.h \ config/nm-config-device.c \ @@ -266,6 +258,23 @@ nm_sources = \ NetworkManagerUtils.c \ NetworkManagerUtils.h +nm_sources += \ + bluez-manager/nm-bluez-common.h \ + bluez-manager/nm-bluez-device.h \ + bluez-manager/nm-bluez-manager.h + +if WITH_BLUEZ5 +nm_sources += \ + bluez-manager/nm-bluez5-device.c \ + bluez-manager/nm-bluez5-manager.c +else +nm_sources += \ + bluez-manager/nm-bluez-adapter.h \ + bluez-manager/nm-bluez-adapter.c \ + bluez-manager/nm-bluez-device.c \ + bluez-manager/nm-bluez-manager.c +endif + if WITH_MODEM_MANAGER_1 nm_sources += \ modem-manager/nm-modem-broadband.c \ diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h index 26ef1e31a7..4bf029d9a4 100644 --- a/src/bluez-manager/nm-bluez-common.h +++ b/src/bluez-manager/nm-bluez-common.h @@ -21,17 +21,31 @@ #ifndef NM_BLUEZ_COMMON_H #define NM_BLUEZ_COMMON_H +#include + #define BLUETOOTH_CONNECT_DUN "dun" #define BLUETOOTH_CONNECT_NAP "nap" #define BLUEZ_SERVICE "org.bluez" #define BLUEZ_MANAGER_PATH "/" +#define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" + +#if WITH_BLUEZ5 + +#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1" +#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1" +#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network1" + +#else + #define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter" #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" #define BLUEZ_SERIAL_INTERFACE "org.bluez.Serial" #define BLUEZ_NETWORK_INTERFACE "org.bluez.Network" +#endif /* WITH_BLUEZ */ + #endif /* NM_BLUEZ_COMMON_H */ diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 18c166ad85..a14075fbbc 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -297,6 +297,7 @@ bluez_connect_cb (DBusGProxy *proxy, else if (!device || !strlen (device)) { g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid argument received"); + g_free (device); } else { g_simple_async_result_set_op_res_gpointer (result, g_strdup (device), diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index 54a7e1cd59..d03d4bafdf 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -25,6 +25,7 @@ #include #include +#include #include "nm-connection.h" #include "nm-connection-provider.h" @@ -58,7 +59,11 @@ typedef struct { GType nm_bluez_device_get_type (void); -NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider); +NMBluezDevice *nm_bluez_device_new (const char *path +#if ! WITH_BLUEZ5 + , NMConnectionProvider *provider +#endif + ); const char *nm_bluez_device_get_path (NMBluezDevice *self); diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h index 2bfc971eb8..3391f7f5c1 100644 --- a/src/bluez-manager/nm-bluez-manager.h +++ b/src/bluez-manager/nm-bluez-manager.h @@ -25,6 +25,7 @@ #include #include +#include #include "nm-connection-provider.h" G_BEGIN_DECLS @@ -60,7 +61,13 @@ typedef struct { GType nm_bluez_manager_get_type (void); -NMBluezManager *nm_bluez_manager_get (NMConnectionProvider *provider); +NMBluezManager *nm_bluez_manager_get ( +#if WITH_BLUEZ5 + void +#else + NMConnectionProvider *provider +#endif + ); void nm_bluez_manager_query_devices (NMBluezManager *manager); diff --git a/src/bluez-manager/nm-bluez5-device.c b/src/bluez-manager/nm-bluez5-device.c new file mode 100644 index 0000000000..3ccbea719e --- /dev/null +++ b/src/bluez-manager/nm-bluez5-device.c @@ -0,0 +1,658 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2012 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. + */ + +#include +#include +#include +#include +#include + +#include "NetworkManager.h" +#include "nm-setting-bluetooth.h" + +#include "nm-bluez-device.h" +#include "nm-bluez-common.h" +#include "nm-logging.h" + + +G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) + +#define NM_BLUEZ_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_DEVICE, NMBluezDevicePrivate)) + +typedef struct { + char *path; + GDBusProxy *proxy; + GDBusProxy *adapter; + GDBusConnection *connection; + + gboolean initialized; + gboolean usable; + NMBluetoothCapabilities connection_bt_type; + + char *address; + guint8 bin_address[ETH_ALEN]; + char *name; + guint32 capabilities; + gint rssi; + gboolean connected; + + char *bt_iface; +} NMBluezDevicePrivate; + + +enum { + PROP_0, + PROP_PATH, + PROP_ADDRESS, + PROP_NAME, + PROP_CAPABILITIES, + PROP_RSSI, + PROP_USABLE, + PROP_CONNECTED, + + LAST_PROP +}; + +/* Signals */ +enum { + INITIALIZED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/***********************************************************/ + +const char * +nm_bluez_device_get_path (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->path; +} + +const char * +nm_bluez_device_get_address (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->address; +} + +gboolean +nm_bluez_device_get_initialized (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->initialized; +} + +gboolean +nm_bluez_device_get_usable (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->usable; +} + +const char * +nm_bluez_device_get_name (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->name; +} + +guint32 +nm_bluez_device_get_capabilities (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->capabilities; +} + +gint +nm_bluez_device_get_rssi (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; +} + +gboolean +nm_bluez_device_get_connected (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; +} + +static void +check_emit_usable (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + gboolean new_usable; + + new_usable = (priv->initialized && priv->capabilities && priv->name && + priv->address && priv->adapter && priv->connection); + if (new_usable != priv->usable) { + priv->usable = new_usable; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); + } +} + +/********************************************************************/ + +void +nm_bluez_device_call_disconnect (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (priv->connection); + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); + + g_dbus_connection_call (priv->connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ_NETWORK_INTERFACE, + "Disconnect", + g_variant_new ("()"), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, NULL, NULL); + + priv->connection_bt_type = NM_BT_CAPABILITY_NONE; +} + +static void +bluez_connect_pan_cb (GDBusConnection *connection, + GAsyncResult *res, + gpointer user_data) +{ + GSimpleAsyncResult *result = user_data; + NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *variant; + GError *error = NULL; + char *device; + + variant = g_dbus_connection_call_finish (connection, res, &error); + + if (!variant) { + g_simple_async_result_take_error (result, error); + } else { + g_variant_get (variant, "(s)", &device); + + g_simple_async_result_set_op_res_gpointer (result, + g_strdup (device), + g_free); + priv->bt_iface = device; + g_variant_unref (variant); + } + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + NMBluetoothCapabilities connection_bt_type, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); + + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); + + /* For PAN we call Connect() on org.bluez.Network1 */ + g_dbus_connection_call (priv->connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ_NETWORK_INTERFACE, + "Connect", + g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) bluez_connect_pan_cb, + simple); + + priv->connection_bt_type = connection_bt_type; +} + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + const char *device; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (self), + nm_bluez_device_connect_async), + NULL); + + simple = (GSimpleAsyncResult *) result; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); + return device; +} + +/***********************************************************/ + +static guint32 +convert_uuids_to_capabilities (const char **strings) +{ + const char **iter; + guint32 capabilities = 0; + + for (iter = strings; iter && *iter; iter++) { + char **parts; + + parts = g_strsplit (*iter, "-", -1); + if (parts && parts[0]) { + switch (g_ascii_strtoull (parts[0], NULL, 16)) { + case 0x1116: + capabilities |= NM_BT_CAPABILITY_NAP; + break; + default: + break; + } + } + g_strfreev (parts); + } + + return capabilities; +} + +static void +on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + + priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->adapter) { + nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + check_emit_usable (self); +} + +static void +properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariantIter i; + const char *property; + const char *str; + GVariant *v; + guint32 uint_val; + gint int_val; + const char **strv; + + g_variant_iter_init (&i, changed_properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!strcmp (property, "Name")) { + str = g_variant_get_string (v, NULL); + if (g_strcmp0 (priv->name, str)) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } else if (!strcmp (property, "RSSI")) { + int_val = g_variant_get_int16 (v); + if (priv->rssi != int_val) { + priv->rssi = int_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); + } + } else if (!strcmp (property, "UUIDs")) { + strv = g_variant_get_strv (v, NULL); + uint_val = convert_uuids_to_capabilities (strv); + g_free (strv); + if (priv->capabilities != uint_val) { + priv->capabilities = uint_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + } + } else if (!strcmp (property, "Connected")) { + gboolean connected = g_variant_get_boolean (v); + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } + } + g_variant_unref (v); + } + + check_emit_usable (self); +} + +static void +query_properties (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *v; + const char **uuids; + struct ether_addr *tmp; + + v = g_dbus_proxy_get_cached_property (priv->proxy, "Address"); + priv->address = v ? g_variant_dup_string (v, NULL) : NULL; + if (v) + g_variant_unref (v); + if (priv->address) { + tmp = ether_aton (priv->address); + g_assert (tmp); + memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); + } + + v = g_dbus_proxy_get_cached_property (priv->proxy, "Name"); + priv->name = v ? g_variant_dup_string (v, NULL) : NULL; + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy, "RSSI"); + priv->rssi = v ? g_variant_get_int16 (v) : 0; + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy, "UUIDs"); + if (v) { + uuids = g_variant_get_strv (v, NULL); + priv->capabilities = convert_uuids_to_capabilities (uuids); + g_variant_unref (v); + } else + priv->capabilities = NM_BT_CAPABILITY_NONE; + + v = g_dbus_proxy_get_cached_property (priv->proxy, "Adapter"); + if (v) { + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + g_variant_get_string (v, NULL), + BLUEZ_ADAPTER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_adapter_acquired, + self); + g_variant_unref (v); + } + + priv->initialized = TRUE; + g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + + check_emit_usable (self); +} + +static void +on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + return; + } + + g_signal_connect (priv->proxy, "g-properties-changed", + G_CALLBACK (properties_changed), self); + + query_properties (self); +} + +static void +on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + + priv->connection = g_bus_get_finish (res, &error); + + if (!priv->connection) { + nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + return; + } + + check_emit_usable (self); +} + +/********************************************************************/ + +NMBluezDevice * +nm_bluez_device_new (const char *path) +{ + NMBluezDevice *self; + NMBluezDevicePrivate *priv; + + g_return_val_if_fail (path != NULL, NULL); + + self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, + NM_BLUEZ_DEVICE_PATH, path, + NULL); + if (!self) + return NULL; + + priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback) on_bus_acquired, + self); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + priv->path, + BLUEZ_DEVICE_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); + + return self; +} + +static void +nm_bluez_device_init (NMBluezDevice *self) +{ +} + +static void +dispose (GObject *object) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + g_clear_object (&priv->adapter); + g_clear_object (&priv->connection); + + G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + g_free (priv->path); + g_free (priv->address); + g_free (priv->name); + g_free (priv->bt_iface); + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + case PROP_ADDRESS: + g_value_set_string (value, priv->address); + break; + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_CAPABILITIES: + g_value_set_uint (value, priv->capabilities); + break; + case PROP_RSSI: + g_value_set_int (value, priv->rssi); + break; + case PROP_USABLE: + g_value_set_boolean (value, priv->usable); + break; + case PROP_CONNECTED: + g_value_set_boolean (value, priv->connected); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + /* construct only */ + priv->path = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_bluez_device_class_init (NMBluezDeviceClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMBluezDevicePrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + object_class->dispose = dispose; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_BLUEZ_DEVICE_PATH, + "DBus Path", + "DBus Path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_ADDRESS, + g_param_spec_string (NM_BLUEZ_DEVICE_ADDRESS, + "Address", + "Address", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_BLUEZ_DEVICE_NAME, + "Name", + "Name", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CAPABILITIES, + g_param_spec_uint (NM_BLUEZ_DEVICE_CAPABILITIES, + "Capabilities", + "Capabilities", + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_RSSI, + g_param_spec_int (NM_BLUEZ_DEVICE_RSSI, + "RSSI", + "RSSI", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_USABLE, + g_param_spec_boolean (NM_BLUEZ_DEVICE_USABLE, + "Usable", + "Usable", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CONNECTED, + g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, + "Connected", + "Connected", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[INITIALIZED] = g_signal_new ("initialized", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMBluezDeviceClass, initialized), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); +} diff --git a/src/bluez-manager/nm-bluez5-manager.c b/src/bluez-manager/nm-bluez5-manager.c new file mode 100644 index 0000000000..b138eec066 --- /dev/null +++ b/src/bluez-manager/nm-bluez5-manager.c @@ -0,0 +1,424 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2012 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. + */ + +#include +#include +#include +#include + +#include "nm-logging.h" +#include "nm-bluez-manager.h" +#include "nm-bluez-device.h" +#include "nm-bluez-common.h" + +#include "nm-dbus-manager.h" + +typedef struct { + NMDBusManager *dbus_mgr; + gulong name_owner_changed_id; + + GDBusProxy *proxy; + + GHashTable *devices; +} NMBluezManagerPrivate; + +#define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) + +G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT) + +enum { + BDADDR_ADDED, + BDADDR_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) +{ + g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, + nm_bluez_device_get_address (device), + nm_bluez_device_get_name (device), + nm_bluez_device_get_path (device), + nm_bluez_device_get_capabilities (device)); +} + +void +nm_bluez_manager_query_devices (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + GHashTableIter iter; + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + emit_bdaddr_added (self, device); + } +} + +static void +device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self) +{ + gboolean usable = nm_bluez_device_get_usable (device); + + nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", + nm_bluez_device_get_path (device), + usable ? "usable" : "unusable"); + + if (usable) { + nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); + emit_bdaddr_added (self, device); + } else + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); +} + +static void +device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + nm_log_dbg (LOGD_BT, "(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); + if (!success) + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); +} + +static void +device_added (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + device = nm_bluez_device_new (path); + g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); + + nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); +} + +static void +device_removed (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + + device = g_hash_table_lookup (priv->devices, path); + if (device) { + g_object_ref (device); + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); + + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + + g_object_unref (device); + } +} + +static void +object_manager_g_signal (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + NMBluezManager *self) +{ + GVariant *variant; + const gchar *path; + + if (!strcmp (signal_name, "InterfacesRemoved")) { + const gchar **ifaces; + gsize i, length; + + g_variant_get (parameters, "(&o*)", &path, &variant); + + ifaces = g_variant_get_strv (variant, &length); + + for (i = 0; i < length; i++) { + if (!strcmp (ifaces[i], BLUEZ_DEVICE_INTERFACE)) { + device_removed (proxy, path, self); + break; + } + } + + g_free (ifaces); + + } else if (!strcmp (signal_name, "InterfacesAdded")) { + g_variant_get (parameters, "(&o*)", &path, &variant); + + if (g_variant_lookup_value (variant, BLUEZ_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) + device_added (proxy, path, self); + } +} + +static void +get_managed_objects_cb (GDBusProxy *proxy, + GAsyncResult *res, + NMBluezManager *self) +{ + GVariant *variant, *ifaces; + GVariantIter i; + GError *error = NULL; + const char *path; + + variant = g_dbus_proxy_call_finish (proxy, res, &error); + + if (!variant) { + nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + g_variant_iter_init (&i, g_variant_get_child_value (variant, 0)); + while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { + if (g_variant_lookup_value (ifaces, BLUEZ_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) { + device_added (proxy, path, self); + } + } + + g_variant_unref (variant); +} + +static void +on_proxy_acquired (GObject *object, + GAsyncResult *res, + NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + GError *error = NULL; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + /* Get already managed devices. */ + g_dbus_proxy_call (priv->proxy, "GetManagedObjects", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) get_managed_objects_cb, + self); + + g_signal_connect (priv->proxy, "g-signal", + G_CALLBACK (object_manager_g_signal), self); +} + +static void +bluez_connect (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (priv->proxy == NULL); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + OBJECT_MANAGER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); +} + +static void +name_owner_changed_cb (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + /* Can't handle the signal if its not from the Bluez */ + if (strcmp (BLUEZ_SERVICE, name)) + return; + + if (old_owner_good && !new_owner_good) { + if (priv->devices) { + GHashTableIter iter; + NMBluezDevice *device; + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + g_hash_table_remove_all (priv->devices); + } + } +} + +static void +bluez_cleanup (NMBluezManager *self, gboolean do_signal) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + GHashTableIter iter; + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (do_signal) { + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + } + + g_hash_table_remove_all (priv->devices); +} + +static void +dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + + if (!connection) + bluez_cleanup (self, TRUE); + else + bluez_connect (self); +} + +/****************************************************************/ + +NMBluezManager * +nm_bluez_manager_get (void) +{ + static NMBluezManager *singleton = NULL; + + if (singleton) + return g_object_ref (singleton); + + singleton = (NMBluezManager *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); + g_assert (singleton); + + return singleton; +} + +static void +nm_bluez_manager_init (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + priv->dbus_mgr = nm_dbus_manager_get (); + g_assert (priv->dbus_mgr); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (name_owner_changed_cb), + self); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + self); + + bluez_connect (self); + + priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, g_object_unref); +} + +static void +dispose (GObject *object) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (object); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + bluez_cleanup (self, FALSE); + + if (priv->dbus_mgr) { + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); + priv->dbus_mgr = NULL; + } + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (object); + + g_hash_table_destroy (priv->devices); + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->finalize (object); +} + +static void +nm_bluez_manager_class_init (NMBluezManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* Signals */ + signals[BDADDR_ADDED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + + signals[BDADDR_REMOVED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); +} diff --git a/src/nm-manager.c b/src/nm-manager.c index f395f03302..416fefd84b 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4452,7 +4452,11 @@ nm_manager_new (NMSettings *settings, G_CALLBACK (rfkill_manager_rfkill_changed_cb), singleton); - priv->bluez_mgr = nm_bluez_manager_get (NM_CONNECTION_PROVIDER (priv->settings)); + priv->bluez_mgr = nm_bluez_manager_get ( +#if ! WITH_BLUEZ5 + NM_CONNECTION_PROVIDER (priv->settings) +#endif + ); g_signal_connect (priv->bluez_mgr, NM_BLUEZ_MANAGER_BDADDR_ADDED, From c3e644fbb436f7fbcb44af25ec9011e8cc943b96 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 6 Sep 2013 19:29:29 +0200 Subject: [PATCH 11/29] trivial: change nm-bluez*-device.c to be more similar These two files share much code, so they will be merged into one file. As a first step, make some trvial renaming to make the two files more similar and easier to merge. Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 109 ++++++++++++++------------- src/bluez-manager/nm-bluez5-device.c | 59 ++++++++------- 2 files changed, 90 insertions(+), 78 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index a14075fbbc..869f3ec1f9 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -27,10 +27,10 @@ #include "NetworkManager.h" #include "nm-setting-bluetooth.h" -#include "nm-dbus-manager.h" -#include "nm-bluez-device.h" #include "nm-bluez-common.h" +#include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" +#include "nm-bluez-device.h" #include "nm-logging.h" @@ -40,7 +40,7 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; - DBusGProxy *proxy; + DBusGProxy *proxy4; DBusGProxy *connection_proxy; gboolean initialized; @@ -54,7 +54,7 @@ typedef struct { gint rssi; gboolean connected; - char *rfcomm_iface; + char *bt_iface; NMConnectionProvider *provider; GSList *connections; @@ -153,7 +153,10 @@ check_emit_usable (NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); gboolean new_usable; - new_usable = (priv->initialized && priv->capabilities && priv->name && priv->address && priv->connections); + new_usable = (priv->initialized && priv->capabilities && priv->name && + priv->address && + priv->connections + ); if (new_usable != priv->usable) { priv->usable = new_usable; g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); @@ -263,12 +266,12 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) return; if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { - /* Don't ever pass NULL through dbus; rfcomm_iface + /* Don't ever pass NULL through dbus; bt_iface * might happen to be NULL for some reason. */ - if (priv->rfcomm_iface) + if (priv->bt_iface) dbus_g_proxy_call_no_reply (priv->connection_proxy, "Disconnect", - G_TYPE_STRING, priv->rfcomm_iface, + G_TYPE_STRING, priv->bt_iface, G_TYPE_INVALID); } else { dbus_g_proxy_call_no_reply (priv->connection_proxy, "Disconnect", @@ -280,7 +283,7 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) } static void -bluez_connect_cb (DBusGProxy *proxy, +bluez_connect_cb (DBusGProxy *proxy4, DBusGProxyCall *call_id, gpointer user_data) { @@ -290,7 +293,7 @@ bluez_connect_cb (DBusGProxy *proxy, GError *error = NULL; char *device; - if (dbus_g_proxy_end_call (proxy, call_id, &error, + if (dbus_g_proxy_end_call (proxy4, call_id, &error, G_TYPE_STRING, &device, G_TYPE_INVALID) == FALSE) g_simple_async_result_take_error (result, error); @@ -302,7 +305,7 @@ bluez_connect_cb (DBusGProxy *proxy, g_simple_async_result_set_op_res_gpointer (result, g_strdup (device), g_free); - priv->rfcomm_iface = device; + priv->bt_iface = device; } g_simple_async_result_complete (result); @@ -414,7 +417,7 @@ convert_uuids_to_capabilities (const char **strings) } static void -property_changed (DBusGProxy *proxy, +property_changed (DBusGProxy *proxy4, const char *property, GValue *value, gpointer user_data) @@ -425,32 +428,34 @@ property_changed (DBusGProxy *proxy, guint32 uint_val; gint int_val; - if (!strcmp (property, "Name")) { - str = g_value_get_string (value); - if ( (!priv->name && str) - || (priv->name && !str) - || (priv->name && str && strcmp (priv->name, str))) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_value_get_int (value); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - uint_val = convert_uuids_to_capabilities ((const char **) g_value_get_boxed (value)); - if (priv->capabilities != uint_val) { - priv->capabilities = uint_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); - } - } else if (!strcmp (property, "Connected")) { - gboolean connected = g_value_get_boolean (value); - if (priv->connected != connected) { - priv->connected = connected; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + { + if (!strcmp (property, "Name")) { + str = g_value_get_string (value); + if ( (!priv->name && str) + || (priv->name && !str) + || (priv->name && str && strcmp (priv->name, str))) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } else if (!strcmp (property, "RSSI")) { + int_val = g_value_get_int (value); + if (priv->rssi != int_val) { + priv->rssi = int_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); + } + } else if (!strcmp (property, "UUIDs")) { + uint_val = convert_uuids_to_capabilities ((const char **) g_value_get_boxed (value)); + if (priv->capabilities != uint_val) { + priv->capabilities = uint_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + } + } else if (!strcmp (property, "Connected")) { + gboolean connected = g_value_get_boolean (value); + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } } } @@ -458,7 +463,7 @@ property_changed (DBusGProxy *proxy, } static void -get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); @@ -468,7 +473,7 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) const char **uuids; struct ether_addr *tmp; - if (!dbus_g_proxy_end_call (proxy, call, &err, + if (!dbus_g_proxy_end_call (proxy4, call, &err, DBUS_TYPE_G_MAP_OF_VARIANT, &properties, G_TYPE_INVALID)) { nm_log_warn (LOGD_BT, "bluez error getting device properties: %s", @@ -516,7 +521,7 @@ query_properties (NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); DBusGProxyCall *call; - call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", + call = dbus_g_proxy_begin_call (priv->proxy4, "GetProperties", get_properties_cb, self, NULL, G_TYPE_INVALID); @@ -529,7 +534,9 @@ query_properties (NMBluezDevice *self) /********************************************************************/ NMBluezDevice * -nm_bluez_device_new (const char *path, NMConnectionProvider *provider) +nm_bluez_device_new (const char *path + , NMConnectionProvider *provider + ) { NMBluezDevice *self; NMBluezDevicePrivate *priv; @@ -570,18 +577,18 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE); + priv->proxy4 = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ_DEVICE_INTERFACE); dbus_g_object_register_marshaller (g_cclosure_marshal_generic, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy, "PropertyChanged", + dbus_g_proxy_add_signal (priv->proxy4, "PropertyChanged", G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "PropertyChanged", + dbus_g_proxy_connect_signal (priv->proxy4, "PropertyChanged", G_CALLBACK (property_changed), self, NULL); query_properties (self); @@ -621,8 +628,8 @@ finalize (GObject *object) g_free (priv->path); g_free (priv->address); g_free (priv->name); - g_free (priv->rfcomm_iface); - g_object_unref (priv->proxy); + g_free (priv->bt_iface); + g_object_unref (priv->proxy4); G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); } @@ -753,7 +760,7 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMBluezDeviceClass, initialized), - NULL, NULL, NULL, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); } diff --git a/src/bluez-manager/nm-bluez5-device.c b/src/bluez-manager/nm-bluez5-device.c index 3ccbea719e..5d1ff8c58f 100644 --- a/src/bluez-manager/nm-bluez5-device.c +++ b/src/bluez-manager/nm-bluez5-device.c @@ -28,8 +28,8 @@ #include "NetworkManager.h" #include "nm-setting-bluetooth.h" -#include "nm-bluez-device.h" #include "nm-bluez-common.h" +#include "nm-bluez-device.h" #include "nm-logging.h" @@ -39,9 +39,9 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; - GDBusProxy *proxy; + GDBusProxy *proxy5; GDBusProxy *adapter; - GDBusConnection *connection; + GDBusConnection *dbus_connection; gboolean initialized; gboolean usable; @@ -151,7 +151,9 @@ check_emit_usable (NMBluezDevice *self) gboolean new_usable; new_usable = (priv->initialized && priv->capabilities && priv->name && - priv->address && priv->adapter && priv->connection); + priv->address && + priv->adapter && priv->dbus_connection + ); if (new_usable != priv->usable) { priv->usable = new_usable; g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); @@ -165,10 +167,10 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->connection); + g_return_if_fail (priv->dbus_connection); g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); - g_dbus_connection_call (priv->connection, + g_dbus_connection_call (priv->dbus_connection, BLUEZ_SERVICE, priv->path, BLUEZ_NETWORK_INTERFACE, @@ -183,18 +185,18 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) } static void -bluez_connect_pan_cb (GDBusConnection *connection, +bluez_connect_pan_cb (GDBusConnection *dbus_connection, GAsyncResult *res, gpointer user_data) { - GSimpleAsyncResult *result = user_data; + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *variant; GError *error = NULL; char *device; + GVariant *variant; - variant = g_dbus_connection_call_finish (connection, res, &error); + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); if (!variant) { g_simple_async_result_take_error (result, error); @@ -229,7 +231,7 @@ nm_bluez_device_connect_async (NMBluezDevice *self, nm_bluez_device_connect_async); /* For PAN we call Connect() on org.bluez.Network1 */ - g_dbus_connection_call (priv->connection, + g_dbus_connection_call (priv->dbus_connection, BLUEZ_SERVICE, priv->path, BLUEZ_NETWORK_INTERFACE, @@ -313,7 +315,7 @@ on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) } static void -properties_changed (GDBusProxy *proxy, +properties_changed (GDBusProxy *proxy5, GVariant *changed_properties, GStrv invalidated_properties, gpointer user_data) @@ -372,7 +374,7 @@ query_properties (NMBluezDevice *self) const char **uuids; struct ether_addr *tmp; - v = g_dbus_proxy_get_cached_property (priv->proxy, "Address"); + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); priv->address = v ? g_variant_dup_string (v, NULL) : NULL; if (v) g_variant_unref (v); @@ -382,17 +384,17 @@ query_properties (NMBluezDevice *self) memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); } - v = g_dbus_proxy_get_cached_property (priv->proxy, "Name"); + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); priv->name = v ? g_variant_dup_string (v, NULL) : NULL; if (v) g_variant_unref (v); - v = g_dbus_proxy_get_cached_property (priv->proxy, "RSSI"); + v = g_dbus_proxy_get_cached_property (priv->proxy5, "RSSI"); priv->rssi = v ? g_variant_get_int16 (v) : 0; if (v) g_variant_unref (v); - v = g_dbus_proxy_get_cached_property (priv->proxy, "UUIDs"); + v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); if (v) { uuids = g_variant_get_strv (v, NULL); priv->capabilities = convert_uuids_to_capabilities (uuids); @@ -400,7 +402,7 @@ query_properties (NMBluezDevice *self) } else priv->capabilities = NM_BT_CAPABILITY_NONE; - v = g_dbus_proxy_get_cached_property (priv->proxy, "Adapter"); + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); if (v) { g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, @@ -426,9 +428,9 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *error; - priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!priv->proxy) { + if (!priv->proxy5) { nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error && error->message ? error->message : "(unknown)"); g_clear_error (&error); @@ -436,7 +438,7 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) return; } - g_signal_connect (priv->proxy, "g-properties-changed", + g_signal_connect (priv->proxy5, "g-properties-changed", G_CALLBACK (properties_changed), self); query_properties (self); @@ -448,9 +450,9 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *error = NULL; - priv->connection = g_bus_get_finish (res, &error); + priv->dbus_connection = g_bus_get_finish (res, &error); - if (!priv->connection) { + if (!priv->dbus_connection) { nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error && error->message ? error->message : "(unknown)"); g_clear_error (&error); @@ -464,7 +466,8 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) /********************************************************************/ NMBluezDevice * -nm_bluez_device_new (const char *path) +nm_bluez_device_new (const char *path + ) { NMBluezDevice *self; NMBluezDevicePrivate *priv; @@ -505,10 +508,11 @@ nm_bluez_device_init (NMBluezDevice *self) static void dispose (GObject *object) { - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + NMBluezDevice *self = NM_BLUEZ_DEVICE (object); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); g_clear_object (&priv->adapter); - g_clear_object (&priv->connection); + g_clear_object (&priv->dbus_connection); G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } @@ -522,7 +526,7 @@ finalize (GObject *object) g_free (priv->address); g_free (priv->name); g_free (priv->bt_iface); - g_object_unref (priv->proxy); + g_object_unref (priv->proxy5); G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); } @@ -588,8 +592,8 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; - object_class->finalize = finalize; object_class->dispose = dispose; + object_class->finalize = finalize; /* Properties */ g_object_class_install_property @@ -656,3 +660,4 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); } + From daef45bdc0d15130f0fc7a6b1e8033a3802f5a43 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Sep 2013 14:00:23 +0200 Subject: [PATCH 12/29] bluez: no need to check for valid GError if glib function fails Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez5-device.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/bluez-manager/nm-bluez5-device.c b/src/bluez-manager/nm-bluez5-device.c index 5d1ff8c58f..461e9546cc 100644 --- a/src/bluez-manager/nm-bluez5-device.c +++ b/src/bluez-manager/nm-bluez5-device.c @@ -305,8 +305,7 @@ on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); if (!priv->adapter) { - nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", - error && error->message ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); g_clear_error (&error); return; } @@ -431,8 +430,7 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); if (!priv->proxy5) { - nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", - error && error->message ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); g_clear_error (&error); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); return; @@ -453,8 +451,7 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) priv->dbus_connection = g_bus_get_finish (res, &error); if (!priv->dbus_connection) { - nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", - error && error->message ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error->message); g_clear_error (&error); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); return; From 0cec10c013480b45841d92c89de365f12df5d967 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 6 Sep 2013 21:03:28 +0200 Subject: [PATCH 13/29] bluez: merge file nm-bluez5-device.c into nm-bluez-device.c The files nm-bluez-device.c and nm-bluez5-device.c are similar. Merge them together into one file and handle the differences using #if directives. This commit does not actually change any functionality. All it does, is merging the files together and separating the differences with #if#else. The next commit will further add common functionality, so this reduces code duplication for now. Signed-off-by: Thomas Haller --- src/Makefile.am | 3 +- src/bluez-manager/nm-bluez-device.c | 292 +++++++++++- src/bluez-manager/nm-bluez5-device.c | 660 --------------------------- 3 files changed, 291 insertions(+), 664 deletions(-) delete mode 100644 src/bluez-manager/nm-bluez5-device.c diff --git a/src/Makefile.am b/src/Makefile.am index 9791102cdb..700afe3417 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -260,18 +260,17 @@ nm_sources = \ nm_sources += \ bluez-manager/nm-bluez-common.h \ + bluez-manager/nm-bluez-device.c \ bluez-manager/nm-bluez-device.h \ bluez-manager/nm-bluez-manager.h if WITH_BLUEZ5 nm_sources += \ - bluez-manager/nm-bluez5-device.c \ bluez-manager/nm-bluez5-manager.c else nm_sources += \ bluez-manager/nm-bluez-adapter.h \ bluez-manager/nm-bluez-adapter.c \ - bluez-manager/nm-bluez-device.c \ bluez-manager/nm-bluez-manager.c endif diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 869f3ec1f9..a5e3631fd0 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -16,6 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2009 - 2012 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. */ #include @@ -28,8 +29,10 @@ #include "nm-setting-bluetooth.h" #include "nm-bluez-common.h" +#if ! WITH_BLUEZ5 #include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" +#endif #include "nm-bluez-device.h" #include "nm-logging.h" @@ -40,8 +43,14 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; +#if WITH_BLUEZ5 + GDBusProxy *proxy5; + GDBusProxy *adapter; + GDBusConnection *dbus_connection; +#else DBusGProxy *proxy4; DBusGProxy *connection_proxy; +#endif gboolean initialized; gboolean usable; @@ -56,8 +65,10 @@ typedef struct { char *bt_iface; +#if ! WITH_BLUEZ5 NMConnectionProvider *provider; GSList *connections; +#endif } NMBluezDevicePrivate; @@ -155,7 +166,11 @@ check_emit_usable (NMBluezDevice *self) new_usable = (priv->initialized && priv->capabilities && priv->name && priv->address && +#if WITH_BLUEZ5 + priv->adapter && priv->dbus_connection +#else priv->connections +#endif ); if (new_usable != priv->usable) { priv->usable = new_usable; @@ -165,6 +180,7 @@ check_emit_usable (NMBluezDevice *self) /********************************************************************/ +#if ! WITH_BLUEZ5 static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection) { @@ -254,12 +270,28 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) } /***********************************************************/ +#endif void nm_bluez_device_call_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); +#if WITH_BLUEZ5 + g_return_if_fail (priv->dbus_connection); + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); + + g_dbus_connection_call (priv->dbus_connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ_NETWORK_INTERFACE, + "Disconnect", + g_variant_new ("()"), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, NULL, NULL); +#else g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); if (!priv->connection_proxy) @@ -279,13 +311,20 @@ nm_bluez_device_call_disconnect (NMBluezDevice *self) } g_clear_object (&priv->connection_proxy); +#endif priv->connection_bt_type = NM_BT_CAPABILITY_NONE; } static void +#if WITH_BLUEZ5 +bluez_connect_pan_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, + gpointer user_data) +#else bluez_connect_cb (DBusGProxy *proxy4, DBusGProxyCall *call_id, gpointer user_data) +#endif { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); @@ -293,6 +332,23 @@ bluez_connect_cb (DBusGProxy *proxy4, GError *error = NULL; char *device; +#if WITH_BLUEZ5 + GVariant *variant; + + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); + + if (!variant) { + g_simple_async_result_take_error (result, error); + } else { + g_variant_get (variant, "(s)", &device); + + g_simple_async_result_set_op_res_gpointer (result, + g_strdup (device), + g_free); + priv->bt_iface = device; + g_variant_unref (variant); + } +#else if (dbus_g_proxy_end_call (proxy4, call_id, &error, G_TYPE_STRING, &device, G_TYPE_INVALID) == FALSE) @@ -307,6 +363,7 @@ bluez_connect_cb (DBusGProxy *proxy4, g_free); priv->bt_iface = device; } +#endif g_simple_async_result_complete (result); g_object_unref (result); @@ -320,12 +377,37 @@ nm_bluez_device_connect_async (NMBluezDevice *self, { GSimpleAsyncResult *simple; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); +#if ! WITH_BLUEZ5 DBusGConnection *connection; - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); - connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); +#endif +#if WITH_BLUEZ5 + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); + + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); + + /* For PAN we call Connect() on org.bluez.Network1 */ + g_dbus_connection_call (priv->dbus_connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ_NETWORK_INTERFACE, + "Connect", + g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) bluez_connect_pan_cb, + simple); + + priv->connection_bt_type = connection_bt_type; +#else + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); if (priv->connection_proxy) { g_simple_async_report_error_in_idle (G_OBJECT (self), @@ -362,6 +444,7 @@ nm_bluez_device_connect_async (NMBluezDevice *self, G_TYPE_INVALID); priv->connection_bt_type = connection_bt_type; } +#endif } const char * @@ -400,9 +483,11 @@ convert_uuids_to_capabilities (const char **strings) parts = g_strsplit (*iter, "-", -1); if (parts && parts[0]) { switch (g_ascii_strtoull (parts[0], NULL, 16)) { +#if ! WITH_BLUEZ5 case 0x1103: capabilities |= NM_BT_CAPABILITY_DUN; break; +#endif case 0x1116: capabilities |= NM_BT_CAPABILITY_NAP; break; @@ -416,6 +501,76 @@ convert_uuids_to_capabilities (const char **strings) return capabilities; } +#if WITH_BLUEZ5 +static void +on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + + priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->adapter) { + nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); + g_clear_error (&error); + return; + } + + check_emit_usable (self); +} + +static void +properties_changed (GDBusProxy *proxy5, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariantIter i; + const char *property; + const char *str; + GVariant *v; + guint32 uint_val; + gint int_val; + const char **strv; + + g_variant_iter_init (&i, changed_properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!strcmp (property, "Name")) { + str = g_variant_get_string (v, NULL); + if (g_strcmp0 (priv->name, str)) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } else if (!strcmp (property, "RSSI")) { + int_val = g_variant_get_int16 (v); + if (priv->rssi != int_val) { + priv->rssi = int_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); + } + } else if (!strcmp (property, "UUIDs")) { + strv = g_variant_get_strv (v, NULL); + uint_val = convert_uuids_to_capabilities (strv); + g_free (strv); + if (priv->capabilities != uint_val) { + priv->capabilities = uint_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + } + } else if (!strcmp (property, "Connected")) { + gboolean connected = g_variant_get_boolean (v); + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } + } + g_variant_unref (v); + } + + check_emit_usable (self); +} +#else static void property_changed (DBusGProxy *proxy4, const char *property, @@ -461,7 +616,65 @@ property_changed (DBusGProxy *proxy4, check_emit_usable (self); } +#endif +#if WITH_BLUEZ5 +static void +query_properties (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *v; + const char **uuids; + struct ether_addr *tmp; + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); + priv->address = v ? g_variant_dup_string (v, NULL) : NULL; + if (v) + g_variant_unref (v); + if (priv->address) { + tmp = ether_aton (priv->address); + g_assert (tmp); + memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); + } + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); + priv->name = v ? g_variant_dup_string (v, NULL) : NULL; + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "RSSI"); + priv->rssi = v ? g_variant_get_int16 (v) : 0; + if (v) + g_variant_unref (v); + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); + if (v) { + uuids = g_variant_get_strv (v, NULL); + priv->capabilities = convert_uuids_to_capabilities (uuids); + g_variant_unref (v); + } else + priv->capabilities = NM_BT_CAPABILITY_NONE; + + v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); + if (v) { + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + g_variant_get_string (v, NULL), + BLUEZ_ADAPTER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_adapter_acquired, + self); + g_variant_unref (v); + } + + priv->initialized = TRUE; + g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + + check_emit_usable (self); +} +#else static void get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) { @@ -530,20 +743,69 @@ query_properties (NMBluezDevice *self) priv->path); } } +#endif + + +#if WITH_BLUEZ5 +static void +on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + + priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy5) { + nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + return; + } + + g_signal_connect (priv->proxy5, "g-properties-changed", + G_CALLBACK (properties_changed), self); + + query_properties (self); +} + +static void +on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + + priv->dbus_connection = g_bus_get_finish (res, &error); + + if (!priv->dbus_connection) { + nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + return; + } + + check_emit_usable (self); +} +#endif /********************************************************************/ NMBluezDevice * nm_bluez_device_new (const char *path +#if ! WITH_BLUEZ5 , NMConnectionProvider *provider +#endif ) { NMBluezDevice *self; NMBluezDevicePrivate *priv; +#if ! WITH_BLUEZ5 DBusGConnection *connection; +#endif g_return_val_if_fail (path != NULL, NULL); +#if ! WITH_BLUEZ5 g_return_val_if_fail (provider != NULL, NULL); +#endif self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, NM_BLUEZ_DEVICE_PATH, path, @@ -553,6 +815,22 @@ nm_bluez_device_new (const char *path priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); +#if WITH_BLUEZ5 + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback) on_bus_acquired, + self); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + priv->path, + BLUEZ_DEVICE_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); +#else priv->provider = provider; g_signal_connect (priv->provider, @@ -592,6 +870,7 @@ nm_bluez_device_new (const char *path G_CALLBACK (property_changed), self, NULL); query_properties (self); +#endif return self; } @@ -606,6 +885,10 @@ dispose (GObject *object) NMBluezDevice *self = NM_BLUEZ_DEVICE (object); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); +#if WITH_BLUEZ5 + g_clear_object (&priv->adapter); + g_clear_object (&priv->dbus_connection); +#else g_slist_foreach (priv->connections, (GFunc) g_object_unref, NULL); g_slist_free (priv->connections); priv->connections = NULL; @@ -616,6 +899,7 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); g_clear_object (&priv->connection_proxy); +#endif G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } @@ -629,7 +913,11 @@ finalize (GObject *object) g_free (priv->address); g_free (priv->name); g_free (priv->bt_iface); +#if WITH_BLUEZ5 + g_object_unref (priv->proxy5); +#else g_object_unref (priv->proxy4); +#endif G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); } diff --git a/src/bluez-manager/nm-bluez5-device.c b/src/bluez-manager/nm-bluez5-device.c deleted file mode 100644 index 461e9546cc..0000000000 --- a/src/bluez-manager/nm-bluez5-device.c +++ /dev/null @@ -1,660 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2013 Intel Corporation. - */ - -#include -#include -#include -#include -#include - -#include "NetworkManager.h" -#include "nm-setting-bluetooth.h" - -#include "nm-bluez-common.h" -#include "nm-bluez-device.h" -#include "nm-logging.h" - - -G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) - -#define NM_BLUEZ_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_DEVICE, NMBluezDevicePrivate)) - -typedef struct { - char *path; - GDBusProxy *proxy5; - GDBusProxy *adapter; - GDBusConnection *dbus_connection; - - gboolean initialized; - gboolean usable; - NMBluetoothCapabilities connection_bt_type; - - char *address; - guint8 bin_address[ETH_ALEN]; - char *name; - guint32 capabilities; - gint rssi; - gboolean connected; - - char *bt_iface; -} NMBluezDevicePrivate; - - -enum { - PROP_0, - PROP_PATH, - PROP_ADDRESS, - PROP_NAME, - PROP_CAPABILITIES, - PROP_RSSI, - PROP_USABLE, - PROP_CONNECTED, - - LAST_PROP -}; - -/* Signals */ -enum { - INITIALIZED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - -/***********************************************************/ - -const char * -nm_bluez_device_get_path (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->path; -} - -const char * -nm_bluez_device_get_address (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->address; -} - -gboolean -nm_bluez_device_get_initialized (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->initialized; -} - -gboolean -nm_bluez_device_get_usable (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->usable; -} - -const char * -nm_bluez_device_get_name (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->name; -} - -guint32 -nm_bluez_device_get_capabilities (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->capabilities; -} - -gint -nm_bluez_device_get_rssi (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; -} - -gboolean -nm_bluez_device_get_connected (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; -} - -static void -check_emit_usable (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - gboolean new_usable; - - new_usable = (priv->initialized && priv->capabilities && priv->name && - priv->address && - priv->adapter && priv->dbus_connection - ); - if (new_usable != priv->usable) { - priv->usable = new_usable; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); - } -} - -/********************************************************************/ - -void -nm_bluez_device_call_disconnect (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_return_if_fail (priv->dbus_connection); - g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); - - g_dbus_connection_call (priv->dbus_connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_NETWORK_INTERFACE, - "Disconnect", - g_variant_new ("()"), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, NULL, NULL); - - priv->connection_bt_type = NM_BT_CAPABILITY_NONE; -} - -static void -bluez_connect_pan_cb (GDBusConnection *dbus_connection, - GAsyncResult *res, - gpointer user_data) -{ - GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); - NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - char *device; - GVariant *variant; - - variant = g_dbus_connection_call_finish (dbus_connection, res, &error); - - if (!variant) { - g_simple_async_result_take_error (result, error); - } else { - g_variant_get (variant, "(s)", &device); - - g_simple_async_result_set_op_res_gpointer (result, - g_strdup (device), - g_free); - priv->bt_iface = device; - g_variant_unref (variant); - } - - g_simple_async_result_complete (result); - g_object_unref (result); -} - -void -nm_bluez_device_connect_async (NMBluezDevice *self, - NMBluetoothCapabilities connection_bt_type, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); - - simple = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - nm_bluez_device_connect_async); - - /* For PAN we call Connect() on org.bluez.Network1 */ - g_dbus_connection_call (priv->dbus_connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_NETWORK_INTERFACE, - "Connect", - g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 20000, - NULL, - (GAsyncReadyCallback) bluez_connect_pan_cb, - simple); - - priv->connection_bt_type = connection_bt_type; -} - -const char * -nm_bluez_device_connect_finish (NMBluezDevice *self, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - const char *device; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, - G_OBJECT (self), - nm_bluez_device_connect_async), - NULL); - - simple = (GSimpleAsyncResult *) result; - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); - return device; -} - -/***********************************************************/ - -static guint32 -convert_uuids_to_capabilities (const char **strings) -{ - const char **iter; - guint32 capabilities = 0; - - for (iter = strings; iter && *iter; iter++) { - char **parts; - - parts = g_strsplit (*iter, "-", -1); - if (parts && parts[0]) { - switch (g_ascii_strtoull (parts[0], NULL, 16)) { - case 0x1116: - capabilities |= NM_BT_CAPABILITY_NAP; - break; - default: - break; - } - } - g_strfreev (parts); - } - - return capabilities; -} - -static void -on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error; - - priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->adapter) { - nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); - g_clear_error (&error); - return; - } - - check_emit_usable (self); -} - -static void -properties_changed (GDBusProxy *proxy5, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariantIter i; - const char *property; - const char *str; - GVariant *v; - guint32 uint_val; - gint int_val; - const char **strv; - - g_variant_iter_init (&i, changed_properties); - while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { - if (!strcmp (property, "Name")) { - str = g_variant_get_string (v, NULL); - if (g_strcmp0 (priv->name, str)) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_variant_get_int16 (v); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - strv = g_variant_get_strv (v, NULL); - uint_val = convert_uuids_to_capabilities (strv); - g_free (strv); - if (priv->capabilities != uint_val) { - priv->capabilities = uint_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); - } - } else if (!strcmp (property, "Connected")) { - gboolean connected = g_variant_get_boolean (v); - if (priv->connected != connected) { - priv->connected = connected; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); - } - } - g_variant_unref (v); - } - - check_emit_usable (self); -} - -static void -query_properties (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *v; - const char **uuids; - struct ether_addr *tmp; - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); - priv->address = v ? g_variant_dup_string (v, NULL) : NULL; - if (v) - g_variant_unref (v); - if (priv->address) { - tmp = ether_aton (priv->address); - g_assert (tmp); - memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); - } - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); - priv->name = v ? g_variant_dup_string (v, NULL) : NULL; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "RSSI"); - priv->rssi = v ? g_variant_get_int16 (v) : 0; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); - if (v) { - uuids = g_variant_get_strv (v, NULL); - priv->capabilities = convert_uuids_to_capabilities (uuids); - g_variant_unref (v); - } else - priv->capabilities = NM_BT_CAPABILITY_NONE; - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); - if (v) { - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - g_variant_get_string (v, NULL), - BLUEZ_ADAPTER_INTERFACE, - NULL, - (GAsyncReadyCallback) on_adapter_acquired, - self); - g_variant_unref (v); - } - - priv->initialized = TRUE; - g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - - check_emit_usable (self); -} - -static void -on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error; - - priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->proxy5) { - nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; - } - - g_signal_connect (priv->proxy5, "g-properties-changed", - G_CALLBACK (properties_changed), self); - - query_properties (self); -} - -static void -on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - - priv->dbus_connection = g_bus_get_finish (res, &error); - - if (!priv->dbus_connection) { - nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; - } - - check_emit_usable (self); -} - -/********************************************************************/ - -NMBluezDevice * -nm_bluez_device_new (const char *path - ) -{ - NMBluezDevice *self; - NMBluezDevicePrivate *priv; - - g_return_val_if_fail (path != NULL, NULL); - - self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, - NM_BLUEZ_DEVICE_PATH, path, - NULL); - if (!self) - return NULL; - - priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_bus_get (G_BUS_TYPE_SYSTEM, - NULL, - (GAsyncReadyCallback) on_bus_acquired, - self); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - self); - - return self; -} - -static void -nm_bluez_device_init (NMBluezDevice *self) -{ -} - -static void -dispose (GObject *object) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (object); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_clear_object (&priv->adapter); - g_clear_object (&priv->dbus_connection); - - G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); - - g_free (priv->path); - g_free (priv->address); - g_free (priv->name); - g_free (priv->bt_iface); - g_object_unref (priv->proxy5); - - G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_ADDRESS: - g_value_set_string (value, priv->address); - break; - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_RSSI: - g_value_set_int (value, priv->rssi); - break; - case PROP_USABLE: - g_value_set_boolean (value, priv->usable); - break; - case PROP_CONNECTED: - g_value_set_boolean (value, priv->connected); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - /* construct only */ - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_bluez_device_class_init (NMBluezDeviceClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (config_class); - - g_type_class_add_private (config_class, sizeof (NMBluezDevicePrivate)); - - /* virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_PATH, - g_param_spec_string (NM_BLUEZ_DEVICE_PATH, - "DBus Path", - "DBus Path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_ADDRESS, - g_param_spec_string (NM_BLUEZ_DEVICE_ADDRESS, - "Address", - "Address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_NAME, - g_param_spec_string (NM_BLUEZ_DEVICE_NAME, - "Name", - "Name", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_BLUEZ_DEVICE_CAPABILITIES, - "Capabilities", - "Capabilities", - 0, G_MAXUINT, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_RSSI, - g_param_spec_int (NM_BLUEZ_DEVICE_RSSI, - "RSSI", - "RSSI", - G_MININT, G_MAXINT, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_USABLE, - g_param_spec_boolean (NM_BLUEZ_DEVICE_USABLE, - "Usable", - "Usable", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CONNECTED, - g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, - "Connected", - "Connected", - FALSE, - G_PARAM_READABLE)); - - /* Signals */ - signals[INITIALIZED] = g_signal_new ("initialized", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezDeviceClass, initialized), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); -} - From bda25894ea913f6344ebf3dbdb4fee1c63be0d26 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Sep 2013 15:44:02 +0200 Subject: [PATCH 14/29] trivial: rename function nm_bluez_device_call_disconnect to nm_bluez_device_disconnect Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 2 +- src/bluez-manager/nm-bluez-device.h | 2 +- src/devices/nm-device-bt.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index a5e3631fd0..0da51b7257 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -273,7 +273,7 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) #endif void -nm_bluez_device_call_disconnect (NMBluezDevice *self) +nm_bluez_device_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index d03d4bafdf..dfc3e441b7 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -95,7 +95,7 @@ nm_bluez_device_connect_finish (NMBluezDevice *self, GError **error); void -nm_bluez_device_call_disconnect (NMBluezDevice *self); +nm_bluez_device_disconnect (NMBluezDevice *self); #endif /* NM_BLUEZ_DEVICE_H */ diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index cb8c790979..b0be0fbfc3 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -904,7 +904,7 @@ deactivate (NMDevice *device) } } - nm_bluez_device_call_disconnect (priv->bt_device); + nm_bluez_device_disconnect (priv->bt_device); if (priv->timeout_id) { g_source_remove (priv->timeout_id); From dc85b22e0aaa6b89d256dd31a20132fe45743a60 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 19 Sep 2013 14:08:31 +0200 Subject: [PATCH 15/29] bluez: take reference for device before creating dbus adapter Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 0da51b7257..3be7dfd85d 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -513,10 +513,10 @@ on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) if (!priv->adapter) { nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); g_clear_error (&error); - return; - } + } else + check_emit_usable (self); - check_emit_usable (self); + g_object_unref (self); } static void @@ -657,6 +657,7 @@ query_properties (NMBluezDevice *self) v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); if (v) { + g_object_ref (self); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, @@ -759,13 +760,13 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); g_clear_error (&error); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; + } else { + g_signal_connect (priv->proxy5, "g-properties-changed", + G_CALLBACK (properties_changed), self); + + query_properties (self); } - - g_signal_connect (priv->proxy5, "g-properties-changed", - G_CALLBACK (properties_changed), self); - - query_properties (self); + g_object_unref (self); } static void @@ -821,6 +822,7 @@ nm_bluez_device_new (const char *path (GAsyncReadyCallback) on_bus_acquired, self); + g_object_ref (self); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, From 008453e61f89f23c6479e5d8d8064aa408186105 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 8 Sep 2013 16:04:34 +0200 Subject: [PATCH 16/29] bluez: connections must be pre-configured for BlueZ 5 devices Modify BlueZ 5 device to have the same behaviour as BlueZ 4, i.e. a pre-configured connection must exist for the device to show up in NetworkManager's device list. Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 62 ++++++++++++--------------- src/bluez-manager/nm-bluez-device.h | 6 +-- src/bluez-manager/nm-bluez-manager.h | 8 +--- src/bluez-manager/nm-bluez5-manager.c | 9 +++- src/nm-manager.c | 6 +-- 5 files changed, 37 insertions(+), 54 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 3be7dfd85d..596ef5b904 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -65,10 +65,8 @@ typedef struct { char *bt_iface; -#if ! WITH_BLUEZ5 NMConnectionProvider *provider; GSList *connections; -#endif } NMBluezDevicePrivate; @@ -167,10 +165,9 @@ check_emit_usable (NMBluezDevice *self) new_usable = (priv->initialized && priv->capabilities && priv->name && priv->address && #if WITH_BLUEZ5 - priv->adapter && priv->dbus_connection -#else - priv->connections + priv->adapter && priv->dbus_connection && #endif + priv->connections ); if (new_usable != priv->usable) { priv->usable = new_usable; @@ -180,7 +177,6 @@ check_emit_usable (NMBluezDevice *self) /********************************************************************/ -#if ! WITH_BLUEZ5 static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection) { @@ -270,7 +266,6 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) } /***********************************************************/ -#endif void nm_bluez_device_disconnect (NMBluezDevice *self) @@ -670,6 +665,9 @@ query_properties (NMBluezDevice *self) g_variant_unref (v); } + /* Check if any connections match this device */ + cp_connections_loaded (priv->provider, self); + priv->initialized = TRUE; g_signal_emit (self, signals[INITIALIZED], 0, TRUE); @@ -791,11 +789,7 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) /********************************************************************/ NMBluezDevice * -nm_bluez_device_new (const char *path -#if ! WITH_BLUEZ5 - , NMConnectionProvider *provider -#endif - ) +nm_bluez_device_new (const char *path, NMConnectionProvider *provider) { NMBluezDevice *self; NMBluezDevicePrivate *priv; @@ -804,9 +798,7 @@ nm_bluez_device_new (const char *path #endif g_return_val_if_fail (path != NULL, NULL); -#if ! WITH_BLUEZ5 g_return_val_if_fail (provider != NULL, NULL); -#endif self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, NM_BLUEZ_DEVICE_PATH, path, @@ -816,23 +808,6 @@ nm_bluez_device_new (const char *path priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); -#if WITH_BLUEZ5 - g_bus_get (G_BUS_TYPE_SYSTEM, - NULL, - (GAsyncReadyCallback) on_bus_acquired, - self); - - g_object_ref (self); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - self); -#else priv->provider = provider; g_signal_connect (priv->provider, @@ -855,6 +830,23 @@ nm_bluez_device_new (const char *path G_CALLBACK (cp_connections_loaded), self); +#if WITH_BLUEZ5 + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback) on_bus_acquired, + self); + + g_object_ref (self); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + priv->path, + BLUEZ_DEVICE_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); +#else connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); priv->proxy4 = dbus_g_proxy_new_for_name (connection, @@ -887,10 +879,6 @@ dispose (GObject *object) NMBluezDevice *self = NM_BLUEZ_DEVICE (object); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); -#if WITH_BLUEZ5 - g_clear_object (&priv->adapter); - g_clear_object (&priv->dbus_connection); -#else g_slist_foreach (priv->connections, (GFunc) g_object_unref, NULL); g_slist_free (priv->connections); priv->connections = NULL; @@ -900,6 +888,10 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); +#if WITH_BLUEZ5 + g_clear_object (&priv->adapter); + g_clear_object (&priv->dbus_connection); +#else g_clear_object (&priv->connection_proxy); #endif diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index dfc3e441b7..11add38901 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -59,11 +59,7 @@ typedef struct { GType nm_bluez_device_get_type (void); -NMBluezDevice *nm_bluez_device_new (const char *path -#if ! WITH_BLUEZ5 - , NMConnectionProvider *provider -#endif - ); +NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider); const char *nm_bluez_device_get_path (NMBluezDevice *self); diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h index 3391f7f5c1..95e319c5e0 100644 --- a/src/bluez-manager/nm-bluez-manager.h +++ b/src/bluez-manager/nm-bluez-manager.h @@ -61,13 +61,7 @@ typedef struct { GType nm_bluez_manager_get_type (void); -NMBluezManager *nm_bluez_manager_get ( -#if WITH_BLUEZ5 - void -#else - NMConnectionProvider *provider -#endif - ); +NMBluezManager *nm_bluez_manager_get (NMConnectionProvider *provider); void nm_bluez_manager_query_devices (NMBluezManager *manager); diff --git a/src/bluez-manager/nm-bluez5-manager.c b/src/bluez-manager/nm-bluez5-manager.c index b138eec066..0542be87c0 100644 --- a/src/bluez-manager/nm-bluez5-manager.c +++ b/src/bluez-manager/nm-bluez5-manager.c @@ -36,6 +36,8 @@ typedef struct { NMDBusManager *dbus_mgr; gulong name_owner_changed_id; + NMConnectionProvider *provider; + GDBusProxy *proxy; GHashTable *devices; @@ -117,7 +119,7 @@ device_added (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path); + device = nm_bluez_device_new (path, priv->provider); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); @@ -329,7 +331,7 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, /****************************************************************/ NMBluezManager * -nm_bluez_manager_get (void) +nm_bluez_manager_get (NMConnectionProvider *provider) { static NMBluezManager *singleton = NULL; @@ -339,6 +341,9 @@ nm_bluez_manager_get (void) singleton = (NMBluezManager *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); g_assert (singleton); + /* Cache the connection provider for NMBluezAdapter objects */ + NM_BLUEZ_MANAGER_GET_PRIVATE (singleton)->provider = provider; + return singleton; } diff --git a/src/nm-manager.c b/src/nm-manager.c index 416fefd84b..f395f03302 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4452,11 +4452,7 @@ nm_manager_new (NMSettings *settings, G_CALLBACK (rfkill_manager_rfkill_changed_cb), singleton); - priv->bluez_mgr = nm_bluez_manager_get ( -#if ! WITH_BLUEZ5 - NM_CONNECTION_PROVIDER (priv->settings) -#endif - ); + priv->bluez_mgr = nm_bluez_manager_get (NM_CONNECTION_PROVIDER (priv->settings)); g_signal_connect (priv->bluez_mgr, NM_BLUEZ_MANAGER_BDADDR_ADDED, From 3b12d9ae6ebca1cd7172c6017ecc6393e8a96af9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 12 Sep 2013 16:50:38 +0200 Subject: [PATCH 17/29] core: add has_connections_loaded method to NMConnectionProvider This method returns true, if the connections are already loaded (and the connection_loaded signal already emited). Signed-off-by: Thomas Haller --- src/nm-connection-provider.c | 9 +++++++++ src/nm-connection-provider.h | 14 ++++++++++++++ src/settings/nm-settings.c | 9 +++++++++ 3 files changed, 32 insertions(+) diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c index 401f8dabb7..dca4bfb668 100644 --- a/src/nm-connection-provider.c +++ b/src/nm-connection-provider.c @@ -40,6 +40,15 @@ nm_connection_provider_get_connections (NMConnectionProvider *self) return NULL; } +gboolean +nm_connection_provider_has_connections_loaded (NMConnectionProvider *self) +{ + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), FALSE); + + g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->has_connections_loaded); + return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->has_connections_loaded (self); +} + /*****************************************************************************/ static void diff --git a/src/nm-connection-provider.h b/src/nm-connection-provider.h index 942651f76b..75a572ed53 100644 --- a/src/nm-connection-provider.h +++ b/src/nm-connection-provider.h @@ -58,6 +58,8 @@ struct _NMConnectionProvider { const GSList * (*get_connections) (NMConnectionProvider *self); + gboolean (*has_connections_loaded) (NMConnectionProvider *self); + /* Signals */ void (*connection_added) (NMConnectionProvider *self, NMConnection *connection); @@ -103,4 +105,16 @@ GSList *nm_connection_provider_get_best_connections (NMConnectionProvider *self, */ const GSList *nm_connection_provider_get_connections (NMConnectionProvider *self); +/** + * nm_connection_provider_has_connections_loaded: + * @self: the #NMConnectionProvider + * + * Returns: TRUE or FALSE indicating whether the connections of the provider are already + * loaded. If they are not yet loaded, the provider will not emit the signals + * NM_CP_SIGNAL_CONNECTION_ADDED, NM_CP_SIGNAL_CONNECTION_UPDATED and + * NM_CP_SIGNAL_CONNECTION_REMOVED until NM_CP_SIGNAL_CONNECTIONS_LOADED gets + * emited. + */ +gboolean nm_connection_provider_has_connections_loaded (NMConnectionProvider *self); + #endif /* NM_CONNECTION_PROVIDER_H */ diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index b18a9af9ca..2da97624d7 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1635,6 +1635,14 @@ get_connections (NMConnectionProvider *provider) return g_slist_reverse (list); } +static gboolean +has_connections_loaded (NMConnectionProvider *provider) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (provider); + + return priv->connections_loaded; +} + /***************************************************************/ NMSettings * @@ -1667,6 +1675,7 @@ connection_provider_init (NMConnectionProvider *cp_class) { cp_class->get_best_connections = get_best_connections; cp_class->get_connections = get_connections; + cp_class->has_connections_loaded = has_connections_loaded; } static void From 98daf270ba69000db8e0bb7c09b26d1cd9aaf14a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 17 Sep 2013 12:42:51 +0200 Subject: [PATCH 18/29] core: add add_connection method to NMConnectionProvider This exposes the functionality of nm_settings_add_connection to the users of NMConnectionProvider. Signed-off-by: Thomas Haller --- src/nm-connection-provider.c | 12 ++++++++++++ src/nm-connection-provider.h | 20 ++++++++++++++++++++ src/settings/nm-settings.c | 11 +++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c index dca4bfb668..467d99d2b1 100644 --- a/src/nm-connection-provider.c +++ b/src/nm-connection-provider.c @@ -49,6 +49,18 @@ nm_connection_provider_has_connections_loaded (NMConnectionProvider *self) return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->has_connections_loaded (self); } +NMConnection * +nm_connection_provider_add_connection (NMConnectionProvider *self, + NMConnection *connection, + gboolean save_to_disk, + GError **error) +{ + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); + + g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection); + return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection (self, connection, save_to_disk, error); +} + /*****************************************************************************/ static void diff --git a/src/nm-connection-provider.h b/src/nm-connection-provider.h index 75a572ed53..2afbc6d65c 100644 --- a/src/nm-connection-provider.h +++ b/src/nm-connection-provider.h @@ -60,6 +60,11 @@ struct _NMConnectionProvider { gboolean (*has_connections_loaded) (NMConnectionProvider *self); + NMConnection * (*add_connection) (NMConnectionProvider *self, + NMConnection *connection, + gboolean save_to_disk, + GError **error); + /* Signals */ void (*connection_added) (NMConnectionProvider *self, NMConnection *connection); @@ -117,4 +122,19 @@ const GSList *nm_connection_provider_get_connections (NMConnectionProvider *self */ gboolean nm_connection_provider_has_connections_loaded (NMConnectionProvider *self); + +/** + * nm_connection_provider_add_connection: + * @self: the #NMConnectionProvider + * @connection: the connection to be added + * @save_to_disk: whether to store the connection on disk + * @error: returns any error if adding fails + * + * returns: a newly added #NMConnection. + */ +NMConnection *nm_connection_provider_add_connection (NMConnectionProvider *self, + NMConnection *connection, + gboolean save_to_disk, + GError **error); + #endif /* NM_CONNECTION_PROVIDER_H */ diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 2da97624d7..2d3e278351 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -930,6 +930,16 @@ nm_settings_add_connection (NMSettings *self, return NULL; } +static NMConnection * +_nm_connection_provider_add_connection (NMConnectionProvider *provider, + NMConnection *connection, + gboolean save_to_disk, + GError **error) +{ + g_assert (NM_IS_CONNECTION_PROVIDER (provider) && NM_IS_SETTINGS (provider)); + return NM_CONNECTION (nm_settings_add_connection (NM_SETTINGS (provider), connection, save_to_disk, error)); +} + static gboolean secrets_filter_cb (NMSetting *setting, const char *secret, @@ -1676,6 +1686,7 @@ connection_provider_init (NMConnectionProvider *cp_class) cp_class->get_best_connections = get_best_connections; cp_class->get_connections = get_connections; cp_class->has_connections_loaded = has_connections_loaded; + cp_class->add_connection = _nm_connection_provider_add_connection; } static void From 57e19288b7fc0e3e61cd184fe8583de49f2ae4fa Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 17 Sep 2013 11:03:57 +0200 Subject: [PATCH 19/29] bluez: create NMConnection for PAN devices Create a new NMConnection for PAN devices if no compatible connection exists and export it via DBUS. This has the effect of always exposing any usable PAN-capable device. https://bugzilla.gnome.org/show_bug.cgi?id=701078 Signed-off-by: Thomas Haller --- po/POTFILES.in | 1 + src/bluez-manager/nm-bluez-device.c | 135 ++++++++++++++++++++++++++-- 2 files changed, 131 insertions(+), 5 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index a608f34cf8..e953666cc3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -36,6 +36,7 @@ libnm-util/nm-setting-wireless.c libnm-util/nm-utils.c policy/org.freedesktop.NetworkManager.policy.in.in src/main.c +src/bluez-manager/nm-bluez-device.c src/dhcp-manager/nm-dhcp-dhclient.c src/dhcp-manager/nm-dhcp-dhclient-utils.c src/dhcp-manager/nm-dhcp-manager.c diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 596ef5b904..da6a57314e 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -20,6 +20,7 @@ */ #include +#include #include #include #include @@ -35,6 +36,7 @@ #endif #include "nm-bluez-device.h" #include "nm-logging.h" +#include "nm-utils.h" G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) @@ -67,6 +69,9 @@ typedef struct { NMConnectionProvider *provider; GSList *connections; + + NMConnection *pan_connection; + gboolean pan_connection_no_autocreate; } NMBluezDevicePrivate; @@ -90,6 +95,11 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; + +static void cp_connection_added (NMConnectionProvider *provider, + NMConnection *connection, NMBluezDevice *self); + + /***********************************************************/ const char * @@ -156,6 +166,102 @@ nm_bluez_device_get_connected (NMBluezDevice *self) return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; } +static void +pan_connection_check_create (NMBluezDevice *self) +{ + NMConnection *connection; + NMConnection *added; + NMSetting *setting; + char *uuid, *id; + GByteArray *bdaddr_array; + GError *error = NULL; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (priv->capabilities & NM_BT_CAPABILITY_NAP); + g_return_if_fail (priv->connections == NULL); + g_return_if_fail (priv->name); + + if (priv->pan_connection || priv->pan_connection_no_autocreate) { + /* already have a connection or we don't want to create one, nothing to do. */ + return; + } + + if (!nm_connection_provider_has_connections_loaded (priv->provider)) { + /* do not try to create any connections until the connection provider is ready. */ + return; + } + + /* Only try once to create a connection. If it does not succeed, we do not try again. Also, + * if the connection gets deleted later, do not create another one for this device. */ + priv->pan_connection_no_autocreate = TRUE; + + /* create a new connection */ + + connection = nm_connection_new (); + + /* Setting: Connection */ + uuid = nm_utils_uuid_generate (); + id = g_strdup_printf (_("%s Network"), priv->name); + setting = nm_setting_connection_new (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, + NULL); + nm_connection_add_setting (connection, setting); + + /* Setting: Bluetooth */ + bdaddr_array = g_byte_array_sized_new (sizeof (priv->bin_address)); + g_byte_array_append (bdaddr_array, priv->bin_address, sizeof (priv->bin_address)); + setting = nm_setting_bluetooth_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_BLUETOOTH_BDADDR, bdaddr_array, + NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + nm_connection_add_setting (connection, setting); + g_byte_array_free (bdaddr_array, TRUE); + + /* Setting: IPv4 */ + setting = nm_setting_ip4_config_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_MAY_FAIL, FALSE, + NULL); + nm_connection_add_setting (connection, setting); + + /* Setting: IPv6 */ + setting = nm_setting_ip6_config_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, + NULL); + nm_connection_add_setting (connection, setting); + + /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) + * which then already finds the suitable connection in priv->connections. This is confusing, + * so block the signal. check_emit_usable will succeed after this function call returns. */ + g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); + added = nm_connection_provider_add_connection (priv->provider, connection, FALSE, &error); + g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); + + if (added) { + g_assert (g_slist_find (priv->connections, added)); + + priv->pan_connection = added; + nm_log_dbg (LOGD_SETTINGS, "added new Bluetooth connection for NAP device '%s': '%s' (%s)", priv->path, id, uuid); + } else { + nm_log_warn (LOGD_SETTINGS, "couldn't add new Bluetooth connection for NAP device '%s': '%s' (%s): %d / %s", + priv->path, id, uuid, error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + } + + g_object_unref (connection); + g_free (id); + g_free (uuid); +} + static void check_emit_usable (NMBluezDevice *self) { @@ -163,12 +269,28 @@ check_emit_usable (NMBluezDevice *self) gboolean new_usable; new_usable = (priv->initialized && priv->capabilities && priv->name && - priv->address && #if WITH_BLUEZ5 priv->adapter && priv->dbus_connection && + (priv->capabilities & NM_BT_CAPABILITY_NAP) && /* BlueZ5 is only usable with NAP devices */ #endif - priv->connections - ); + priv->address); + + if (!new_usable) + goto END; + + if (priv->connections) + goto END; + + if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { + /* non NAP devices are only usable, if they already have a connection. */ + new_usable = FALSE; + goto END; + } + + pan_connection_check_create (self); + new_usable = !!priv->pan_connection; + +END: if (new_usable != priv->usable) { priv->usable = new_usable; g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); @@ -201,11 +323,11 @@ connection_compatible (NMBluezDevice *self, NMConnection *connection) bt_type = nm_setting_bluetooth_get_connection_type (s_bt); if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) - return FALSE; + return FALSE; if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) - return FALSE; + return FALSE; return TRUE; } @@ -239,6 +361,9 @@ cp_connection_removed (NMConnectionProvider *provider, if (g_slist_find (priv->connections, connection)) { priv->connections = g_slist_remove (priv->connections, connection); + if (priv->pan_connection == connection) { + priv->pan_connection = NULL; + } g_object_unref (connection); check_emit_usable (self); } From cfd4d5209cac4e850ed07a8f935690e2c8841f41 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Sep 2013 19:17:21 +0200 Subject: [PATCH 20/29] bluez: do not allow resetting the capabilities of a bluez device Also freeze gobject notifications while updating proberties. Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 56 ++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index da6a57314e..16f2fc77e4 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -268,10 +268,16 @@ check_emit_usable (NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); gboolean new_usable; + /* only expect the supported capabilities set. */ + g_assert ((priv->capabilities & ~( NM_BT_CAPABILITY_NAP +#if ! WITH_BLUEZ5 + | NM_BT_CAPABILITY_DUN +#endif + )) == NM_BT_CAPABILITY_NONE); + new_usable = (priv->initialized && priv->capabilities && priv->name && #if WITH_BLUEZ5 priv->adapter && priv->dbus_connection && - (priv->capabilities & NM_BT_CAPABILITY_NAP) && /* BlueZ5 is only usable with NAP devices */ #endif priv->address); @@ -621,6 +627,30 @@ convert_uuids_to_capabilities (const char **strings) return capabilities; } +static void +_set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean notify) +{ + guint32 uint_val; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + uint_val = convert_uuids_to_capabilities (uuids); + if (priv->capabilities != uint_val) { + if (priv->capabilities) { + /* changing (relevant) capabilities is not supported and ignored -- except setting initially */ + nm_log_warn (LOGD_BT, "ignore change of capabilities for Bluetooth device %s from %u to %u", + priv->path, priv->capabilities, uint_val); + return; + } + nm_log_dbg (LOGD_BT, "set capabilities for Bluetooth device %s: %s%s%s", priv->path, + uint_val & NM_BT_CAPABILITY_NAP ? "NAP" : "", + ((uint_val & NM_BT_CAPABILITY_DUN) && (uint_val &NM_BT_CAPABILITY_NAP)) ? " | " : "", + uint_val & NM_BT_CAPABILITY_DUN ? "DUN" : ""); + priv->capabilities = uint_val; + if (notify) + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + } +} + #if WITH_BLUEZ5 static void on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) @@ -651,10 +681,10 @@ properties_changed (GDBusProxy *proxy5, const char *property; const char *str; GVariant *v; - guint32 uint_val; gint int_val; const char **strv; + g_object_freeze_notify (G_OBJECT (self)); g_variant_iter_init (&i, changed_properties); while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { if (!strcmp (property, "Name")) { @@ -672,12 +702,8 @@ properties_changed (GDBusProxy *proxy5, } } else if (!strcmp (property, "UUIDs")) { strv = g_variant_get_strv (v, NULL); - uint_val = convert_uuids_to_capabilities (strv); + _set_property_capabilities (self, strv, TRUE); g_free (strv); - if (priv->capabilities != uint_val) { - priv->capabilities = uint_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); - } } else if (!strcmp (property, "Connected")) { gboolean connected = g_variant_get_boolean (v); if (priv->connected != connected) { @@ -687,6 +713,7 @@ properties_changed (GDBusProxy *proxy5, } g_variant_unref (v); } + g_object_thaw_notify (G_OBJECT (self)); check_emit_usable (self); } @@ -700,9 +727,9 @@ property_changed (DBusGProxy *proxy4, NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); const char *str; - guint32 uint_val; gint int_val; + g_object_freeze_notify (G_OBJECT (self)); { if (!strcmp (property, "Name")) { str = g_value_get_string (value); @@ -720,11 +747,7 @@ property_changed (DBusGProxy *proxy4, g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); } } else if (!strcmp (property, "UUIDs")) { - uint_val = convert_uuids_to_capabilities ((const char **) g_value_get_boxed (value)); - if (priv->capabilities != uint_val) { - priv->capabilities = uint_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); - } + _set_property_capabilities (self, (const char **) g_value_get_boxed (value), TRUE); } else if (!strcmp (property, "Connected")) { gboolean connected = g_value_get_boolean (value); if (priv->connected != connected) { @@ -733,6 +756,7 @@ property_changed (DBusGProxy *proxy4, } } } + g_object_thaw_notify (G_OBJECT (self)); check_emit_usable (self); } @@ -770,7 +794,7 @@ query_properties (NMBluezDevice *self) v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); if (v) { uuids = g_variant_get_strv (v, NULL); - priv->capabilities = convert_uuids_to_capabilities (uuids); + _set_property_capabilities (self, uuids, FALSE); g_variant_unref (v); } else priv->capabilities = NM_BT_CAPABILITY_NONE; @@ -807,7 +831,6 @@ get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) GHashTable *properties = NULL; GError *err = NULL; GValue *value; - const char **uuids; struct ether_addr *tmp; if (!dbus_g_proxy_end_call (proxy4, call, &err, @@ -836,8 +859,7 @@ get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) value = g_hash_table_lookup (properties, "UUIDs"); if (value) { - uuids = (const char **) g_value_get_boxed (value); - priv->capabilities = convert_uuids_to_capabilities (uuids); + _set_property_capabilities (self, (const char **) g_value_get_boxed (value), FALSE); } else priv->capabilities = NM_BT_CAPABILITY_NONE; From b246788bc46cf7e9fe4d7d802f17f18c50acece5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Sep 2013 20:48:45 +0200 Subject: [PATCH 21/29] config: make BlueZ 5 default and replace --enable-bluez5 with --enable-bluez4 Build now BlueZ 5 by default and rename the configure flag --enable-bluez5 to --enable-bluez4. Signed-off-by: Thomas Haller --- configure.ac | 16 +++++++------- src/Makefile.am | 8 +++---- src/bluez-manager/nm-bluez-common.h | 2 +- src/bluez-manager/nm-bluez-device.c | 34 ++++++++++++++--------------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/configure.ac b/configure.ac index c17db5d4f6..424c904f6b 100644 --- a/configure.ac +++ b/configure.ac @@ -268,15 +268,15 @@ fi AC_SUBST(UDEV_BASE_DIR) # BlueZ -AC_ARG_ENABLE(bluez5, AS_HELP_STRING([--enable-bluez5], - [build with BlueZ 5 support instead of BlueZ 4]), - [enable_bluez5=${enableval}]) -if (test "${enable_bluez5}" = "yes"); then - AC_DEFINE(WITH_BLUEZ5, 1, [Define if you have BlueZ 5 support]) +AC_ARG_ENABLE(bluez4, AS_HELP_STRING([--enable-bluez4], + [build with BlueZ 4 support instead of BlueZ 5]), + [enable_bluez4=${enableval}]) +if (test "${enable_bluez4}" = "yes"); then + AC_DEFINE(WITH_BLUEZ4, 1, [Define if you have BlueZ 4 support]) else - AC_DEFINE(WITH_BLUEZ5, 0, [Define if you have BlueZ 5 support]) + AC_DEFINE(WITH_BLUEZ4, 0, [Define if you have BlueZ 4 support]) fi -AM_CONDITIONAL(WITH_BLUEZ5, test "${enable_bluez5}" = "yes") +AM_CONDITIONAL(WITH_BLUEZ4, test "${enable_bluez4}" = "yes") # systemd unit support AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], @@ -825,7 +825,7 @@ echo " modemmanager-1: $with_modem_manager_1" echo " concheck: $enable_concheck" echo " libndp: $libndp_location" echo " libteamdctl: $enable_teamdctl" -echo " bluez 5: $enable_bluez5" +echo " bluez 4: $enable_bluez4" echo echo "Configuration plugins" diff --git a/src/Makefile.am b/src/Makefile.am index 700afe3417..532c62fffe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -264,14 +264,14 @@ nm_sources += \ bluez-manager/nm-bluez-device.h \ bluez-manager/nm-bluez-manager.h -if WITH_BLUEZ5 -nm_sources += \ - bluez-manager/nm-bluez5-manager.c -else +if WITH_BLUEZ4 nm_sources += \ bluez-manager/nm-bluez-adapter.h \ bluez-manager/nm-bluez-adapter.c \ bluez-manager/nm-bluez-manager.c +else +nm_sources += \ + bluez-manager/nm-bluez5-manager.c endif if WITH_MODEM_MANAGER_1 diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h index 4bf029d9a4..ecc4d70947 100644 --- a/src/bluez-manager/nm-bluez-common.h +++ b/src/bluez-manager/nm-bluez-common.h @@ -31,7 +31,7 @@ #define BLUEZ_MANAGER_PATH "/" #define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1" #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1" diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 16f2fc77e4..b827aa3591 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -30,7 +30,7 @@ #include "nm-setting-bluetooth.h" #include "nm-bluez-common.h" -#if ! WITH_BLUEZ5 +#if WITH_BLUEZ4 #include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" #endif @@ -45,7 +45,7 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 GDBusProxy *proxy5; GDBusProxy *adapter; GDBusConnection *dbus_connection; @@ -270,13 +270,13 @@ check_emit_usable (NMBluezDevice *self) /* only expect the supported capabilities set. */ g_assert ((priv->capabilities & ~( NM_BT_CAPABILITY_NAP -#if ! WITH_BLUEZ5 +#if WITH_BLUEZ4 | NM_BT_CAPABILITY_DUN #endif )) == NM_BT_CAPABILITY_NONE); new_usable = (priv->initialized && priv->capabilities && priv->name && -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 priv->adapter && priv->dbus_connection && #endif priv->address); @@ -403,7 +403,7 @@ nm_bluez_device_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 g_return_if_fail (priv->dbus_connection); g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); @@ -442,7 +442,7 @@ nm_bluez_device_disconnect (NMBluezDevice *self) } static void -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 bluez_connect_pan_cb (GDBusConnection *dbus_connection, GAsyncResult *res, gpointer user_data) @@ -458,7 +458,7 @@ bluez_connect_cb (DBusGProxy *proxy4, GError *error = NULL; char *device; -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 GVariant *variant; variant = g_dbus_connection_call_finish (dbus_connection, res, &error); @@ -503,13 +503,13 @@ nm_bluez_device_connect_async (NMBluezDevice *self, { GSimpleAsyncResult *simple; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); -#if ! WITH_BLUEZ5 +#if WITH_BLUEZ4 DBusGConnection *connection; connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); #endif -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); simple = g_simple_async_result_new (G_OBJECT (self), @@ -609,7 +609,7 @@ convert_uuids_to_capabilities (const char **strings) parts = g_strsplit (*iter, "-", -1); if (parts && parts[0]) { switch (g_ascii_strtoull (parts[0], NULL, 16)) { -#if ! WITH_BLUEZ5 +#if WITH_BLUEZ4 case 0x1103: capabilities |= NM_BT_CAPABILITY_DUN; break; @@ -651,7 +651,7 @@ _set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean no } } -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 static void on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) { @@ -762,7 +762,7 @@ property_changed (DBusGProxy *proxy4, } #endif -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 static void query_properties (NMBluezDevice *self) { @@ -892,7 +892,7 @@ query_properties (NMBluezDevice *self) #endif -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 static void on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) { @@ -940,7 +940,7 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) { NMBluezDevice *self; NMBluezDevicePrivate *priv; -#if ! WITH_BLUEZ5 +#if WITH_BLUEZ4 DBusGConnection *connection; #endif @@ -977,7 +977,7 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) G_CALLBACK (cp_connections_loaded), self); -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 g_bus_get (G_BUS_TYPE_SYSTEM, NULL, (GAsyncReadyCallback) on_bus_acquired, @@ -1035,7 +1035,7 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 g_clear_object (&priv->adapter); g_clear_object (&priv->dbus_connection); #else @@ -1054,7 +1054,7 @@ finalize (GObject *object) g_free (priv->address); g_free (priv->name); g_free (priv->bt_iface); -#if WITH_BLUEZ5 +#if ! WITH_BLUEZ4 g_object_unref (priv->proxy5); #else g_object_unref (priv->proxy4); From 03aeaf7b7718211322f6620c76827132599d8055 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Sep 2013 21:00:33 +0200 Subject: [PATCH 22/29] bluez: rename files from nm-bluez-* to nm-bluez4-* Signed-off-by: Thomas Haller --- src/Makefile.am | 6 +++--- .../{nm-bluez-adapter.c => nm-bluez4-adapter.c} | 2 +- .../{nm-bluez-adapter.h => nm-bluez4-adapter.h} | 0 .../{nm-bluez-manager.c => nm-bluez4-manager.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/bluez-manager/{nm-bluez-adapter.c => nm-bluez4-adapter.c} (99%) rename src/bluez-manager/{nm-bluez-adapter.h => nm-bluez4-adapter.h} (100%) rename src/bluez-manager/{nm-bluez-manager.c => nm-bluez4-manager.c} (99%) diff --git a/src/Makefile.am b/src/Makefile.am index 532c62fffe..e391da0edf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -266,9 +266,9 @@ nm_sources += \ if WITH_BLUEZ4 nm_sources += \ - bluez-manager/nm-bluez-adapter.h \ - bluez-manager/nm-bluez-adapter.c \ - bluez-manager/nm-bluez-manager.c + bluez-manager/nm-bluez4-adapter.h \ + bluez-manager/nm-bluez4-adapter.c \ + bluez-manager/nm-bluez4-manager.c else nm_sources += \ bluez-manager/nm-bluez5-manager.c diff --git a/src/bluez-manager/nm-bluez-adapter.c b/src/bluez-manager/nm-bluez4-adapter.c similarity index 99% rename from src/bluez-manager/nm-bluez-adapter.c rename to src/bluez-manager/nm-bluez4-adapter.c index caa50b0f1d..e9f806f71b 100644 --- a/src/bluez-manager/nm-bluez-adapter.c +++ b/src/bluez-manager/nm-bluez4-adapter.c @@ -23,7 +23,7 @@ #include "NetworkManager.h" #include "nm-dbus-manager.h" -#include "nm-bluez-adapter.h" +#include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-dbus-glib-types.h" diff --git a/src/bluez-manager/nm-bluez-adapter.h b/src/bluez-manager/nm-bluez4-adapter.h similarity index 100% rename from src/bluez-manager/nm-bluez-adapter.h rename to src/bluez-manager/nm-bluez4-adapter.h diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez4-manager.c similarity index 99% rename from src/bluez-manager/nm-bluez-manager.c rename to src/bluez-manager/nm-bluez4-manager.c index 81dfe940ae..882028cd04 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez4-manager.c @@ -27,7 +27,7 @@ #include "nm-logging.h" #include "nm-dbus-glib-types.h" #include "nm-bluez-manager.h" -#include "nm-bluez-adapter.h" +#include "nm-bluez4-adapter.h" #include "nm-dbus-manager.h" #include "nm-bluez-common.h" From 7ff6b9d29b7e63635b14846abee4c9da37b5d08e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Sep 2013 21:09:14 +0200 Subject: [PATCH 23/29] bluez: rename files from nm-bluez5-* to nm-bluez-* Signed-off-by: Thomas Haller --- src/Makefile.am | 2 +- src/bluez-manager/{nm-bluez5-manager.c => nm-bluez-manager.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/bluez-manager/{nm-bluez5-manager.c => nm-bluez-manager.c} (100%) diff --git a/src/Makefile.am b/src/Makefile.am index e391da0edf..7799cbfddd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -271,7 +271,7 @@ nm_sources += \ bluez-manager/nm-bluez4-manager.c else nm_sources += \ - bluez-manager/nm-bluez5-manager.c + bluez-manager/nm-bluez-manager.c endif if WITH_MODEM_MANAGER_1 diff --git a/src/bluez-manager/nm-bluez5-manager.c b/src/bluez-manager/nm-bluez-manager.c similarity index 100% rename from src/bluez-manager/nm-bluez5-manager.c rename to src/bluez-manager/nm-bluez-manager.c From 18624eb6ddc7c278395fda81645bc2f5aba20301 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 23 Sep 2013 15:54:23 -0500 Subject: [PATCH 24/29] bluez: combine bluez4 and bluez5 connect/disconnect code Pretty trivial to combine right now, and use GDBus for everything here. No need to stick with dbus-glib for these operations. --- src/bluez-manager/nm-bluez-device.c | 171 ++++++++++------------------ 1 file changed, 63 insertions(+), 108 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index b827aa3591..1df19c388e 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -45,13 +45,12 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; + GDBusConnection *dbus_connection; #if ! WITH_BLUEZ4 GDBusProxy *proxy5; GDBusProxy *adapter; - GDBusConnection *dbus_connection; #else DBusGProxy *proxy4; - DBusGProxy *connection_proxy; #endif gboolean initialized; @@ -277,9 +276,9 @@ check_emit_usable (NMBluezDevice *self) new_usable = (priv->initialized && priv->capabilities && priv->name && #if ! WITH_BLUEZ4 - priv->adapter && priv->dbus_connection && + priv->adapter && #endif - priv->address); + priv->dbus_connection && priv->address); if (!new_usable) goto END; @@ -398,67 +397,75 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) /***********************************************************/ +static void +bluez_disconnect_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (user_data); + GError *error = NULL; + GVariant *variant; + + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); + if (!variant) { + nm_log_warn (LOGD_BT, "%s: failed to disconnect: %s", priv->address, error->message); + g_error_free (error); + } else + g_variant_unref (variant); +} + void nm_bluez_device_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *args = NULL; + const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; + + g_return_if_fail (priv->dbus_connection); #if ! WITH_BLUEZ4 - g_return_if_fail (priv->dbus_connection); g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); +#else + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); + + if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { + /* Can't pass a NULL interface name through dbus to bluez, so just + * ignore the disconnect if the interface isn't known. + */ + if (!priv->bt_iface) + return; + + args = g_variant_new ("(s)", priv->bt_iface), + dbus_iface = BLUEZ_SERIAL_INTERFACE; + } +#endif g_dbus_connection_call (priv->dbus_connection, BLUEZ_SERVICE, priv->path, - BLUEZ_NETWORK_INTERFACE, + dbus_iface, "Disconnect", - g_variant_new ("()"), + args ? args : g_variant_new ("()"), NULL, G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, NULL, NULL); -#else - g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); + 10000, + NULL, + (GAsyncReadyCallback) bluez_disconnect_cb, + self); - if (!priv->connection_proxy) - return; - - if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { - /* Don't ever pass NULL through dbus; bt_iface - * might happen to be NULL for some reason. - */ - if (priv->bt_iface) - dbus_g_proxy_call_no_reply (priv->connection_proxy, "Disconnect", - G_TYPE_STRING, priv->bt_iface, - G_TYPE_INVALID); - } else { - dbus_g_proxy_call_no_reply (priv->connection_proxy, "Disconnect", - G_TYPE_INVALID); - } - - g_clear_object (&priv->connection_proxy); -#endif priv->connection_bt_type = NM_BT_CAPABILITY_NONE; } static void -#if ! WITH_BLUEZ4 -bluez_connect_pan_cb (GDBusConnection *dbus_connection, - GAsyncResult *res, - gpointer user_data) -#else -bluez_connect_cb (DBusGProxy *proxy4, - DBusGProxyCall *call_id, +bluez_connect_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, gpointer user_data) -#endif { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *error = NULL; char *device; - -#if ! WITH_BLUEZ4 GVariant *variant; variant = g_dbus_connection_call_finish (dbus_connection, res, &error); @@ -474,22 +481,6 @@ bluez_connect_cb (DBusGProxy *proxy4, priv->bt_iface = device; g_variant_unref (variant); } -#else - if (dbus_g_proxy_end_call (proxy4, call_id, &error, - G_TYPE_STRING, &device, - G_TYPE_INVALID) == FALSE) - g_simple_async_result_take_error (result, error); - else if (!device || !strlen (device)) { - g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid argument received"); - g_free (device); - } else { - g_simple_async_result_set_op_res_gpointer (result, - g_strdup (device), - g_free); - priv->bt_iface = device; - } -#endif g_simple_async_result_complete (result); g_object_unref (result); @@ -503,74 +494,40 @@ nm_bluez_device_connect_async (NMBluezDevice *self, { GSimpleAsyncResult *simple; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); -#if WITH_BLUEZ4 - DBusGConnection *connection; - - connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); -#endif + const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; + const char *connect_type = BLUETOOTH_CONNECT_NAP; + g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); #if ! WITH_BLUEZ4 g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); +#else + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); + + if (connection_bt_type == NM_BT_CAPABILITY_DUN) { + dbus_iface = BLUEZ_SERIAL_INTERFACE; + connect_type = BLUETOOTH_CONNECT_DUN; + } +#endif simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, nm_bluez_device_connect_async); - /* For PAN we call Connect() on org.bluez.Network1 */ g_dbus_connection_call (priv->dbus_connection, BLUEZ_SERVICE, priv->path, - BLUEZ_NETWORK_INTERFACE, + dbus_iface, "Connect", - g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), + g_variant_new ("(s)", connect_type), NULL, G_DBUS_CALL_FLAGS_NONE, 20000, NULL, - (GAsyncReadyCallback) bluez_connect_pan_cb, + (GAsyncReadyCallback) bluez_connect_cb, simple); priv->connection_bt_type = connection_bt_type; -#else - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); - - if (priv->connection_proxy) { - g_simple_async_report_error_in_idle (G_OBJECT (self), - callback, - user_data, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Already connected to bluez service"); - return; - } - priv->connection_proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); - if (!priv->connection_proxy) { - g_simple_async_report_error_in_idle (G_OBJECT (self), - callback, - user_data, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unable to create proxy"); - } else { - simple = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - nm_bluez_device_connect_async); - dbus_g_proxy_begin_call_with_timeout (priv->connection_proxy, "Connect", - bluez_connect_cb, - simple, - NULL, - 20000, - G_TYPE_STRING, - connection_bt_type == NM_BT_CAPABILITY_DUN ? BLUETOOTH_CONNECT_DUN : BLUETOOTH_CONNECT_NAP, - G_TYPE_INVALID); - priv->connection_bt_type = connection_bt_type; - } -#endif } const char * @@ -913,6 +870,7 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) } g_object_unref (self); } +#endif static void on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) @@ -931,7 +889,6 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) check_emit_usable (self); } -#endif /********************************************************************/ @@ -977,12 +934,12 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) G_CALLBACK (cp_connections_loaded), self); -#if ! WITH_BLUEZ4 g_bus_get (G_BUS_TYPE_SYSTEM, NULL, (GAsyncReadyCallback) on_bus_acquired, self); +#if ! WITH_BLUEZ4 g_object_ref (self); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, @@ -1037,10 +994,8 @@ dispose (GObject *object) #if ! WITH_BLUEZ4 g_clear_object (&priv->adapter); - g_clear_object (&priv->dbus_connection); -#else - g_clear_object (&priv->connection_proxy); #endif + g_clear_object (&priv->dbus_connection); G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } From 961e23a2e2502a64dc0adfd234e670690be2cc5d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 23 Sep 2013 16:12:00 -0500 Subject: [PATCH 25/29] build: show bluez4 as "no" when not explicitly enabled --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 424c904f6b..136c1d047b 100644 --- a/configure.ac +++ b/configure.ac @@ -275,6 +275,7 @@ if (test "${enable_bluez4}" = "yes"); then AC_DEFINE(WITH_BLUEZ4, 1, [Define if you have BlueZ 4 support]) else AC_DEFINE(WITH_BLUEZ4, 0, [Define if you have BlueZ 4 support]) + enable_bluez4=no fi AM_CONDITIONAL(WITH_BLUEZ4, test "${enable_bluez4}" = "yes") From 050cf2dbaeaaec40a7bd79cc1bcd6c838eefca96 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 23 Sep 2013 16:33:44 -0500 Subject: [PATCH 26/29] bluez: check bluez5 adapter powered state and remove devices if killed --- src/bluez-manager/nm-bluez-device.c | 54 +++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 1df19c388e..2912c28dd6 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -49,6 +49,7 @@ typedef struct { #if ! WITH_BLUEZ4 GDBusProxy *proxy5; GDBusProxy *adapter; + gboolean adapter_powered; #else DBusGProxy *proxy4; #endif @@ -276,7 +277,7 @@ check_emit_usable (NMBluezDevice *self) new_usable = (priv->initialized && priv->capabilities && priv->name && #if ! WITH_BLUEZ4 - priv->adapter && + priv->adapter && priv->adapter_powered && #endif priv->dbus_connection && priv->address); @@ -609,19 +610,58 @@ _set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean no } #if ! WITH_BLUEZ4 +static void +adapter_properties_changed (GDBusProxy *proxy5, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariantIter i; + const char *property; + GVariant *v; + + g_variant_iter_init (&i, changed_properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!strcmp (property, "Powered")) { + gboolean powered = g_variant_get_boolean (v); + if (priv->adapter_powered != powered) + priv->adapter_powered = powered; + } + g_variant_unref (v); + } + + check_emit_usable (self); +} + static void on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *error; + GVariant *v; priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!priv->adapter) { nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); g_clear_error (&error); - } else + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + } else { + g_signal_connect (priv->adapter, "g-properties-changed", + G_CALLBACK (adapter_properties_changed), self); + + /* Check adapter's powered state */ + v = g_dbus_proxy_get_cached_property (priv->adapter, "Powered"); + priv->adapter_powered = v ? g_variant_get_boolean (v) : FALSE; + if (v) + g_variant_unref (v); + + priv->initialized = TRUE; + g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + check_emit_usable (self); + } g_object_unref (self); } @@ -758,7 +798,6 @@ query_properties (NMBluezDevice *self) v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); if (v) { - g_object_ref (self); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, @@ -767,17 +806,12 @@ query_properties (NMBluezDevice *self) BLUEZ_ADAPTER_INTERFACE, NULL, (GAsyncReadyCallback) on_adapter_acquired, - self); + g_object_ref (self)); g_variant_unref (v); } /* Check if any connections match this device */ cp_connections_loaded (priv->provider, self); - - priv->initialized = TRUE; - g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - - check_emit_usable (self); } #else static void From 07cc990981de901438efd09f3c34835a5531f606 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Sep 2013 20:04:24 +0200 Subject: [PATCH 27/29] bluez: ensure that address of NMBluezDevice cannot be reset Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-device.c | 57 ++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index 2912c28dd6..3beb06547f 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -320,6 +320,10 @@ connection_compatible (NMBluezDevice *self, NMConnection *connection) if (!s_bt) return FALSE; + if (!priv->address) { + /* unless address is set, bin_address is not initialized. */ + return FALSE; + } bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); if (!bdaddr || bdaddr->len != ETH_ALEN) return FALSE; @@ -609,6 +613,44 @@ _set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean no } } +/** + * priv->address can only be set one to a certain (non NULL) value. Every later attempt + * to reset it to another value will be ignored and a warning will be logged. + * + * When setting the address for the first time, we also set bin_address. + **/ +static void +_set_property_address (NMBluezDevice *self, const char *addr) +{ + struct ether_addr *tmp; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (g_strcmp0 (priv->address, addr) == 0) + return; + + if (!addr) { + nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); + return; + } + + if (priv->address != NULL) { + nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); + return; + } + + tmp = ether_aton (addr); + if (!tmp) { + if (priv->address) + nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s' (invalid value)", priv->path, priv->address, addr); + else + nm_log_warn (LOGD_BT, "[%s] cannot reset address from NULL to '%s' (invalid value)", priv->path, addr); + return; + } + memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); + priv->address = g_strdup (addr); + return; +} + #if ! WITH_BLUEZ4 static void adapter_properties_changed (GDBusProxy *proxy5, @@ -766,17 +808,11 @@ query_properties (NMBluezDevice *self) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GVariant *v; const char **uuids; - struct ether_addr *tmp; v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); - priv->address = v ? g_variant_dup_string (v, NULL) : NULL; + _set_property_address (self, v ? g_variant_get_string (v, NULL) : NULL); if (v) g_variant_unref (v); - if (priv->address) { - tmp = ether_aton (priv->address); - g_assert (tmp); - memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); - } v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); priv->name = v ? g_variant_dup_string (v, NULL) : NULL; @@ -835,12 +871,7 @@ get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) } value = g_hash_table_lookup (properties, "Address"); - priv->address = value ? g_value_dup_string (value) : NULL; - if (priv->address) { - tmp = ether_aton (priv->address); - g_assert (tmp); - memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); - } + _set_property_address (self, value ? g_value_get_string (value) : NULL); value = g_hash_table_lookup (properties, "Name"); priv->name = value ? g_value_dup_string (value) : NULL; From ef472259cf02f4d644767d0b270a7978cff917a1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 25 Sep 2013 21:54:55 +0200 Subject: [PATCH 28/29] bluez: fix emitting of REMOVED signal in manager Ensure, before emitting the REMOVED signal for devices, that the device was usable before. Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-manager.c | 29 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c index 0542be87c0..e24d8600a3 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-manager.c @@ -56,6 +56,9 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +static void device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self); +static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self); + static void emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) { @@ -81,6 +84,18 @@ nm_bluez_manager_query_devices (NMBluezManager *self) } } +static void +remove_device (NMBluezManager *self, NMBluezDevice *device) +{ + if (nm_bluez_device_get_usable (device)) { + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + } + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); +} + static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self) { @@ -139,11 +154,7 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) if (device) { g_object_ref (device); g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); - - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); - + remove_device (NM_BLUEZ_MANAGER (self), device); g_object_unref (device); } } @@ -284,9 +295,7 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, g_hash_table_iter_init (&iter, priv->devices); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); + remove_device (self, device); g_hash_table_remove_all (priv->devices); } } @@ -307,9 +316,7 @@ bluez_cleanup (NMBluezManager *self, gboolean do_signal) if (do_signal) { g_hash_table_iter_init (&iter, priv->devices); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); + remove_device (self, device); } g_hash_table_remove_all (priv->devices); From e0e10a06b2637beb23c439630f8ec336b9760b93 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Sep 2013 22:07:36 +0200 Subject: [PATCH 29/29] bluez: remove the device from manager before emitting REMOVED signal As we iterate through the list of devices that are about to removed, they should be removed before emitting the signal. Signed-off-by: Thomas Haller --- src/bluez-manager/nm-bluez-manager.c | 42 +++++++++++++++------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c index e24d8600a3..3801d5ee37 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-manager.c @@ -96,6 +96,21 @@ remove_device (NMBluezManager *self, NMBluezDevice *device) g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); } +static void +remove_all_devices (NMBluezManager *self) +{ + GHashTableIter iter; + NMBluezDevice *device; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + g_hash_table_iter_steal (&iter); + remove_device (self, device); + g_object_unref (device); + } +} + static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self) { @@ -152,8 +167,7 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) device = g_hash_table_lookup (priv->devices, path); if (device) { - g_object_ref (device); - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); + g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); remove_device (NM_BLUEZ_MANAGER (self), device); g_object_unref (device); } @@ -289,15 +303,8 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, return; if (old_owner_good && !new_owner_good) { - if (priv->devices) { - GHashTableIter iter; - NMBluezDevice *device; - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) - remove_device (self, device); - g_hash_table_remove_all (priv->devices); - } + if (priv->devices) + remove_all_devices (self); } } @@ -305,21 +312,16 @@ static void bluez_cleanup (NMBluezManager *self, gboolean do_signal) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - GHashTableIter iter; if (priv->proxy) { g_object_unref (priv->proxy); priv->proxy = NULL; } - if (do_signal) { - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) - remove_device (self, device); - } - - g_hash_table_remove_all (priv->devices); + if (do_signal) + remove_all_devices (self); + else + g_hash_table_remove_all (priv->devices); } static void