bluetooth: move device logic to bluez manager

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.
This commit is contained in:
Dan Williams 2012-05-11 11:17:18 -05:00
parent 4dc5e6c92a
commit 201096b209
7 changed files with 313 additions and 255 deletions

View 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 */

View 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);

View file

@ -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 <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,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 */

View 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);

View 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);
}
}
@ -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),

View 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 */

View 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;
}