diff options
Diffstat (limited to 'src/devices/bluetooth')
| -rw-r--r-- | src/devices/bluetooth/nm-bluez-common.h | 26 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez-device.c | 58 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez-device.h | 3 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez-manager.c | 37 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez4-adapter.c | 131 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez4-adapter.h | 6 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez4-manager.c | 154 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez5-dun.c | 4 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-bluez5-manager.c | 299 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-device-bt.c | 96 | ||||
| -rw-r--r-- | src/devices/bluetooth/nm-device-bt.h | 6 |
11 files changed, 591 insertions, 229 deletions
diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/devices/bluetooth/nm-bluez-common.h index 6e97c3f5..d72bea81 100644 --- a/src/devices/bluetooth/nm-bluez-common.h +++ b/src/devices/bluetooth/nm-bluez-common.h @@ -15,7 +15,7 @@ * 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 Red Hat, Inc. + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_BLUEZ_COMMON_H__ @@ -24,21 +24,23 @@ #define BLUETOOTH_CONNECT_DUN "dun" #define BLUETOOTH_CONNECT_NAP "nap" -#define BLUEZ_SERVICE "org.bluez" +#define NM_BLUEZ_SERVICE "org.bluez" -#define BLUEZ_MANAGER_PATH "/" -#define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" +#define NM_BLUEZ_MANAGER_PATH "/" +#define NM_OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" -#define BLUEZ5_ADAPTER_INTERFACE "org.bluez.Adapter1" -#define BLUEZ5_DEVICE_INTERFACE "org.bluez.Device1" -#define BLUEZ5_NETWORK_INTERFACE "org.bluez.Network1" +#define NM_BLUEZ5_ADAPTER_INTERFACE "org.bluez.Adapter1" +#define NM_BLUEZ5_DEVICE_INTERFACE "org.bluez.Device1" +#define NM_BLUEZ5_NETWORK_INTERFACE "org.bluez.Network1" +#define NM_BLUEZ5_NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1" -#define BLUEZ4_MANAGER_INTERFACE "org.bluez.Manager" -#define BLUEZ4_ADAPTER_INTERFACE "org.bluez.Adapter" -#define BLUEZ4_DEVICE_INTERFACE "org.bluez.Device" -#define BLUEZ4_SERIAL_INTERFACE "org.bluez.Serial" -#define BLUEZ4_NETWORK_INTERFACE "org.bluez.Network" +#define NM_BLUEZ4_MANAGER_INTERFACE "org.bluez.Manager" +#define NM_BLUEZ4_ADAPTER_INTERFACE "org.bluez.Adapter" +#define NM_BLUEZ4_DEVICE_INTERFACE "org.bluez.Device" +#define NM_BLUEZ4_SERIAL_INTERFACE "org.bluez.Serial" +#define NM_BLUEZ4_NETWORK_INTERFACE "org.bluez.Network" #define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" +#define NM_BLUEZ_MANAGER_NETWORK_SERVER_ADDED "network-server-added" #endif /* NM_BLUEZ_COMMON_H */ diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 41ef74ca..182527d9 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -84,6 +84,7 @@ typedef struct { char *name; guint32 capabilities; gboolean connected; + gboolean paired; char *b4_iface; #if WITH_BLUEZ5_DUN @@ -278,10 +279,11 @@ check_emit_usable (NMBluezDevice *self) /* only expect the supported capabilities set. */ nm_assert ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE ); - new_usable = (priv->initialized && priv->capabilities && priv->name && - ((priv->bluez_version == 4) || - (priv->bluez_version == 5 && priv->adapter5 && priv->adapter_powered) ) && - priv->dbus_connection && priv->address && priv->adapter_address); + new_usable = ( priv->initialized && priv->capabilities + && priv->name && priv->paired + && ( (priv->bluez_version == 4) + || (priv->bluez_version == 5 && priv->adapter5 && priv->adapter_powered)) + && priv->dbus_connection && priv->address && priv->adapter_address); if (!new_usable) goto END; @@ -343,6 +345,10 @@ connection_compatible (NMBluezDevice *self, NMConnection *connection) return FALSE; bt_type = nm_setting_bluetooth_get_connection_type (s_bt); + + if (nm_streq (bt_type, NM_SETTING_BLUETOOTH_TYPE_NAP)) + return FALSE; + if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) return FALSE; @@ -465,7 +471,7 @@ nm_bluez_device_disconnect (NMBluezDevice *self) if (!priv->b4_iface) goto out; args = g_variant_new ("(s)", priv->b4_iface), - dbus_iface = BLUEZ4_SERIAL_INTERFACE; + dbus_iface = NM_BLUEZ4_SERIAL_INTERFACE; } else if (priv->bluez_version == 5) { #if WITH_BLUEZ5_DUN nm_bluez5_dun_cleanup (priv->b5_dun_context); @@ -475,16 +481,16 @@ nm_bluez_device_disconnect (NMBluezDevice *self) } } else if (priv->connection_bt_type == NM_BT_CAPABILITY_NAP) { if (priv->bluez_version == 4) - dbus_iface = BLUEZ4_NETWORK_INTERFACE; + dbus_iface = NM_BLUEZ4_NETWORK_INTERFACE; else if (priv->bluez_version == 5) - dbus_iface = BLUEZ5_NETWORK_INTERFACE; + dbus_iface = NM_BLUEZ5_NETWORK_INTERFACE; else g_assert_not_reached (); } else g_assert_not_reached (); g_dbus_connection_call (priv->dbus_connection, - BLUEZ_SERVICE, + NM_BLUEZ_SERVICE, priv->path, dbus_iface, "Disconnect", @@ -577,13 +583,13 @@ nm_bluez_device_connect_async (NMBluezDevice *self, if (connection_bt_type == NM_BT_CAPABILITY_NAP) { connect_type = BLUETOOTH_CONNECT_NAP; if (priv->bluez_version == 4) - dbus_iface = BLUEZ4_NETWORK_INTERFACE; + dbus_iface = NM_BLUEZ4_NETWORK_INTERFACE; else if (priv->bluez_version == 5) - dbus_iface = BLUEZ5_NETWORK_INTERFACE; + dbus_iface = NM_BLUEZ5_NETWORK_INTERFACE; } else if (connection_bt_type == NM_BT_CAPABILITY_DUN) { connect_type = BLUETOOTH_CONNECT_DUN; if (priv->bluez_version == 4) - dbus_iface = BLUEZ4_SERIAL_INTERFACE; + dbus_iface = NM_BLUEZ4_SERIAL_INTERFACE; else if (priv->bluez_version == 5) { #if WITH_BLUEZ5_DUN if (priv->b5_dun_context == NULL) @@ -602,7 +608,7 @@ nm_bluez_device_connect_async (NMBluezDevice *self, g_assert_not_reached (); g_dbus_connection_call (priv->dbus_connection, - BLUEZ_SERVICE, + NM_BLUEZ_SERVICE, priv->path, dbus_iface, "Connect", @@ -795,6 +801,17 @@ _take_variant_property_connected (NMBluezDevice *self, GVariant *v) g_variant_unref (v); } +static void +_take_variant_property_paired (NMBluezDevice *self, GVariant *v) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (VARIANT_IS_OF_TYPE_BOOLEAN (v)) + priv->paired = g_variant_get_boolean (v); + + if (v) + g_variant_unref (v); +} static void adapter5_on_properties_changed (GDBusProxy *proxy, @@ -864,6 +881,8 @@ _take_one_variant_property (NMBluezDevice *self, const char *property, GVariant _take_variant_property_address (self, v); else if (!g_strcmp0 (property, "Connected")) _take_variant_property_connected (self, v); + else if (!g_strcmp0 (property, "Paired")) + _take_variant_property_paired (self, v); else if (!g_strcmp0 (property, "Name")) _take_variant_property_name (self, v); else if (!g_strcmp0 (property, "UUIDs")) @@ -963,6 +982,7 @@ query_properties (NMBluezDevice *self) g_object_freeze_notify (G_OBJECT (self)); _take_variant_property_address (self, g_dbus_proxy_get_cached_property (priv->proxy, "Address")); _take_variant_property_connected (self, g_dbus_proxy_get_cached_property (priv->proxy, "Connected")); + _take_variant_property_paired (self, g_dbus_proxy_get_cached_property (priv->proxy, "Paired")); _take_variant_property_name (self, g_dbus_proxy_get_cached_property (priv->proxy, "Name")); _take_variant_property_uuids (self, g_dbus_proxy_get_cached_property (priv->proxy, "UUIDs")); g_object_thaw_notify (G_OBJECT (self)); @@ -972,9 +992,9 @@ query_properties (NMBluezDevice *self) g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, - BLUEZ_SERVICE, + NM_BLUEZ_SERVICE, g_variant_get_string (v, NULL), - BLUEZ5_ADAPTER_INTERFACE, + NM_BLUEZ5_ADAPTER_INTERFACE, NULL, (GAsyncReadyCallback) adapter5_on_acquired, g_object_ref (self)); @@ -1134,17 +1154,17 @@ nm_bluez_device_new (const char *path, switch (priv->bluez_version) { case 4: - interface_name = BLUEZ4_DEVICE_INTERFACE; + interface_name = NM_BLUEZ4_DEVICE_INTERFACE; break; case 5: - interface_name = BLUEZ5_DEVICE_INTERFACE; + interface_name = NM_BLUEZ5_DEVICE_INTERFACE; break; } g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, - BLUEZ_SERVICE, + NM_BLUEZ_SERVICE, priv->path, interface_name, NULL, @@ -1199,7 +1219,7 @@ dispose (GObject *object) if (to_delete) { nm_log_dbg (LOGD_BT, "bluez[%s] removing Bluetooth connection for NAP device: '%s' (%s)", priv->path, nm_connection_get_id (to_delete), nm_connection_get_uuid (to_delete)); - nm_settings_connection_delete (NM_SETTINGS_CONNECTION (to_delete), NULL, NULL); + nm_settings_connection_delete (NM_SETTINGS_CONNECTION (to_delete), NULL); g_object_unref (to_delete); } @@ -1274,7 +1294,7 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - signals[INITIALIZED] = g_signal_new ("initialized", + signals[INITIALIZED] = g_signal_new (NM_BLUEZ_DEVICE_INITIALIZED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h index e56d5d24..f8a1872f 100644 --- a/src/devices/bluetooth/nm-bluez-device.h +++ b/src/devices/bluetooth/nm-bluez-device.h @@ -39,6 +39,7 @@ #define NM_BLUEZ_DEVICE_CONNECTED "connected" /* Signals */ +#define NM_BLUEZ_DEVICE_INITIALIZED "initialized" #define NM_BLUEZ_DEVICE_REMOVED "removed" typedef struct _NMBluezDevice NMBluezDevice; @@ -61,8 +62,6 @@ const char *nm_bluez_device_get_address (NMBluezDevice *self); const char *nm_bluez_device_get_name (NMBluezDevice *self); -guint32 nm_bluez_device_get_class (NMBluezDevice *self); - guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); gboolean nm_bluez_device_get_connected (NMBluezDevice *self); diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index 2f0afa16..96e80245 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -26,6 +26,7 @@ #include <gmodule.h> #include "devices/nm-device-factory.h" +#include "devices/nm-device-bridge.h" #include "nm-setting-bluetooth.h" #include "settings/nm-settings.h" #include "nm-bluez4-manager.h" @@ -146,7 +147,7 @@ cleanup_checking (NMBluezManager *self, gboolean do_unwatch_name) static void -manager_bdaddr_added_cb (NMBluez4Manager *bluez_mgr, +manager_bdaddr_added_cb (GObject *manager, NMBluezDevice *bt_device, const char *bdaddr, const char *name, @@ -180,6 +181,13 @@ manager_bdaddr_added_cb (NMBluez4Manager *bluez_mgr, } static void +manager_network_server_added_cb (GObject *manager, + gpointer user_data) +{ + nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (user_data), NULL); +} + +static void setup_version_number (NMBluezManager *self, int bluez_version) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); @@ -228,6 +236,10 @@ setup_bluez5 (NMBluezManager *self) NM_BLUEZ_MANAGER_BDADDR_ADDED, G_CALLBACK (manager_bdaddr_added_cb), self); + g_signal_connect (manager, + NM_BLUEZ_MANAGER_NETWORK_SERVER_ADDED, + G_CALLBACK (manager_network_server_added_cb), + self); nm_bluez5_manager_query_devices (manager); } @@ -264,7 +276,7 @@ check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, c cleanup_checking (self, FALSE); if (!priv->watch_name_id) { priv->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, - BLUEZ_SERVICE, + NM_BLUEZ_SERVICE, G_BUS_NAME_WATCHER_FLAGS_NONE, watch_name_on_appeared, NULL, @@ -317,7 +329,7 @@ check_bluez_and_try_setup_do_introspect (GObject *source_object, /* might not be the best approach to detect the version, but it's good enough in practice. */ if (strstr (xml_data, "org.freedesktop.DBus.ObjectManager")) bluez_version = 5; - else if (strstr (xml_data, BLUEZ4_MANAGER_INTERFACE)) + else if (strstr (xml_data, NM_BLUEZ4_MANAGER_INTERFACE)) bluez_version = 4; else reason = "unexpected introspect result"; @@ -380,7 +392,7 @@ check_bluez_and_try_setup (NMBluezManager *self) g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, - BLUEZ_SERVICE, + NM_BLUEZ_SERVICE, "/", DBUS_INTERFACE_INTROSPECTABLE, priv->async_cancellable, @@ -406,6 +418,20 @@ create_device (NMDeviceFactory *factory, return NULL; } +static gboolean +match_connection (NMDeviceFactory *factory, + NMConnection *connection) +{ + const char *type = nm_connection_get_connection_type (connection); + + nm_assert (nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME)); + + if (_nm_connection_get_setting_bluetooth_for_nap (connection)) + return FALSE; /* handled by the bridge factory */ + + return TRUE; +} + /*****************************************************************************/ static void @@ -427,7 +453,7 @@ dispose (GObject *object) g_clear_object (&priv->manager4); } if (priv->manager5) { - g_signal_handlers_disconnect_by_func (priv->manager5, manager_bdaddr_added_cb, self); + g_signal_handlers_disconnect_by_data (priv->manager5, self); g_clear_object (&priv->manager5); } @@ -450,5 +476,6 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) factory_class->get_supported_types = get_supported_types; factory_class->create_device = create_device; + factory_class->match_connection = match_connection; factory_class->start = start; } diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index c0c1be30..0f19f998 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -25,6 +25,7 @@ #include <string.h> #include "nm-dbus-interface.h" +#include "nm-utils/nm-hash-utils.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-core-internal.h" @@ -49,6 +50,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { char *path; GDBusProxy *proxy; + GCancellable *proxy_cancellable; gboolean initialized; char *address; @@ -73,6 +75,11 @@ G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) /*****************************************************************************/ +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-adapter", __VA_ARGS__) + +/*****************************************************************************/ + static void device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device); /*****************************************************************************/ @@ -119,8 +126,8 @@ nm_bluez4_adapter_get_devices (NMBluez4Adapter *self) static void emit_device_removed (NMBluez4Adapter *self, NMBluezDevice *device) { - nm_log_dbg (LOGD_BT, "(%s): bluez device now unusable", - nm_bluez_device_get_path (device)); + _LOGD ("(%s): bluez device now unusable", + nm_bluez_device_get_path (device)); g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); } @@ -130,9 +137,9 @@ device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); if (nm_bluez_device_get_usable (device)) { - nm_log_dbg (LOGD_BT, "(%s): bluez device now usable (device address is %s)", - nm_bluez_device_get_path (device), - nm_bluez_device_get_address (device)); + _LOGD ("(%s): bluez device now usable (device address is %s)", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); } else emit_device_removed (self, device); @@ -143,9 +150,9 @@ device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - nm_log_dbg (LOGD_BT, "(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); + _LOGD ("(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); if (!success) device_do_remove (self, device); } @@ -174,11 +181,11 @@ device_created (GDBusProxy *proxy, const char *path, gpointer user_data) NMBluezDevice *device; device = nm_bluez_device_new (path, priv->address, priv->settings, 4); - g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_signal_connect (device, NM_BLUEZ_DEVICE_INITIALIZED, G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::" NM_BLUEZ_DEVICE_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); + _LOGD ("(%s): new bluez device found", path); } static void @@ -188,7 +195,7 @@ device_removed (GDBusProxy *proxy, const char *path, gpointer user_data) NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; - nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + _LOGD ("(%s): bluez device removed", path); device = g_hash_table_lookup (priv->devices, path); if (device) @@ -198,19 +205,28 @@ device_removed (GDBusProxy *proxy, const char *path, gpointer user_data) static void get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - GError *err = NULL; + NMBluez4Adapter *self; + NMBluez4AdapterPrivate *priv; + gs_free_error GError *error = NULL; GVariant *ret, *properties; char **devices; int i; ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, - G_VARIANT_TYPE ("(a{sv})"), &err); + G_VARIANT_TYPE ("(a{sv})"), &error); + + if ( !ret + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = NM_BLUEZ4_ADAPTER (user_data); + priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + + g_clear_object (&priv->proxy_cancellable); + if (!ret) { - g_dbus_error_strip_remote_error (err); - nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", err->message); - g_error_free (err); + g_dbus_error_strip_remote_error (error); + _LOGW ("bluez error getting adapter properties: %s", error->message); goto done; } @@ -233,15 +249,43 @@ done: } static void -query_properties (NMBluez4Adapter *self) +_proxy_new_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + NMBluez4Adapter *self; + NMBluez4AdapterPrivate *priv; + gs_free_error GError *error = NULL; + GDBusProxy *proxy; + + proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if ( !proxy + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = user_data; + priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + + if (!proxy) { + _LOGW ("bluez error creating D-Bus proxy: %s", error->message); + g_clear_object (&priv->proxy_cancellable); + g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized); + return; + } + + priv->proxy = proxy; + + _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (device_created), self); + _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (device_removed), self); g_dbus_proxy_call (priv->proxy, "GetProperties", NULL, G_DBUS_CALL_FLAGS_NONE, -1, - NULL, - get_properties_cb, self); + priv->proxy_cancellable, + get_properties_cb, + self); } /*****************************************************************************/ @@ -297,7 +341,7 @@ nm_bluez4_adapter_init (NMBluez4Adapter *self) { NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + priv->devices = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, NULL); } @@ -316,19 +360,17 @@ nm_bluez4_adapter_new (const char *path, NMSettings *settings) priv->settings = g_object_ref (settings); - priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - BLUEZ_SERVICE, - priv->path, - BLUEZ4_ADAPTER_INTERFACE, - NULL, NULL); - _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (device_created), self); - _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (device_removed), self); + priv->proxy_cancellable = g_cancellable_new (); - query_properties (self); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_BLUEZ_SERVICE, + priv->path, + NM_BLUEZ4_ADAPTER_INTERFACE, + priv->proxy_cancellable, + _proxy_new_cb, + self); return self; } @@ -339,21 +381,28 @@ dispose (GObject *object) NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; + nm_clear_g_cancellable (&priv->proxy_cancellable); + while ((device = g_hash_table_find (priv->devices, _find_all, NULL))) device_do_remove (self, device); + if (priv->proxy) { + g_signal_handlers_disconnect_by_data (priv->proxy, self); + g_clear_object (&priv->proxy); + } + G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->dispose (object); } static void finalize (GObject *object) { - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE ((NMBluez4Adapter *) object); + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); g_hash_table_destroy (priv->devices); g_free (priv->address); g_free (priv->path); - g_object_unref (priv->proxy); G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object); @@ -384,7 +433,7 @@ nm_bluez4_adapter_class_init (NMBluez4AdapterClass *config_class) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - signals[INITIALIZED] = g_signal_new ("initialized", + signals[INITIALIZED] = g_signal_new (NM_BLUEZ4_ADAPTER_INITIALIZED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, @@ -392,7 +441,7 @@ nm_bluez4_adapter_class_init (NMBluez4AdapterClass *config_class) g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - signals[DEVICE_ADDED] = g_signal_new ("device-added", + signals[DEVICE_ADDED] = g_signal_new (NM_BLUEZ4_ADAPTER_DEVICE_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, @@ -400,7 +449,7 @@ nm_bluez4_adapter_class_init (NMBluez4AdapterClass *config_class) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); - signals[DEVICE_REMOVED] = g_signal_new ("device-removed", + signals[DEVICE_REMOVED] = g_signal_new (NM_BLUEZ4_ADAPTER_DEVICE_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, diff --git a/src/devices/bluetooth/nm-bluez4-adapter.h b/src/devices/bluetooth/nm-bluez4-adapter.h index e240ec2c..0aa4ff91 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.h +++ b/src/devices/bluetooth/nm-bluez4-adapter.h @@ -30,9 +30,15 @@ #define NM_IS_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_ADAPTER)) #define NM_BLUEZ4_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) +/* Properties */ #define NM_BLUEZ4_ADAPTER_PATH "path" #define NM_BLUEZ4_ADAPTER_ADDRESS "address" +/* Signals */ +#define NM_BLUEZ4_ADAPTER_INITIALIZED "initialized" +#define NM_BLUEZ4_ADAPTER_DEVICE_ADDED "device-added" +#define NM_BLUEZ4_ADAPTER_DEVICE_REMOVED "device-removed" + typedef struct _NMBluez4Adapter NMBluez4Adapter; typedef struct _NMBluez4AdapterClass NMBluez4AdapterClass; diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c index a9079a2f..1fe02f18 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -47,6 +47,7 @@ typedef struct { NMSettings *settings; GDBusProxy *proxy; + GCancellable *proxy_cancellable; NMBluez4Adapter *adapter; } NMBluez4ManagerPrivate; @@ -66,6 +67,11 @@ G_DEFINE_TYPE (NMBluez4Manager, nm_bluez4_manager, G_TYPE_OBJECT) /*****************************************************************************/ +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-manager", __VA_ARGS__) + +/*****************************************************************************/ + static void emit_bdaddr_added (NMBluez4Manager *self, NMBluezDevice *device) { @@ -119,8 +125,10 @@ adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_d emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); g_slist_free (devices); - g_signal_connect (adapter, "device-added", G_CALLBACK (device_added), self); - g_signal_connect (adapter, "device-removed", G_CALLBACK (device_removed), self); + g_signal_connect (adapter, NM_BLUEZ4_ADAPTER_DEVICE_ADDED, + G_CALLBACK (device_added), self); + g_signal_connect (adapter, NM_BLUEZ4_ADAPTER_DEVICE_REMOVED, + G_CALLBACK (device_removed), self); } else { g_object_unref (priv->adapter); priv->adapter = NULL; @@ -169,49 +177,70 @@ default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *s /* Add the new default adapter */ if (path) { priv->adapter = nm_bluez4_adapter_new (path, priv->settings); - g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); + g_signal_connect (priv->adapter, NM_BLUEZ4_ADAPTER_INITIALIZED, + G_CALLBACK (adapter_initialized), self); } } static void default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { - NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - GVariant *ret; - GError *err = NULL; + NMBluez4Manager *self; + NMBluez4ManagerPrivate *priv; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + const char *default_adapter; ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, - G_VARIANT_TYPE ("(o)"), &err); - if (ret) { - const char *default_adapter; + G_VARIANT_TYPE ("(o)"), &error); + if ( !ret + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; - g_variant_get (ret, "(&o)", &default_adapter); - default_adapter_changed (priv->proxy, default_adapter, self); - g_variant_unref (ret); - } else { + self = NM_BLUEZ4_MANAGER (user_data); + priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + g_clear_object (&priv->proxy_cancellable); + + if (!ret) { /* Ignore "No such adapter" errors; just means bluetooth isn't active */ - if ( !_nm_dbus_error_has_name (err, "org.bluez.Error.NoSuchAdapter") - && !_nm_dbus_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") - && !g_error_matches (err, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { - g_dbus_error_strip_remote_error (err); - nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", - err->message); + if ( !_nm_dbus_error_has_name (error, "org.bluez.Error.NoSuchAdapter") + && !_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed") + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { + g_dbus_error_strip_remote_error (error); + _LOGW ("bluez error getting default adapter: %s", + error->message); } - g_error_free (err); + return; } + + g_variant_get (ret, "(&o)", &default_adapter); + default_adapter_changed (priv->proxy, default_adapter, self); } static void -query_default_adapter (NMBluez4Manager *self) +name_owner_changed (NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + gs_free char *owner = NULL; + + nm_clear_g_cancellable (&priv->proxy_cancellable); + + owner = g_dbus_proxy_get_name_owner (priv->proxy); + if (!owner) { + /* Throwing away the adapter removes all devices too */ + g_clear_object (&priv->adapter); + return; + } + + priv->proxy_cancellable = g_cancellable_new (); g_dbus_proxy_call (priv->proxy, "DefaultAdapter", NULL, G_DBUS_CALL_FLAGS_NONE, -1, - NULL, - default_adapter_cb, self); + priv->proxy_cancellable, + default_adapter_cb, + self); } static void @@ -219,34 +248,35 @@ name_owner_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data) { - NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - char *owner; - - owner = g_dbus_proxy_get_name_owner (priv->proxy); - if (owner) { - query_default_adapter (self); - g_free (owner); - } else { - /* Throwing away the adapter removes all devices too */ - g_clear_object (&priv->adapter); - } + name_owner_changed (user_data); } -/*****************************************************************************/ - static void -nm_bluez4_manager_init (NMBluez4Manager *self) +_proxy_new_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + NMBluez4Manager *self; + NMBluez4ManagerPrivate *priv; + gs_free_error GError *error = NULL; + GDBusProxy *proxy; + + proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if ( !proxy + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = user_data; + priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + if (!proxy) { + _LOGW ("bluez error creating D-Bus proxy: %s", error->message); + g_clear_object (&priv->proxy_cancellable); + return; + } + + priv->proxy = proxy; - priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - BLUEZ4_MANAGER_INTERFACE, - NULL, NULL); _nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"), G_CALLBACK (adapter_removed), self); _nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"), @@ -254,7 +284,27 @@ nm_bluez4_manager_init (NMBluez4Manager *self) g_signal_connect (priv->proxy, "notify::g-name-owner", G_CALLBACK (name_owner_changed_cb), self); - query_default_adapter (self); + name_owner_changed (self); +} + +/*****************************************************************************/ + +static void +nm_bluez4_manager_init (NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + priv->proxy_cancellable = g_cancellable_new (); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_BLUEZ_SERVICE, + NM_BLUEZ_MANAGER_PATH, + NM_BLUEZ4_MANAGER_INTERFACE, + priv->proxy_cancellable, + _proxy_new_cb, + self); } NMBluez4Manager * @@ -275,7 +325,13 @@ dispose (GObject *object) NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - g_clear_object (&priv->proxy); + nm_clear_g_cancellable (&priv->proxy_cancellable); + + if (priv->proxy) { + g_signal_handlers_disconnect_by_data (priv->proxy, self); + g_clear_object (&priv->proxy); + } + g_clear_object (&priv->adapter); G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c index aba3a0dd..ca09b276 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.c +++ b/src/devices/bluetooth/nm-bluez5-dun.c @@ -386,11 +386,11 @@ nm_bluez5_dun_cleanup (NMBluez5DunContext *context) ioctl (context->rfcomm_fd, RFCOMMRELEASEDEV, &req); context->rfcomm_id = -1; } - close (context->rfcomm_fd); + nm_close (context->rfcomm_fd); context->rfcomm_fd = -1; } - close (context->rfcomm_tty_fd); + nm_close (context->rfcomm_tty_fd); context->rfcomm_tty_fd = -1; } diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index 88759301..8c93f2a5 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2017 Red Hat, Inc. * Copyright (C) 2013 Intel Corporation. */ @@ -30,14 +30,17 @@ #include "nm-core-internal.h" +#include "nm-utils/c-list.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" +#include "devices/nm-device-bridge.h" #include "settings/nm-settings.h" /*****************************************************************************/ enum { BDADDR_ADDED, + NETWORK_SERVER_ADDED, LAST_SIGNAL, }; @@ -49,10 +52,13 @@ typedef struct { GDBusProxy *proxy; GHashTable *devices; + + CList network_servers; } NMBluez5ManagerPrivate; struct _NMBluez5Manager { GObject parent; + NMBtVTableNetworkServer network_server_vtable; NMBluez5ManagerPrivate _priv; }; @@ -64,6 +70,15 @@ G_DEFINE_TYPE (NMBluez5Manager, nm_bluez5_manager, G_TYPE_OBJECT) #define NM_BLUEZ5_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMBluez5Manager, NM_IS_BLUEZ5_MANAGER) +#define NM_BLUEZ5_MANAGER_GET_NETWORK_SERVER_VTABLE(self) (&(self)->network_server_vtable) +#define NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER(vtable) \ + NM_BLUEZ5_MANAGER(((char *)(vtable)) - offsetof (struct _NMBluez5Manager, network_server_vtable)) + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez5", __VA_ARGS__) + /*****************************************************************************/ static void device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self); @@ -71,6 +86,182 @@ static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Man /*****************************************************************************/ +typedef struct { + char *path; + char *addr; + NMDevice *device; + CList lst_ns; +} NetworkServer; + +static NetworkServer * +_find_network_server (NMBluez5Manager *self, const char *path, NMDevice *device) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NetworkServer *network_server; + + nm_assert (path || NM_IS_DEVICE (device)); + + c_list_for_each_entry (network_server, &priv->network_servers, lst_ns) { + if (path && !nm_streq (network_server->path, path)) + continue; + if (device && network_server->device != device) + continue; + return network_server; + } + return NULL; +} + +static NetworkServer * +_find_network_server_for_addr (NMBluez5Manager *self, const char *addr) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NetworkServer *network_server; + + c_list_for_each_entry (network_server, &priv->network_servers, lst_ns) { + /* The address lookups need a server not assigned to a device + * and tolerate an empty address as a wildcard for "any". */ + if ( !network_server->device + && (!addr || nm_streq (network_server->addr, addr))) + return network_server; + } + return NULL; +} + +static void +_network_server_unregister (NMBluez5Manager *self, NetworkServer *network_server) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + if (!network_server->device) { + /* Not connected. */ + return; + } + + _LOGI ("NAP: unregistering %s from %s", + nm_device_get_iface (network_server->device), + network_server->addr); + + g_dbus_connection_call (g_dbus_proxy_get_connection (priv->proxy), + NM_BLUEZ_SERVICE, + network_server->path, + NM_BLUEZ5_NETWORK_SERVER_INTERFACE, + "Unregister", + g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, NULL, NULL); + + g_clear_object (&network_server->device); +} + +static void +_network_server_free (NMBluez5Manager *self, NetworkServer *network_server) +{ + _network_server_unregister (self, network_server); + c_list_unlink (&network_server->lst_ns); + g_free (network_server->path); + g_free (network_server->addr); + g_slice_free (NetworkServer, network_server); +} + +static gboolean +network_server_is_available (const NMBtVTableNetworkServer *vtable, + const char *addr) +{ + NMBluez5Manager *self = NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER (vtable); + + return !!_find_network_server_for_addr (self, addr); +} + +static gboolean +network_server_register_bridge (const NMBtVTableNetworkServer *vtable, + const char *addr, + NMDevice *device) +{ + NMBluez5Manager *self = NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER (vtable); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NetworkServer *network_server = _find_network_server_for_addr (self, addr); + + nm_assert (NM_IS_DEVICE (device)); + nm_assert (!_find_network_server (self, NULL, device)); + + if (!network_server) { + /* The device checked that a network server is available, before + * starting the activation, but for some reason it no longer is. + * Indicate that the activation should not proceed. */ + _LOGI ("NAP: %s is not available for %s", addr, nm_device_get_iface (device)); + return FALSE; + } + + _LOGI ("NAP: registering %s on %s", nm_device_get_iface (device), network_server->addr); + + g_dbus_connection_call (g_dbus_proxy_get_connection (priv->proxy), + NM_BLUEZ_SERVICE, + network_server->path, + NM_BLUEZ5_NETWORK_SERVER_INTERFACE, + "Register", + g_variant_new ("(ss)", BLUETOOTH_CONNECT_NAP, nm_device_get_iface (device)), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, NULL, NULL); + + network_server->device = g_object_ref (device); + + return TRUE; +} + +static gboolean +network_server_unregister_bridge (const NMBtVTableNetworkServer *vtable, + NMDevice *device) +{ + NMBluez5Manager *self = NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER (vtable); + NetworkServer *network_server = _find_network_server (self, NULL, device); + + if (network_server) + _network_server_unregister (self, network_server); + + return TRUE; +} + +static void +network_server_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) +{ + NetworkServer *network_server; + + network_server = _find_network_server (self, path, NULL); + if (!network_server) + return; + + if (network_server->device) { + nm_device_queue_state (network_server->device, NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_BT_FAILED); + } + _LOGI ("NAP: removed interface %s", network_server->addr); + _network_server_free (self, network_server); +} + +static void +network_server_added (GDBusProxy *proxy, const gchar *path, const char *addr, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NetworkServer *network_server; + + /* If BlueZ messes up and announces a single network server twice, + * make sure we get rid of the older instance first. */ + network_server_removed (proxy, path, self); + + network_server = g_slice_new0 (NetworkServer); + network_server->path = g_strdup (path); + network_server->addr = g_strdup (addr); + c_list_link_before (&priv->network_servers, &network_server->lst_ns); + + _LOGI ("NAP: added interface %s", addr); + + g_signal_emit (self, signals[NETWORK_SERVER_ADDED], 0); +} + +/*****************************************************************************/ + static void emit_bdaddr_added (NMBluez5Manager *self, NMBluezDevice *device) { @@ -125,14 +316,14 @@ device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *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"); + _LOGD ("(%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)); + _LOGD ("(%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_by_name (device, NM_BLUEZ_DEVICE_REMOVED); @@ -143,9 +334,9 @@ device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *se { NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - nm_log_dbg (LOGD_BT, "(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); + _LOGD ("(%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)); } @@ -157,11 +348,11 @@ device_added (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) NMBluezDevice *device; device = nm_bluez_device_new (path, NULL, priv->settings, 5); - g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_signal_connect (device, NM_BLUEZ_DEVICE_INITIALIZED, G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::" NM_BLUEZ_DEVICE_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); + _LOGD ("(%s): new bluez device found", path); } static void @@ -170,7 +361,7 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); NMBluezDevice *device; - nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + _LOGD ("(%s): bluez device removed", path); device = g_hash_table_lookup (priv->devices, path); if (device) { @@ -186,8 +377,16 @@ object_manager_interfaces_added (GDBusProxy *proxy, GVariant *dict, NMBluez5Manager *self) { - if (g_variant_lookup (dict, BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL)) + if (g_variant_lookup (dict, NM_BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL)) device_added (proxy, path, self); + if (g_variant_lookup (dict, NM_BLUEZ5_NETWORK_SERVER_INTERFACE, "a{sv}", NULL)) { + gs_unref_variant GVariant *adapter = g_variant_lookup_value (dict, NM_BLUEZ5_ADAPTER_INTERFACE, G_VARIANT_TYPE_DICTIONARY); + const char *address; + + if ( adapter + && g_variant_lookup (adapter, "Address", "&s", &address)) + network_server_added (proxy, path, address, self); + } } static void @@ -196,8 +395,10 @@ object_manager_interfaces_removed (GDBusProxy *proxy, const char **ifaces, NMBluez5Manager *self) { - if (ifaces && g_strv_contains (ifaces, BLUEZ5_DEVICE_INTERFACE)) + if (ifaces && g_strv_contains (ifaces, NM_BLUEZ5_DEVICE_INTERFACE)) device_removed (proxy, path, self); + if (ifaces && g_strv_contains (ifaces, NM_BLUEZ5_NETWORK_SERVER_INTERFACE)) + network_server_removed (proxy, path, self); } static void @@ -215,20 +416,17 @@ get_managed_objects_cb (GDBusProxy *proxy, &error); if (!variant) { if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) - nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?"); + _LOGW ("Couldn't get managed objects: not running Bluez5?"); else { g_dbus_error_strip_remote_error (error); - nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", error->message); + _LOGW ("Couldn't get managed objects: %s", error->message); } 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, BLUEZ5_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) { - device_added (proxy, path, self); - } + object_manager_interfaces_added (proxy, path, ifaces, self); g_variant_unref (ifaces); } @@ -248,7 +446,7 @@ on_proxy_acquired (GObject *object, 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->message); + _LOGW ("Couldn't acquire object manager proxy: %s", error->message); g_clear_error (&error); return; } @@ -281,9 +479,9 @@ bluez_connect (NMBluez5Manager *self) g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - OBJECT_MANAGER_INTERFACE, + NM_BLUEZ_SERVICE, + NM_BLUEZ_MANAGER_PATH, + NM_OBJECT_MANAGER_INTERFACE, NULL, (GAsyncReadyCallback) on_proxy_acquired, self); @@ -306,33 +504,26 @@ name_owner_changed_cb (GObject *object, } } -static void -bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - - if (priv->proxy) { - g_signal_handlers_disconnect_by_func (priv->proxy, G_CALLBACK (name_owner_changed_cb), self); - g_clear_object (&priv->proxy); - } - - if (do_signal) - remove_all_devices (self); - else - g_hash_table_remove_all (priv->devices); -} - /*****************************************************************************/ static void nm_bluez5_manager_init (NMBluez5Manager *self) { NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBtVTableNetworkServer *network_server_vtable = NM_BLUEZ5_MANAGER_GET_NETWORK_SERVER_VTABLE (self); bluez_connect (self); - priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + priv->devices = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref); + + c_list_init (&priv->network_servers); + + nm_assert (!nm_bt_vtable_network_server); + network_server_vtable->is_available = network_server_is_available; + network_server_vtable->register_bridge = network_server_register_bridge; + network_server_vtable->unregister_bridge = network_server_unregister_bridge; + nm_bt_vtable_network_server = network_server_vtable; } NMBluez5Manager * @@ -351,8 +542,18 @@ static void dispose (GObject *object) { NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + CList *iter, *safe; - bluez_cleanup (self, FALSE); + c_list_for_each_safe (iter, safe, &priv->network_servers) + _network_server_free (self, c_list_entry (iter, NetworkServer, lst_ns)); + + if (priv->proxy) { + g_signal_handlers_disconnect_by_func (priv->proxy, G_CALLBACK (name_owner_changed_cb), self); + g_clear_object (&priv->proxy); + } + + g_hash_table_remove_all (priv->devices); G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->dispose (object); } @@ -360,7 +561,8 @@ dispose (GObject *object) static void finalize (GObject *object) { - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE ((NMBluez5Manager *) object); + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); g_hash_table_destroy (priv->devices); @@ -384,4 +586,11 @@ nm_bluez5_manager_class_init (NMBluez5ManagerClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + + signals[NETWORK_SERVER_ADDED] = + g_signal_new (NM_BLUEZ_MANAGER_NETWORK_SERVER_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); } diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 4ee71489..0d46be8f 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -40,15 +40,14 @@ #include "nm-bt-error.h" #include "platform/nm-platform.h" +#include "devices/wwan/nm-modem-manager.h" +#include "devices/wwan/nm-modem.h" + #include "introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h" #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBt); -#define MM_DBUS_SERVICE "org.freedesktop.ModemManager1" -#define MM_DBUS_PATH "/org/freedesktop/ModemManager1" -#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager1" - /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( @@ -65,7 +64,8 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - GDBusProxy *mm_proxy; + NMModemManager *modem_manager; + gboolean mm_running; NMBluezDevice *bt_device; @@ -647,7 +647,7 @@ component_added (NMDevice *device, GObject *component) NMDeviceState state; NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - if (!NM_IS_MODEM (component)) + if (!component || !NM_IS_MODEM (component)) return FALSE; modem = NM_MODEM (component); @@ -967,9 +967,12 @@ is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags) } static void -set_mm_running (NMDeviceBt *self, gboolean running) +set_mm_running (NMDeviceBt *self) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gboolean running; + + running = (nm_modem_manager_name_owner_get (priv->modem_manager) != NULL); if (priv->mm_running != running) { _LOGD (LOGD_BT, "ModemManager now %s", @@ -983,18 +986,11 @@ set_mm_running (NMDeviceBt *self, gboolean running) } static void -mm_name_owner_changed (GObject *object, - GParamSpec *pspec, - NMDeviceBt *self) +mm_name_owner_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) { - char *owner; - - owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)); - if (owner) { - set_mm_running (self, TRUE); - g_free (owner); - } else - set_mm_running (self, FALSE); + set_mm_running (user_data); } /*****************************************************************************/ @@ -1039,7 +1035,8 @@ set_property (GObject *object, guint prop_id, case PROP_BT_DEVICE: /* construct-only */ priv->bt_device = g_value_dup_object (value); - g_signal_connect (priv->bt_device, "removed", G_CALLBACK (bluez_device_removed), object); + if (!priv->bt_device) + g_return_if_reached (); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1052,46 +1049,42 @@ set_property (GObject *object, guint prop_id, static void nm_device_bt_init (NMDeviceBt *self) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - GError *error = NULL; - - priv->mm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - MM_DBUS_SERVICE, - MM_DBUS_PATH, - MM_DBUS_INTERFACE, - NULL, &error); - if (priv->mm_proxy) { - g_signal_connect (priv->mm_proxy, "notify::g-name-owner", - G_CALLBACK (mm_name_owner_changed), - self); - mm_name_owner_changed (G_OBJECT (priv->mm_proxy), NULL, self); - } else { - _LOGW (LOGD_MB, "Could not create proxy for '%s': %s", - MM_DBUS_SERVICE, error->message); - g_clear_error (&error); - } } static void constructed (GObject *object) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) object); + NMDeviceBt *self = NM_DEVICE_BT (object); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); const char *my_hwaddr; G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); + priv->modem_manager = g_object_ref (nm_modem_manager_get ()); + + nm_modem_manager_name_owner_ref (priv->modem_manager); + + g_signal_connect (priv->modem_manager, + "notify::"NM_MODEM_MANAGER_NAME_OWNER, + G_CALLBACK (mm_name_owner_changed_cb), + self); + + if (priv->bt_device) { + /* Watch for BT device property changes */ + g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, + G_CALLBACK (bluez_connected_changed), + object); + g_signal_connect (priv->bt_device, NM_BLUEZ_DEVICE_REMOVED, + G_CALLBACK (bluez_device_removed), object); + } + my_hwaddr = nm_device_get_hw_address (NM_DEVICE (object)); - g_assert (my_hwaddr); - priv->bdaddr = g_strdup (my_hwaddr); + if (my_hwaddr) + priv->bdaddr = g_strdup (my_hwaddr); + else + g_warn_if_reached (); - /* Watch for BT device property changes */ - g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, - G_CALLBACK (bluez_connected_changed), - object); + set_mm_running (self); } NMDevice * @@ -1129,9 +1122,10 @@ dispose (GObject *object) g_signal_handlers_disconnect_matched (priv->bt_device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); - if (priv->mm_proxy) { - g_signal_handlers_disconnect_by_func (priv->mm_proxy, G_CALLBACK (mm_name_owner_changed), object); - g_clear_object (&priv->mm_proxy); + if (priv->modem_manager) { + g_signal_handlers_disconnect_by_func (priv->modem_manager, G_CALLBACK (mm_name_owner_changed_cb), object); + nm_modem_manager_name_owner_unref (priv->modem_manager); + g_clear_object (&priv->modem_manager); } modem_cleanup (NM_DEVICE_BT (object)); diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h index 9bcf6ca8..b90dbd2a 100644 --- a/src/devices/bluetooth/nm-device-bt.h +++ b/src/devices/bluetooth/nm-device-bt.h @@ -24,8 +24,6 @@ #include "devices/nm-device.h" #include "nm-bluez-device.h" -#include "devices/wwan/nm-modem.h" - #define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ()) #define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt)) #define NM_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) @@ -52,8 +50,10 @@ NMDevice *nm_device_bt_new (NMBluezDevice *bt_device, guint32 nm_device_bt_get_capabilities (NMDeviceBt *device); +struct _NMModem; + gboolean nm_device_bt_modem_added (NMDeviceBt *device, - NMModem *modem, + struct _NMModem *modem, const char *driver); #endif /* __NETWORKMANAGER_DEVICE_BT_H__ */ |