bluetooth: move device logic to bluez manager
authorDan Williams <dcbw@redhat.com>
Fri, 11 May 2012 16:17:18 +0000 (11:17 -0500)
committerDan Williams <dcbw@redhat.com>
Thu, 17 May 2012 18:27:09 +0000 (13:27 -0500)
To simplify NMManager and to make use of the new connection provider
functionality, move the logic for when a paired Bluetooth device
is actually usable for network connections or not into the bluez
manager and out of NMManager.  The general direction should be towards
moving this sort of logic out of the manager and into the device
specific stuff, like we did with the WiMAX bits, so we can make
stuff into plugins.

src/bluez-manager/nm-bluez-adapter.c
src/bluez-manager/nm-bluez-adapter.h
src/bluez-manager/nm-bluez-device.c
src/bluez-manager/nm-bluez-device.h
src/bluez-manager/nm-bluez-manager.c
src/bluez-manager/nm-bluez-manager.h
src/nm-manager.c

index 27a85e7..4c36f3d 100644 (file)
@@ -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 <glib.h>
@@ -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 */
index c552e98..36aa55d 100644 (file)
@@ -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 <glib-object.h>
 
 #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);
 
index ecb6ce5..b12a861 100644 (file)
  * 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 <glib.h>
 #include <string.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
 
 #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,59 +132,137 @@ nm_bluez_device_get_rssi (NMBluezDevice *self)
        return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi;
 }
 
-static guint32
-convert_uuids_to_capabilities (const char **strings)
+static void
+check_emit_usable (NMBluezDevice *self)
 {
-       const char **iter;
-       guint32 capabilities = 0;
+       NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
+       gboolean new_usable;
 
-       for (iter = strings; iter && *iter; iter++) {
-               char **parts;
-               guint uuid16;
+       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);
+       }
+}
 
-               parts = g_strsplit (*iter, "-", -1);
-               if (parts == NULL || parts[0] == NULL) {
-                       g_strfreev (parts);
-                       continue;
-               }
+/********************************************************************/
 
-               uuid16 = g_ascii_strtoull (parts[0], NULL, 16);
-               g_strfreev (parts);
+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;
 
-               switch (uuid16) {
-               case 0x1103:
-                       capabilities |= NM_BT_CAPABILITY_DUN;
-                       break;
-               case 0x1116:
-                       capabilities |= NM_BT_CAPABILITY_NAP;
-                       break;
-               default:
-                       break;
-               }
+       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);
        }
+}
 
-       return capabilities;
+static void
+cp_connection_added (NMConnectionProvider *provider,
+                     NMConnection *connection,
+                     NMBluezDevice *self)
+{
+       if (connection_compatible (self, connection))
+               _internal_add_connection (self, connection);
 }
 
 static void
-check_emit_usable (NMBluezDevice *self)
+cp_connection_removed (NMConnectionProvider *provider,
+                       NMConnection *connection,
+                       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);
+       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)
+{
+       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 0x1103:
+                               capabilities |= NM_BT_CAPABILITY_DUN;
+                               break;
+                       case 0x1116:
+                               capabilities |= NM_BT_CAPABILITY_NAP;
+                               break;
+                       default:
+                               break;
+                       }
                }
+               g_strfreev (parts);
        }
+
+       return capabilities;
 }
 
 static void
@@ -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);
 
@@ -319,6 +443,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)
 {
        NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (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 */
index 8a6b359..f5fdbf5 100644 (file)
@@ -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 <glib.h>
 #include <glib-object.h>
 
+#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);
 
index 942d0f3..e485ffe 100644 (file)
@@ -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 <signal.h>
@@ -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);
        }
 }
@@ -238,12 +240,6 @@ bluez_connect (NMBluezManager *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,
                        const char *old_owner,
@@ -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),
index 9cfab1b..1549e69 100644 (file)
@@ -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 <glib.h>
 #include <glib-object.h>
 
+#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 */
index 748885e..8f05c08 100644 (file)
@@ -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;
 }