diff --git a/src/bluez-manager/nm-bluez-adapter.c b/src/bluez-manager/nm-bluez-adapter.c index 27a85e78eb..4c36f3de4c 100644 --- a/src/bluez-manager/nm-bluez-adapter.c +++ b/src/bluez-manager/nm-bluez-adapter.c @@ -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 - 2010 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. */ #include @@ -41,6 +41,9 @@ typedef struct { char *address; GHashTable *devices; + + /* Cached for devices */ + NMConnectionProvider *provider; } NMBluezAdapterPrivate; @@ -85,23 +88,18 @@ nm_bluez_adapter_get_initialized (NMBluezAdapter *self) return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->initialized; } -static void -devices_to_list (gpointer key, gpointer data, gpointer user_data) -{ - NMBluezDevice *device = NM_BLUEZ_DEVICE (data); - GSList **list = user_data; - - if (nm_bluez_device_get_usable (device)) - *list = g_slist_append (*list, data); -} - GSList * nm_bluez_adapter_get_devices (NMBluezAdapter *self) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); GSList *devices = NULL; + GHashTableIter iter; + NMBluezDevice *device; - g_hash_table_foreach (priv->devices, devices_to_list, &devices); + g_hash_table_iter_init (&iter, NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + devices = g_slist_append (devices, device); + } return devices; } @@ -109,16 +107,19 @@ static void device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) { NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + gboolean usable = nm_bluez_device_get_usable (device); - if (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)); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); - else { - g_object_ref (device); - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); + } else g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); - g_object_unref (device); - } } static void @@ -127,6 +128,9 @@ device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_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)); } @@ -138,10 +142,12 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data) NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_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, g_strdup (path), device); + 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 @@ -151,10 +157,12 @@ device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_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, path); + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); g_object_unref (device); } @@ -214,8 +222,10 @@ query_properties (NMBluezAdapter *self) } } +/***********************************************************/ + NMBluezAdapter * -nm_bluez_adapter_new (const char *path) +nm_bluez_adapter_new (const char *path, NMConnectionProvider *provider) { NMBluezAdapter *self; NMBluezAdapterPrivate *priv; @@ -229,6 +239,9 @@ nm_bluez_adapter_new (const char *path) return NULL; priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + + priv->provider = provider; + dbus_mgr = nm_dbus_manager_get (); connection = nm_dbus_manager_get_connection (dbus_mgr); @@ -258,7 +271,23 @@ nm_bluez_adapter_init (NMBluezAdapter *self) NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_object_unref); + NULL, g_object_unref); +} + +static void +dispose (GObject *object) +{ + NMBluezAdapter *self = NM_BLUEZ_ADAPTER (object); + NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + 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[DEVICE_REMOVED], 0, device); + g_hash_table_remove_all (priv->devices); + + G_OBJECT_CLASS (nm_bluez_adapter_parent_class)->dispose (object); } static void @@ -320,6 +349,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; + object_class->dispose = dispose; object_class->finalize = finalize; /* Properties */ diff --git a/src/bluez-manager/nm-bluez-adapter.h b/src/bluez-manager/nm-bluez-adapter.h index c552e98900..36aa55dfe9 100644 --- a/src/bluez-manager/nm-bluez-adapter.h +++ b/src/bluez-manager/nm-bluez-adapter.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) 2009 - 2012 Red Hat, Inc. */ #ifndef NM_BLUEZ_ADAPTER_H @@ -25,6 +25,7 @@ #include #include "nm-bluez-device.h" +#include "nm-connection-provider.h" #define NM_TYPE_BLUEZ_ADAPTER (nm_bluez_adapter_get_type ()) #define NM_BLUEZ_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapter)) @@ -53,7 +54,8 @@ typedef struct { GType nm_bluez_adapter_get_type (void); -NMBluezAdapter *nm_bluez_adapter_new (const char *path); +NMBluezAdapter *nm_bluez_adapter_new (const char *path, + NMConnectionProvider *provider); const char *nm_bluez_adapter_get_path (NMBluezAdapter *self); diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index ecb6ce5136..b12a8619bd 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -15,13 +15,17 @@ * 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 - 2010 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. */ #include #include +#include +#include #include "NetworkManager.h" +#include "nm-setting-bluetooth.h" + #include "nm-dbus-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" @@ -41,9 +45,13 @@ typedef struct { gboolean usable; char *address; + guint8 bin_address[ETH_ALEN]; char *name; guint32 capabilities; gint rssi; + + NMConnectionProvider *provider; + GSList *connections; } NMBluezDevicePrivate; @@ -66,6 +74,8 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; +/***********************************************************/ + const char * nm_bluez_device_get_path (NMBluezDevice *self) { @@ -122,6 +132,111 @@ nm_bluez_device_get_rssi (NMBluezDevice *self) return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; } +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->connections); + if (new_usable != priv->usable) { + priv->usable = new_usable; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); + } +} + +/********************************************************************/ + +static gboolean +connection_compatible (NMBluezDevice *self, NMConnection *connection) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + NMSettingBluetooth *s_bt; + const char *bt_type; + const GByteArray *bdaddr; + + if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) + return FALSE; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return FALSE; + + bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); + if (!bdaddr || bdaddr->len != ETH_ALEN) + return FALSE; + if (memcmp (bdaddr->data, priv->bin_address, ETH_ALEN) != 0) + return FALSE; + + 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; + + if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) + && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) + return FALSE; + + return TRUE; +} + +static void +_internal_add_connection (NMBluezDevice *self, NMConnection *connection) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (!g_slist_find (priv->connections, connection)) { + priv->connections = g_slist_prepend (priv->connections, g_object_ref (connection)); + check_emit_usable (self); + } +} + +static void +cp_connection_added (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + if (connection_compatible (self, connection)) + _internal_add_connection (self, connection); +} + +static void +cp_connection_removed (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (g_slist_find (priv->connections, connection)) { + priv->connections = g_slist_remove (priv->connections, connection); + g_object_unref (connection); + check_emit_usable (self); + } +} + +static void +cp_connection_updated (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + if (connection_compatible (self, connection)) + _internal_add_connection (self, connection); + else + cp_connection_removed (provider, connection, self); +} + +static void +cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) +{ + const GSList *connections, *iter; + + connections = nm_connection_provider_get_connections (provider); + for (iter = connections; iter; iter = g_slist_next (iter)) + cp_connection_added (provider, NM_CONNECTION (iter->data), self); +} + +/***********************************************************/ + static guint32 convert_uuids_to_capabilities (const char **strings) { @@ -130,53 +245,26 @@ convert_uuids_to_capabilities (const char **strings) for (iter = strings; iter && *iter; iter++) { char **parts; - guint uuid16; parts = g_strsplit (*iter, "-", -1); - if (parts == NULL || parts[0] == NULL) { - g_strfreev (parts); - continue; + if (parts && parts[0]) { + switch (g_ascii_strtoull (parts[0], NULL, 16)) { + case 0x1103: + capabilities |= NM_BT_CAPABILITY_DUN; + break; + case 0x1116: + capabilities |= NM_BT_CAPABILITY_NAP; + break; + default: + break; + } } - - uuid16 = g_ascii_strtoull (parts[0], NULL, 16); g_strfreev (parts); - - switch (uuid16) { - case 0x1103: - capabilities |= NM_BT_CAPABILITY_DUN; - break; - case 0x1116: - capabilities |= NM_BT_CAPABILITY_NAP; - break; - default: - break; - } } return capabilities; } -static void -check_emit_usable (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if ( priv->initialized - && priv->capabilities - && priv->name - && priv->address) { - if (!priv->usable) { - priv->usable = TRUE; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); - } - } else { - if (priv->usable) { - priv->usable = FALSE; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); - } - } -} - static void property_changed (DBusGProxy *proxy, const char *property, @@ -224,6 +312,7 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) GError *err = NULL; GValue *value; const char **uuids; + struct ether_addr *tmp; if (!dbus_g_proxy_end_call (proxy, call, &err, DBUS_TYPE_G_MAP_OF_VARIANT, &properties, @@ -237,6 +326,11 @@ get_properties_cb (DBusGProxy *proxy, 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); + } value = g_hash_table_lookup (properties, "Name"); priv->name = value ? g_value_dup_string (value) : NULL; @@ -253,6 +347,9 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) g_hash_table_unref (properties); + /* Check if any connections match this device */ + cp_connections_loaded (priv->provider, self); + priv->initialized = TRUE; g_signal_emit (self, signals[INITIALIZED], 0, TRUE); @@ -275,14 +372,18 @@ query_properties (NMBluezDevice *self) } } +/********************************************************************/ + NMBluezDevice * -nm_bluez_device_new (const char *path) +nm_bluez_device_new (const char *path, NMConnectionProvider *provider) { NMBluezDevice *self; NMBluezDevicePrivate *priv; NMDBusManager *dbus_mgr; DBusGConnection *connection; + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (provider != NULL, NULL); self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, NM_BLUEZ_DEVICE_PATH, path, @@ -291,6 +392,29 @@ nm_bluez_device_new (const char *path) return NULL; priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + priv->provider = provider; + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (cp_connection_added), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (cp_connection_removed), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (cp_connection_updated), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTIONS_LOADED, + G_CALLBACK (cp_connections_loaded), + self); + dbus_mgr = nm_dbus_manager_get (); connection = nm_dbus_manager_get_connection (dbus_mgr); @@ -318,6 +442,24 @@ 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_slist_foreach (priv->connections, (GFunc) g_object_unref, NULL); + g_slist_free (priv->connections); + priv->connections = NULL; + + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); + 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_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); +} + static void finalize (GObject *object) { @@ -389,6 +531,7 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; + object_class->dispose = dispose; object_class->finalize = finalize; /* Properties */ diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index 8a6b3597ad..f5fdbf5fb0 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.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) 2009 - 2012 Red Hat, Inc. */ #ifndef NM_BLUEZ_DEVICE_H @@ -24,6 +24,9 @@ #include #include +#include "nm-connection.h" +#include "nm-connection-provider.h" + #define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) #define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) #define NM_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) @@ -53,7 +56,7 @@ typedef struct { GType nm_bluez_device_get_type (void); -NMBluezDevice *nm_bluez_device_new (const char *path); +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.c b/src/bluez-manager/nm-bluez-manager.c index 942d0f3429..e485ffe460 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-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 - 2010 Red Hat, Inc. + * Copyright (C) 2007 - 2012 Red Hat, Inc. */ #include @@ -37,6 +37,8 @@ typedef struct { NMDBusManager *dbus_mgr; gulong name_owner_changed_id; + NMConnectionProvider *provider; + DBusGProxy *proxy; NMBluezAdapter *adapter; @@ -165,7 +167,7 @@ default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *se /* Add the new default adapter */ if (path) { - priv->adapter = nm_bluez_adapter_new (path); + priv->adapter = nm_bluez_adapter_new (path, priv->provider); g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); } } @@ -237,12 +239,6 @@ bluez_connect (NMBluezManager *self) query_default_adapter (self); } -static void -remove_all_devices (NMBluezManager *self, gboolean do_signal) -{ - /* FIXME: do something */ -} - static void name_owner_changed_cb (NMDBusManager *dbus_mgr, const char *name, @@ -251,6 +247,7 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, 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)); @@ -260,8 +257,13 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, if (!old_owner_good && new_owner_good) query_default_adapter (self); - else if (old_owner_good && !new_owner_good) - remove_all_devices (self, TRUE); + else if (old_owner_good && !new_owner_good) { + /* Throwing away the adapter removes all devices too */ + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } + } } static void @@ -274,7 +276,10 @@ bluez_cleanup (NMBluezManager *self, gboolean do_signal) priv->proxy = NULL; } - remove_all_devices (self, do_signal); + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } } static void @@ -290,24 +295,22 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, bluez_connect (self); } +/****************************************************************/ NMBluezManager * -nm_bluez_manager_new (void) -{ - return NM_BLUEZ_MANAGER (g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL)); -} - -NMBluezManager * -nm_bluez_manager_get (void) +nm_bluez_manager_get (NMConnectionProvider *provider) { static NMBluezManager *singleton = NULL; - if (!singleton) - singleton = nm_bluez_manager_new (); - else - g_object_ref (singleton); + if (singleton) + return g_object_ref (singleton); + 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; } @@ -333,13 +336,20 @@ nm_bluez_manager_init (NMBluezManager *self) } static void -finalize (GObject *object) +dispose (GObject *object) { NMBluezManager *self = NM_BLUEZ_MANAGER (object); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); bluez_cleanup (self, FALSE); - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->finalize (object); + 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); + g_object_unref (priv->dbus_mgr); + } + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); } static void @@ -350,11 +360,11 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); /* virtual methods */ - object_class->finalize = finalize; + object_class->dispose = dispose; /* Signals */ signals[BDADDR_ADDED] = - g_signal_new ("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), @@ -363,7 +373,7 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); signals[BDADDR_REMOVED] = - g_signal_new ("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), diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h index 9cfab1b7e7..1549e6996c 100644 --- a/src/bluez-manager/nm-bluez-manager.h +++ b/src/bluez-manager/nm-bluez-manager.h @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2009 Red Hat, Inc. + * Copyright (C) 2007 - 2012 Red Hat, Inc. */ #ifndef NM_BLUEZ_MANAGER_H @@ -25,6 +25,8 @@ #include #include +#include "nm-connection-provider.h" + G_BEGIN_DECLS #define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) @@ -34,6 +36,9 @@ G_BEGIN_DECLS #define NM_IS_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_BLUEZ_MANAGER)) #define NM_BLUEZ_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) +#define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" +#define NM_BLUEZ_MANAGER_BDADDR_REMOVED "bdaddr-removed" + typedef struct { GObject parent; } NMBluezManager; @@ -55,8 +60,8 @@ typedef struct { GType nm_bluez_manager_get_type (void); -NMBluezManager *nm_bluez_manager_new (void); -NMBluezManager *nm_bluez_manager_get (void); +NMBluezManager *nm_bluez_manager_get (NMConnectionProvider *provider); + void nm_bluez_manager_query_devices (NMBluezManager *manager); #endif /* NM_BLUEZ_MANAGER_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 748885e350..8f05c08445 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -127,18 +127,16 @@ static gboolean impl_manager_set_logging (NMManager *manager, #include "nm-manager-glue.h" static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, - const char *bdaddr, - const char *name, - const char *object_path, - guint32 uuids, - NMManager *manager); + const char *bdaddr, + const char *name, + const char *object_path, + guint32 uuids, + NMManager *manager); static void bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr, - const char *bdaddr, - const char *object_path, - gpointer user_data); - -static void bluez_manager_resync_devices (NMManager *self); + const char *bdaddr, + const char *object_path, + gpointer user_data); static void add_device (NMManager *self, NMDevice *device); @@ -1160,8 +1158,6 @@ connection_added (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { - bluez_manager_resync_devices (manager); - if (connection_needs_virtual_device (NM_CONNECTION (connection))) system_create_virtual_device (manager, NM_CONNECTION (connection)); } @@ -1171,8 +1167,6 @@ connection_changed (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { - bluez_manager_resync_devices (manager); - /* FIXME: Some virtual devices may need to be updated in the future. */ } @@ -1181,8 +1175,6 @@ connection_removed (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { - bluez_manager_resync_devices (manager); - /* * Do not delete existing virtual devices to keep connectivity up. * Virtual devices are reused when NetworkManager is restarted. @@ -1793,120 +1785,6 @@ add_device (NMManager *self, NMDevice *device) } } -static gboolean -bdaddr_matches_connection (NMSettingBluetooth *s_bt, const char *bdaddr) -{ - const GByteArray *arr; - gboolean ret = FALSE; - - arr = nm_setting_bluetooth_get_bdaddr (s_bt); - - if ( arr != NULL - && arr->len == ETH_ALEN) { - char *str; - - str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - arr->data[0], - arr->data[1], - arr->data[2], - arr->data[3], - arr->data[4], - arr->data[5]); - ret = g_str_equal (str, bdaddr); - g_free (str); - } - - return ret; -} - -static NMConnection * -bluez_manager_find_connection (NMManager *manager, - const char *bdaddr, - guint32 capabilities) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMConnection *found = NULL; - GSList *connections, *l; - - connections = nm_settings_get_connections (priv->settings); - - for (l = connections; l != NULL; l = l->next) { - NMConnection *candidate = NM_CONNECTION (l->data); - NMSettingConnection *s_con; - NMSettingBluetooth *s_bt; - const char *con_type; - const char *bt_type; - - s_con = nm_connection_get_setting_connection (candidate); - g_assert (s_con); - con_type = nm_setting_connection_get_connection_type (s_con); - g_assert (con_type); - if (!g_str_equal (con_type, NM_SETTING_BLUETOOTH_SETTING_NAME)) - continue; - - s_bt = nm_connection_get_setting_bluetooth (candidate); - if (!s_bt) - continue; - - if (!bdaddr_matches_connection (s_bt, bdaddr)) - continue; - - bt_type = nm_setting_bluetooth_get_connection_type (s_bt); - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) - && !(capabilities & NM_BT_CAPABILITY_DUN)) - continue; - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) - && !(capabilities & NM_BT_CAPABILITY_NAP)) - continue; - - found = candidate; - break; - } - - g_slist_free (connections); - return found; -} - -static void -bluez_manager_resync_devices (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter, *gone = NULL, *keep = NULL; - - /* Remove devices from the device list that don't have a corresponding connection */ - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = NM_DEVICE (iter->data); - guint32 uuids; - const char *bdaddr; - - if (nm_device_get_device_type (candidate) == NM_DEVICE_TYPE_BT) { - uuids = nm_device_bt_get_capabilities (NM_DEVICE_BT (candidate)); - bdaddr = nm_device_bt_get_hw_address (NM_DEVICE_BT (candidate)); - - if (bluez_manager_find_connection (self, bdaddr, uuids)) - keep = g_slist_prepend (keep, candidate); - else - gone = g_slist_prepend (gone, candidate); - } else - keep = g_slist_prepend (keep, candidate); - } - - /* Only touch the device list if anything actually changed */ - if (g_slist_length (gone)) { - g_slist_free (priv->devices); - priv->devices = keep; - - while (g_slist_length (gone)) - gone = remove_one_device (self, gone, NM_DEVICE (gone->data), FALSE); - } else { - g_slist_free (keep); - g_slist_free (gone); - } - - /* Now look for devices without connections */ - nm_bluez_manager_query_devices (priv->bluez_mgr); -} - static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, const char *bdaddr, @@ -1928,12 +1806,6 @@ bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, if (nm_manager_get_device_by_udi (manager, object_path)) return; - if (has_dun == FALSE && has_nap == FALSE) - return; - - if (!bluez_manager_find_connection (manager, bdaddr, capabilities)) - return; - device = nm_device_bt_new (object_path, bdaddr, name, capabilities, FALSE); if (device) { nm_log_info (LOGD_HW, "BT device %s (%s) added (%s%s%s)", @@ -1955,19 +1827,15 @@ bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr, { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; + NMDevice *device; g_return_if_fail (bdaddr != NULL); g_return_if_fail (object_path != NULL); - for (iter = priv->devices; iter; iter = iter->next) { - NMDevice *device = NM_DEVICE (iter->data); - - if (!strcmp (nm_device_get_udi (device), object_path)) { - nm_log_info (LOGD_HW, "BT device %s removed", bdaddr); - priv->devices = remove_one_device (self, priv->devices, device, FALSE); - break; - } + device = nm_manager_get_device_by_udi (self, object_path); + if (device) { + nm_log_info (LOGD_HW, "BT device %s removed", bdaddr); + priv->devices = remove_one_device (self, priv->devices, device, FALSE); } } @@ -3254,9 +3122,6 @@ do_sleep_wake (NMManager *self) else nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED); } - - /* Ask for new bluetooth devices */ - bluez_manager_resync_devices (self); } nm_manager_update_state (self); @@ -3673,7 +3538,7 @@ nm_manager_start (NMManager *self) system_hostname_changed_cb (priv->settings, NULL, self); nm_udev_manager_query_devices (priv->udev_mgr); - bluez_manager_resync_devices (self); + nm_bluez_manager_query_devices (priv->bluez_mgr); /* Query devices again to ensure that we catch all virtual interfaces (like * VLANs) that require a parent. If during the first pass the VLAN @@ -4015,17 +3880,17 @@ nm_manager_new (NMSettings *settings, G_CALLBACK (udev_manager_rfkill_changed_cb), singleton); - priv->bluez_mgr = nm_bluez_manager_get (); + priv->bluez_mgr = nm_bluez_manager_get (NM_CONNECTION_PROVIDER (priv->settings)); g_signal_connect (priv->bluez_mgr, - "bdaddr-added", - G_CALLBACK (bluez_manager_bdaddr_added_cb), - singleton); + NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_CALLBACK (bluez_manager_bdaddr_added_cb), + singleton); g_signal_connect (priv->bluez_mgr, - "bdaddr-removed", - G_CALLBACK (bluez_manager_bdaddr_removed_cb), - singleton); + NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_CALLBACK (bluez_manager_bdaddr_removed_cb), + singleton); return singleton; }