diff --git a/configure.ac b/configure.ac index 136c1d047b..be15f7986a 100644 --- a/configure.ac +++ b/configure.ac @@ -267,18 +267,6 @@ else fi AC_SUBST(UDEV_BASE_DIR) -# BlueZ -AC_ARG_ENABLE(bluez4, AS_HELP_STRING([--enable-bluez4], - [build with BlueZ 4 support instead of BlueZ 5]), - [enable_bluez4=${enableval}]) -if (test "${enable_bluez4}" = "yes"); then - AC_DEFINE(WITH_BLUEZ4, 1, [Define if you have BlueZ 4 support]) -else - AC_DEFINE(WITH_BLUEZ4, 0, [Define if you have BlueZ 4 support]) - enable_bluez4=no -fi -AM_CONDITIONAL(WITH_BLUEZ4, test "${enable_bluez4}" = "yes") - # systemd unit support AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])) @@ -826,7 +814,6 @@ echo " modemmanager-1: $with_modem_manager_1" echo " concheck: $enable_concheck" echo " libndp: $libndp_location" echo " libteamdctl: $enable_teamdctl" -echo " bluez 4: $enable_bluez4" echo echo "Configuration plugins" diff --git a/src/Makefile.am b/src/Makefile.am index 7799cbfddd..d301000bf3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,6 +49,18 @@ NetworkManager_LDADD = libNetworkManager.la $(top_builddir)/libgsystem.la $(LIBN noinst_LTLIBRARIES = libNetworkManager.la nm_sources = \ + bluez-manager/nm-bluez-common.h \ + bluez-manager/nm-bluez-device.c \ + bluez-manager/nm-bluez-device.h \ + bluez-manager/nm-bluez-manager.c \ + bluez-manager/nm-bluez-manager.h \ + bluez-manager/nm-bluez4-adapter.c \ + bluez-manager/nm-bluez4-adapter.h \ + bluez-manager/nm-bluez4-manager.c \ + bluez-manager/nm-bluez4-manager.h \ + bluez-manager/nm-bluez5-manager.c \ + bluez-manager/nm-bluez5-manager.h \ + \ config/nm-config.c \ config/nm-config.h \ config/nm-config-device.c \ @@ -258,22 +270,6 @@ nm_sources = \ NetworkManagerUtils.c \ NetworkManagerUtils.h -nm_sources += \ - bluez-manager/nm-bluez-common.h \ - bluez-manager/nm-bluez-device.c \ - bluez-manager/nm-bluez-device.h \ - bluez-manager/nm-bluez-manager.h - -if WITH_BLUEZ4 -nm_sources += \ - bluez-manager/nm-bluez4-adapter.h \ - bluez-manager/nm-bluez4-adapter.c \ - bluez-manager/nm-bluez4-manager.c -else -nm_sources += \ - bluez-manager/nm-bluez-manager.c -endif - if WITH_MODEM_MANAGER_1 nm_sources += \ modem-manager/nm-modem-broadband.c \ diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h index ecc4d70947..f80cfc2e39 100644 --- a/src/bluez-manager/nm-bluez-common.h +++ b/src/bluez-manager/nm-bluez-common.h @@ -31,21 +31,15 @@ #define BLUEZ_MANAGER_PATH "/" #define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" -#if ! WITH_BLUEZ4 +#define BLUEZ5_ADAPTER_INTERFACE "org.bluez.Adapter1" +#define BLUEZ5_DEVICE_INTERFACE "org.bluez.Device1" +#define BLUEZ5_NETWORK_INTERFACE "org.bluez.Network1" -#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1" -#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1" -#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network1" - -#else - -#define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" -#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter" -#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" -#define BLUEZ_SERIAL_INTERFACE "org.bluez.Serial" -#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network" - -#endif /* WITH_BLUEZ */ +#define BLUEZ4_MANAGER_INTERFACE "org.bluez.Manager" +#define BLUEZ4_ADAPTER_INTERFACE "org.bluez.Adapter" +#define BLUEZ4_DEVICE_INTERFACE "org.bluez.Device" +#define BLUEZ4_SERIAL_INTERFACE "org.bluez.Serial" +#define BLUEZ4_NETWORK_INTERFACE "org.bluez.Network" #endif /* NM_BLUEZ_COMMON_H */ diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index c333796527..032048df37 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -30,10 +30,6 @@ #include "nm-setting-bluetooth.h" #include "nm-bluez-common.h" -#if WITH_BLUEZ4 -#include "nm-dbus-manager.h" -#include "nm-dbus-glib-types.h" -#endif #include "nm-bluez-device.h" #include "nm-logging.h" #include "nm-utils.h" @@ -46,13 +42,13 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; GDBusConnection *dbus_connection; -#if ! WITH_BLUEZ4 - GDBusProxy *proxy5; - GDBusProxy *adapter; + + GDBusProxy *proxy; + + GDBusProxy *adapter5; gboolean adapter_powered; -#else - DBusGProxy *proxy4; -#endif + + int bluez_version; gboolean initialized; gboolean usable; @@ -62,7 +58,6 @@ typedef struct { guint8 bin_address[ETH_ALEN]; char *name; guint32 capabilities; - gint rssi; gboolean connected; char *bt_iface; @@ -81,7 +76,6 @@ enum { PROP_ADDRESS, PROP_NAME, PROP_CAPABILITIES, - PROP_RSSI, PROP_USABLE, PROP_CONNECTED, @@ -101,6 +95,11 @@ static void cp_connection_added (NMConnectionProvider *provider, static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection); +#define VARIANT_IS_OF_TYPE_BOOLEAN(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_BOOLEAN) )) +#define VARIANT_IS_OF_TYPE_STRING(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING) )) +#define VARIANT_IS_OF_TYPE_OBJECT_PATH(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_OBJECT_PATH) )) +#define VARIANT_IS_OF_TYPE_STRING_ARRAY(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING_ARRAY) )) + /***********************************************************/ const char * @@ -151,14 +150,6 @@ nm_bluez_device_get_capabilities (NMBluezDevice *self) return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->capabilities; } -gint -nm_bluez_device_get_rssi (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; -} - gboolean nm_bluez_device_get_connected (NMBluezDevice *self) { @@ -252,9 +243,9 @@ pan_connection_check_create (NMBluezDevice *self) priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); priv->pan_connection = added; - nm_log_dbg (LOGD_SETTINGS, "added new Bluetooth connection for NAP device '%s': '%s' (%s)", priv->path, id, uuid); + nm_log_dbg (LOGD_SETTINGS, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid); } else { - nm_log_warn (LOGD_SETTINGS, "couldn't add new Bluetooth connection for NAP device '%s': '%s' (%s): %d / %s", + nm_log_warn (LOGD_SETTINGS, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %d / %s", priv->path, id, uuid, error ? error->code : -1, (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); @@ -272,16 +263,12 @@ check_emit_usable (NMBluezDevice *self) gboolean new_usable; /* only expect the supported capabilities set. */ - g_assert ((priv->capabilities & ~( NM_BT_CAPABILITY_NAP -#if WITH_BLUEZ4 - | NM_BT_CAPABILITY_DUN -#endif - )) == NM_BT_CAPABILITY_NONE); + g_assert (priv->bluez_version != 4 || ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE )); + g_assert (priv->bluez_version != 5 || ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP )) == NM_BT_CAPABILITY_NONE )); new_usable = (priv->initialized && priv->capabilities && priv->name && -#if ! WITH_BLUEZ4 - priv->adapter && priv->adapter_powered && -#endif + ((priv->bluez_version == 4) || + (priv->bluez_version == 5 && priv->adapter5 && priv->adapter_powered) ) && priv->dbus_connection && priv->address); if (!new_usable) @@ -416,7 +403,7 @@ bluez_disconnect_cb (GDBusConnection *dbus_connection, variant = g_dbus_connection_call_finish (dbus_connection, res, &error); if (!variant) { - nm_log_warn (LOGD_BT, "%s: failed to disconnect: %s", priv->address, error->message); + nm_log_warn (LOGD_BT, "bluez[%s]: failed to disconnect: %s", priv->path, error->message); g_error_free (error); } else g_variant_unref (variant); @@ -427,16 +414,14 @@ nm_bluez_device_disconnect (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GVariant *args = NULL; - const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; + const char *dbus_iface; g_return_if_fail (priv->dbus_connection); -#if ! WITH_BLUEZ4 - g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); -#else - g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); - - if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { + if (priv->bluez_version == 5) { + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ5_NETWORK_INTERFACE; + } else if (priv->bluez_version == 4 && priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { /* Can't pass a NULL interface name through dbus to bluez, so just * ignore the disconnect if the interface isn't known. */ @@ -444,9 +429,11 @@ nm_bluez_device_disconnect (NMBluezDevice *self) return; args = g_variant_new ("(s)", priv->bt_iface), - dbus_iface = BLUEZ_SERIAL_INTERFACE; + dbus_iface = BLUEZ4_SERIAL_INTERFACE; + } else { + g_return_if_fail (priv->bluez_version == 4 && priv->connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ4_NETWORK_INTERFACE; } -#endif g_dbus_connection_call (priv->dbus_connection, BLUEZ_SERVICE, @@ -504,20 +491,21 @@ nm_bluez_device_connect_async (NMBluezDevice *self, { GSimpleAsyncResult *simple; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; + const char *dbus_iface; const char *connect_type = BLUETOOTH_CONNECT_NAP; g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); -#if ! WITH_BLUEZ4 - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); -#else - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); - if (connection_bt_type == NM_BT_CAPABILITY_DUN) { - dbus_iface = BLUEZ_SERIAL_INTERFACE; + if (priv->bluez_version == 5) { + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ5_NETWORK_INTERFACE; + } else if (priv->bluez_version == 4 && connection_bt_type == NM_BT_CAPABILITY_DUN) { + dbus_iface = BLUEZ4_SERIAL_INTERFACE; connect_type = BLUETOOTH_CONNECT_DUN; + } else { + g_return_if_fail (priv->bluez_version == 4 && connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ4_NETWORK_INTERFACE; } -#endif simple = g_simple_async_result_new (G_OBJECT (self), callback, @@ -565,7 +553,7 @@ nm_bluez_device_connect_finish (NMBluezDevice *self, /***********************************************************/ static guint32 -convert_uuids_to_capabilities (const char **strings) +convert_uuids_to_capabilities (const char **strings, int bluez_version) { const char **iter; guint32 capabilities = 0; @@ -576,11 +564,10 @@ convert_uuids_to_capabilities (const char **strings) parts = g_strsplit (*iter, "-", -1); if (parts && parts[0]) { switch (g_ascii_strtoull (parts[0], NULL, 16)) { -#if WITH_BLUEZ4 case 0x1103: - capabilities |= NM_BT_CAPABILITY_DUN; + if (bluez_version == 4) + capabilities |= NM_BT_CAPABILITY_DUN; break; -#endif case 0x1116: capabilities |= NM_BT_CAPABILITY_NAP; break; @@ -595,26 +582,25 @@ convert_uuids_to_capabilities (const char **strings) } static void -_set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean notify) +_set_property_capabilities (NMBluezDevice *self, const char **uuids) { guint32 uint_val; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - uint_val = convert_uuids_to_capabilities (uuids); + uint_val = convert_uuids_to_capabilities (uuids, priv->bluez_version); if (priv->capabilities != uint_val) { if (priv->capabilities) { /* changing (relevant) capabilities is not supported and ignored -- except setting initially */ - nm_log_warn (LOGD_BT, "ignore change of capabilities for Bluetooth device %s from %u to %u", + nm_log_warn (LOGD_BT, "bluez[%s] ignore change of capabilities for Bluetooth device from %u to %u", priv->path, priv->capabilities, uint_val); return; } - nm_log_dbg (LOGD_BT, "set capabilities for Bluetooth device %s: %s%s%s", priv->path, + nm_log_dbg (LOGD_BT, "bluez[%s] set capabilities for Bluetooth device: %s%s%s", priv->path, uint_val & NM_BT_CAPABILITY_NAP ? "NAP" : "", ((uint_val & NM_BT_CAPABILITY_DUN) && (uint_val &NM_BT_CAPABILITY_NAP)) ? " | " : "", uint_val & NM_BT_CAPABILITY_DUN ? "DUN" : ""); priv->capabilities = uint_val; - if (notify) - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); } } @@ -634,34 +620,90 @@ _set_property_address (NMBluezDevice *self, const char *addr) return; if (!addr) { - nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); return; } if (priv->address != NULL) { - nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); return; } tmp = ether_aton (addr); if (!tmp) { if (priv->address) - nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s' (invalid value)", priv->path, priv->address, addr); + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to '%s' (invalid value)", priv->path, priv->address, addr); else - nm_log_warn (LOGD_BT, "[%s] cannot reset address from NULL to '%s' (invalid value)", priv->path, addr); + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from NULL to '%s' (invalid value)", priv->path, addr); return; } memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); priv->address = g_strdup (addr); - return; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_ADDRESS); } -#if ! WITH_BLUEZ4 static void -adapter_properties_changed (GDBusProxy *proxy5, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) +_take_variant_property_address (NMBluezDevice *self, GVariant *v) +{ + _set_property_address (self, VARIANT_IS_OF_TYPE_STRING (v) ? g_variant_get_string (v, NULL) : NULL); + if (v) + g_variant_unref (v); +} + +static void +_take_variant_property_name (NMBluezDevice *self, GVariant *v) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + const char *str; + + if (VARIANT_IS_OF_TYPE_STRING (v)) { + str = g_variant_get_string (v, NULL); + if (g_strcmp0 (priv->name, str)) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } + if (v) + g_variant_unref (v); +} + +static void +_take_variant_property_uuids (NMBluezDevice *self, GVariant *v) +{ + if (VARIANT_IS_OF_TYPE_STRING_ARRAY (v)) { + const char **uuids = g_variant_get_strv (v, NULL); + + _set_property_capabilities (self, uuids); + g_free (uuids); + } + if (v) + g_variant_unref (v); +} + +static void +_take_variant_property_connected (NMBluezDevice *self, GVariant *v) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (VARIANT_IS_OF_TYPE_BOOLEAN (v)) { + gboolean connected = g_variant_get_boolean (v); + + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } + } + if (v) + g_variant_unref (v); +} + + +static void +adapter5_on_properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); @@ -671,7 +713,7 @@ adapter_properties_changed (GDBusProxy *proxy5, g_variant_iter_init (&i, changed_properties); while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { - if (!strcmp (property, "Powered")) { + if (!strcmp (property, "Powered") && VARIANT_IS_OF_TYPE_BOOLEAN (v)) { gboolean powered = g_variant_get_boolean (v); if (priv->adapter_powered != powered) priv->adapter_powered = powered; @@ -683,24 +725,24 @@ adapter_properties_changed (GDBusProxy *proxy5, } static void -on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +adapter5_on_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *error; GVariant *v; - priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!priv->adapter) { - nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); + priv->adapter5 = g_dbus_proxy_new_for_bus_finish (res, &error); + if (!priv->adapter5) { + nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire adapter proxy: %s.", priv->path, error->message); g_clear_error (&error); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); } else { - g_signal_connect (priv->adapter, "g-properties-changed", - G_CALLBACK (adapter_properties_changed), self); + g_signal_connect (priv->adapter5, "g-properties-changed", + G_CALLBACK (adapter5_on_properties_changed), self); /* Check adapter's powered state */ - v = g_dbus_proxy_get_cached_property (priv->adapter, "Powered"); - priv->adapter_powered = v ? g_variant_get_boolean (v) : FALSE; + v = g_dbus_proxy_get_cached_property (priv->adapter5, "Powered"); + priv->adapter_powered = VARIANT_IS_OF_TYPE_BOOLEAN (v) ? g_variant_get_boolean (v) : FALSE; if (v) g_variant_unref (v); @@ -714,182 +756,74 @@ on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) } static void -properties_changed (GDBusProxy *proxy5, +_set_properties (NMBluezDevice *self, GVariant *properties) +{ + GVariantIter i; + const char *property; + GVariant *v; + + g_object_freeze_notify (G_OBJECT (self)); + g_variant_iter_init (&i, properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!property) { + g_variant_unref (v); + } else if (!strcmp (property, "Address")) { + _take_variant_property_address (self, v); + } else if (!strcmp (property, "Connected")) { + _take_variant_property_connected (self, v); + } else if (!strcmp (property, "Name")) { + _take_variant_property_name (self, v); + } else if (!strcmp (property, "UUIDs")) { + _take_variant_property_uuids (self, v); + } else + g_variant_unref (v); + } + g_object_thaw_notify (G_OBJECT (self)); +} + +static void +properties_changed (GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariantIter i; - const char *property; - const char *str; - GVariant *v; - gint int_val; - const char **strv; - g_object_freeze_notify (G_OBJECT (self)); - g_variant_iter_init (&i, changed_properties); - while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { - if (!strcmp (property, "Name")) { - str = g_variant_get_string (v, NULL); - if (g_strcmp0 (priv->name, str)) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_variant_get_int16 (v); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - strv = g_variant_get_strv (v, NULL); - _set_property_capabilities (self, strv, TRUE); - g_free (strv); - } else if (!strcmp (property, "Connected")) { - gboolean connected = g_variant_get_boolean (v); - if (priv->connected != connected) { - priv->connected = connected; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); - } - } - g_variant_unref (v); - } - g_object_thaw_notify (G_OBJECT (self)); + _set_properties (self, changed_properties); check_emit_usable (self); } -#else + + static void -property_changed (DBusGProxy *proxy4, - const char *property, - GValue *value, - gpointer user_data) +get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const char *str; - gint int_val; - - g_object_freeze_notify (G_OBJECT (self)); - { - if (!strcmp (property, "Name")) { - str = g_value_get_string (value); - if ( (!priv->name && str) - || (priv->name && !str) - || (priv->name && str && strcmp (priv->name, str))) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_value_get_int (value); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - _set_property_capabilities (self, (const char **) g_value_get_boxed (value), TRUE); - } else if (!strcmp (property, "Connected")) { - gboolean connected = g_value_get_boolean (value); - if (priv->connected != connected) { - priv->connected = connected; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); - } - } - } - g_object_thaw_notify (G_OBJECT (self)); - - check_emit_usable (self); -} -#endif - -#if ! WITH_BLUEZ4 -static void -query_properties (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *v; - const char **uuids; - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); - _set_property_address (self, v ? g_variant_get_string (v, NULL) : NULL); - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); - priv->name = v ? g_variant_dup_string (v, NULL) : NULL; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "RSSI"); - priv->rssi = v ? g_variant_get_int16 (v) : 0; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); - if (v) { - uuids = g_variant_get_strv (v, NULL); - _set_property_capabilities (self, uuids, FALSE); - g_variant_unref (v); - } else - priv->capabilities = NM_BT_CAPABILITY_NONE; - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); - if (v) { - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - g_variant_get_string (v, NULL), - BLUEZ_ADAPTER_INTERFACE, - NULL, - (GAsyncReadyCallback) on_adapter_acquired, - g_object_ref (self)); - g_variant_unref (v); - } - - /* Check if any connections match this device */ - cp_connections_loaded (priv->provider, self); -} -#else -static void -get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GHashTable *properties = NULL; GError *err = NULL; - GValue *value; + GVariant *v_properties, *v_dict; + GVariantType *v_type; - if (!dbus_g_proxy_end_call (proxy4, call, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &properties, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_BT, "bluez error getting device properties: %s", - err && err->message ? err->message : "(unknown)"); + v_properties = g_dbus_proxy_call_finish (priv->proxy, res, &err); + if (!v_properties) { + nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s", + priv->path, err && err->message ? err->message : "(unknown)"); g_error_free (err); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; + goto END; } - value = g_hash_table_lookup (properties, "Address"); - _set_property_address (self, value ? g_value_get_string (value) : NULL); + v_type = g_variant_type_new ("(a{sv})"); + if (g_variant_is_of_type (v_properties, v_type)) { + v_dict = g_variant_get_child_value (v_properties, 0); + _set_properties (self, v_dict); + g_variant_unref (v_dict); + } else { + nm_log_warn (LOGD_BT, "bluez[%s] GetProperties returns unexpected result of type %s", priv->path, g_variant_get_type_string (v_properties)); + } + g_variant_type_free (v_type); - value = g_hash_table_lookup (properties, "Name"); - priv->name = value ? g_value_dup_string (value) : NULL; - - value = g_hash_table_lookup (properties, "RSSI"); - priv->rssi = value ? g_value_get_int (value) : 0; - - value = g_hash_table_lookup (properties, "UUIDs"); - if (value) { - _set_property_capabilities (self, (const char **) g_value_get_boxed (value), FALSE); - } else - priv->capabilities = NM_BT_CAPABILITY_NONE; - - g_hash_table_unref (properties); + g_variant_unref (v_properties); /* Check if any connections match this device */ cp_connections_loaded (priv->provider, self); @@ -897,49 +831,78 @@ get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) priv->initialized = TRUE; g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + check_emit_usable (self); + +END: + g_object_unref (self); } + static void query_properties (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - DBusGProxyCall *call; + GVariant *v; - call = dbus_g_proxy_begin_call (priv->proxy4, "GetProperties", - get_properties_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) { - nm_log_warn (LOGD_BT, "failed to request Bluetooth device properties for %s.", - priv->path); + switch (priv->bluez_version) { + case 4: + g_dbus_proxy_call (priv->proxy, "GetProperties", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, 3000, + NULL, get_properties_cb_4, g_object_ref (self)); + break; + case 5: + g_object_freeze_notify (G_OBJECT (self)); + _take_variant_property_address (self, g_dbus_proxy_get_cached_property (priv->proxy, "Address")); + _take_variant_property_connected (self, g_dbus_proxy_get_cached_property (priv->proxy, "Connected")); + _take_variant_property_name (self, g_dbus_proxy_get_cached_property (priv->proxy, "Name")); + _take_variant_property_uuids (self, g_dbus_proxy_get_cached_property (priv->proxy, "UUIDs")); + g_object_thaw_notify (G_OBJECT (self)); + + v = g_dbus_proxy_get_cached_property (priv->proxy, "Adapter"); + if (VARIANT_IS_OF_TYPE_OBJECT_PATH (v)) { + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + g_variant_get_string (v, NULL), + BLUEZ5_ADAPTER_INTERFACE, + NULL, + (GAsyncReadyCallback) adapter5_on_acquired, + g_object_ref (self)); + g_variant_unref (v); + } else { + /* If the Adapter property is unset at this point, we won't try to acquire the adapter later on + * and the device stays unusable. This should not happen, but if it does, log a debug message. */ + nm_log_dbg (LOGD_BT, "bluez[%s] device has no adapter property and cannot be used.", priv->path); + } + + /* Check if any connections match this device */ + cp_connections_loaded (priv->provider, self); + + break; } } -#endif - -#if ! WITH_BLUEZ4 static void on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error; + GError *error = NULL; - priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!priv->proxy5) { - nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire device proxy: %s.", priv->path, error->message); g_clear_error (&error); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); } else { - g_signal_connect (priv->proxy5, "g-properties-changed", + g_signal_connect (priv->proxy, "g-properties-changed", G_CALLBACK (properties_changed), self); query_properties (self); } g_object_unref (self); } -#endif static void on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) @@ -950,28 +913,27 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) priv->dbus_connection = g_bus_get_finish (res, &error); if (!priv->dbus_connection) { - nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error->message); + nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire bus connection: %s.", priv->path, error->message); g_clear_error (&error); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; - } + } else + check_emit_usable (self); - check_emit_usable (self); + g_object_unref (self); } /********************************************************************/ NMBluezDevice * -nm_bluez_device_new (const char *path, NMConnectionProvider *provider) +nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez_version) { NMBluezDevice *self; NMBluezDevicePrivate *priv; -#if WITH_BLUEZ4 - DBusGConnection *connection; -#endif + const char *interface_name = NULL; g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (provider != NULL, NULL); + g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL); self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, NM_BLUEZ_DEVICE_PATH, path, @@ -979,8 +941,12 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) if (!self) return NULL; + nm_log_dbg (LOGD_BT, "bluez[%s] create NMBluezDevice", path); + priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + priv->bluez_version = bluez_version; + priv->provider = provider; g_signal_connect (priv->provider, @@ -1006,38 +972,26 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider) g_bus_get (G_BUS_TYPE_SYSTEM, NULL, (GAsyncReadyCallback) on_bus_acquired, - self); + g_object_ref (self)); + + switch (priv->bluez_version) { + case 4: + interface_name = BLUEZ4_DEVICE_INTERFACE; + break; + case 5: + interface_name = BLUEZ5_DEVICE_INTERFACE; + break; + } -#if ! WITH_BLUEZ4 - g_object_ref (self); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, BLUEZ_SERVICE, priv->path, - BLUEZ_DEVICE_INTERFACE, + interface_name, NULL, (GAsyncReadyCallback) on_proxy_acquired, - self); -#else - connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - - priv->proxy4 = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE); - - dbus_g_object_register_marshaller (g_cclosure_marshal_generic, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_VALUE, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy4, "PropertyChanged", - G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy4, "PropertyChanged", - G_CALLBACK (property_changed), self, NULL); - - query_properties (self); -#endif + g_object_ref (self)); return self; } @@ -1061,9 +1015,7 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); -#if ! WITH_BLUEZ4 - g_clear_object (&priv->adapter); -#endif + g_clear_object (&priv->adapter5); g_clear_object (&priv->dbus_connection); G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); @@ -1074,15 +1026,14 @@ finalize (GObject *object) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + nm_log_dbg (LOGD_BT, "bluez[%s]: finalize NMBluezDevice", priv->path); + g_free (priv->path); g_free (priv->address); g_free (priv->name); g_free (priv->bt_iface); -#if ! WITH_BLUEZ4 - g_object_unref (priv->proxy5); -#else - g_object_unref (priv->proxy4); -#endif + + g_clear_object (&priv->proxy); G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); } @@ -1106,9 +1057,6 @@ get_property (GObject *object, guint prop_id, case PROP_CAPABILITIES: g_value_set_uint (value, priv->capabilities); break; - case PROP_RSSI: - g_value_set_int (value, priv->rssi); - break; case PROP_USABLE: g_value_set_boolean (value, priv->usable); break; @@ -1184,14 +1132,6 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) 0, G_MAXUINT, 0, G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_RSSI, - g_param_spec_int (NM_BLUEZ_DEVICE_RSSI, - "RSSI", - "RSSI", - G_MININT, G_MAXINT, 0, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, PROP_USABLE, g_param_spec_boolean (NM_BLUEZ_DEVICE_USABLE, diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index 11add38901..5e586ea5bb 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -40,7 +40,6 @@ #define NM_BLUEZ_DEVICE_ADDRESS "address" #define NM_BLUEZ_DEVICE_NAME "name" #define NM_BLUEZ_DEVICE_CAPABILITIES "capabilities" -#define NM_BLUEZ_DEVICE_RSSI "rssi" #define NM_BLUEZ_DEVICE_USABLE "usable" #define NM_BLUEZ_DEVICE_CONNECTED "connected" @@ -59,7 +58,7 @@ typedef struct { GType nm_bluez_device_get_type (void); -NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider); +NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez_version); const char *nm_bluez_device_get_path (NMBluezDevice *self); @@ -75,8 +74,6 @@ guint32 nm_bluez_device_get_class (NMBluezDevice *self); guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); -gint nm_bluez_device_get_rssi (NMBluezDevice *self); - gboolean nm_bluez_device_get_connected (NMBluezDevice *self); void diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c index 4c375c12f7..b3026bc1f5 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-manager.c @@ -15,9 +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) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2012 Red Hat, Inc. - * Copyright (C) 2013 Intel Corporation. + * Copyright (C) 2013 Red Hat, Inc. */ #include @@ -27,26 +25,37 @@ #include "nm-logging.h" #include "nm-bluez-manager.h" +#include "nm-bluez4-manager.h" +#include "nm-bluez5-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-dbus-manager.h" typedef struct { - NMDBusManager *dbus_mgr; - gulong name_owner_changed_id; + int bluez_version; NMConnectionProvider *provider; + NMBluez4Manager *manager4; + NMBluez5Manager *manager5; - GDBusProxy *proxy; + guint watch_name_id; - GHashTable *devices; + GDBusProxy *introspect_proxy; + GCancellable *async_cancellable; } NMBluezManagerPrivate; #define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT) +enum { + PROP_0, + PROP_PROVIDER, + + LAST_PROP +}; + enum { BDADDR_ADDED, BDADDR_REMOVED, @@ -56,359 +65,411 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self); -static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self); + +static void check_bluez_and_try_setup (NMBluezManager *self); + + +struct AsyncData { + NMBluezManager *self; + GCancellable *async_cancellable; +}; + +static struct AsyncData * +async_data_pack (NMBluezManager *self) +{ + struct AsyncData *data = g_new (struct AsyncData, 1); + + data->self = self; + data->async_cancellable = g_object_ref (NM_BLUEZ_MANAGER_GET_PRIVATE (self)->async_cancellable); + return data; +} + +static NMBluezManager * +async_data_unpack (struct AsyncData *async_data) +{ + NMBluezManager *self = g_cancellable_is_cancelled (async_data->async_cancellable) + ? NULL : async_data->self; + + g_object_unref (async_data->async_cancellable); + g_free (async_data); + return self; +} + + +/** + * Cancel any current attempt to detect the version and cleanup + * the related fields. + **/ +static void +cleanup_checking (NMBluezManager *self, gboolean do_unwatch_name) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (priv->async_cancellable) { + g_cancellable_cancel (priv->async_cancellable); + g_clear_object (&priv->async_cancellable); + } + + g_clear_object (&priv->introspect_proxy); + + if (do_unwatch_name && priv->watch_name_id) { + g_bus_unwatch_name (priv->watch_name_id); + priv->watch_name_id = 0; + } +} + static void -emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) +manager_bdaddr_added_cb (NMBluez4Manager *bluez_mgr, + NMBluezDevice *bt_device, + const char *bdaddr, + const char *name, + const char *object_path, + guint32 uuids, + gpointer user_data) { - g_signal_emit (self, signals[BDADDR_ADDED], 0, - device, - nm_bluez_device_get_address (device), - nm_bluez_device_get_name (device), - nm_bluez_device_get_path (device), - nm_bluez_device_get_capabilities (device)); + /* forward the signal... */ + g_signal_emit (NM_BLUEZ_MANAGER (user_data), signals[BDADDR_ADDED], 0, + bt_device, + bdaddr, + name, + object_path, + uuids); } +static void +manager_bdaddr_removed_cb (NMBluez4Manager *bluez_mgr, + const char *bdaddr, + const char *object_path, + gpointer user_data) +{ + /* forward the signal... */ + g_signal_emit (NM_BLUEZ_MANAGER (user_data), signals[BDADDR_REMOVED], 0, + bdaddr, + object_path); +} + + +static void +setup_version_number (NMBluezManager *self, int bluez_version) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->bluez_version); + + nm_log_info (LOGD_BT, "use BlueZ version %d", bluez_version); + + priv->bluez_version = bluez_version; + + /* Just detected the version. Cleanup the ongoing checking/detection. */ + cleanup_checking (self, TRUE); +} + +static void +setup_bluez4 (NMBluezManager *self) +{ + NMBluez4Manager *manager; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); + + setup_version_number (self, 4); + priv->manager4 = manager = nm_bluez4_manager_new (priv->provider); + + g_signal_connect (manager, + NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_CALLBACK (manager_bdaddr_added_cb), + self); + g_signal_connect (manager, + NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_CALLBACK (manager_bdaddr_removed_cb), + self); + + nm_bluez4_manager_query_devices (manager); +} + +static void +setup_bluez5 (NMBluezManager *self) +{ + NMBluez5Manager *manager; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); + + setup_version_number (self, 5); + priv->manager5 = manager = nm_bluez5_manager_new (priv->provider); + + g_signal_connect (manager, + NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_CALLBACK (manager_bdaddr_added_cb), + self); + g_signal_connect (manager, + NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_CALLBACK (manager_bdaddr_removed_cb), + self); + + nm_bluez5_manager_query_devices (manager); +} + + +static void +watch_name_on_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + check_bluez_and_try_setup (NM_BLUEZ_MANAGER (user_data)); +} + + +static void +check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, const char *reason) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->bluez_version); + + switch (bluez_version) { + case 4: + setup_bluez4 (self); + break; + case 5: + setup_bluez5 (self); + break; + default: + nm_log_dbg (LOGD_BT, "detecting BlueZ version failed: %s", reason); + + /* cancel current attempts to detect the version. */ + cleanup_checking (self, FALSE); + if (!priv->watch_name_id) { + priv->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + BLUEZ_SERVICE, + G_BUS_NAME_WATCHER_FLAGS_NONE, + watch_name_on_appeared, + NULL, + self, + NULL); + } + break; + } +} + +static void +check_bluez_and_try_setup_do_introspect (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezManager *self = async_data_unpack (user_data); + NMBluezManagerPrivate *priv; + GError *error = NULL; + GVariant *result; + const char *xml_data; + int bluez_version = 0; + const char *reason = NULL; + + if (!self) + return; + + priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (priv->introspect_proxy); + g_return_if_fail (!g_cancellable_is_cancelled (priv->async_cancellable)); + g_return_if_fail (!priv->bluez_version); + + g_clear_object (&priv->async_cancellable); + + result = g_dbus_proxy_call_finish (priv->introspect_proxy, res, &error); + + if (!result) { + char *reason2 = g_strdup_printf ("introspect failed with %s", error->message); + check_bluez_and_try_setup_final_step (self, 0, reason2); + g_error_free (error); + g_free (reason2); + return; + } + + g_variant_get (result, "(&s)", &xml_data); + + /* might not be the best approach to detect the version, but it's good enough in practice. */ + if (strstr (xml_data, "org.freedesktop.DBus.ObjectManager")) + bluez_version = 5; + else if (strstr (xml_data, BLUEZ4_MANAGER_INTERFACE)) + bluez_version = 4; + else + reason = "unexpected introspect result"; + + g_variant_unref (result); + + check_bluez_and_try_setup_final_step (self, bluez_version, reason); +} + +static void +check_bluez_and_try_setup_on_new_proxy (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezManager *self = async_data_unpack (user_data); + NMBluezManagerPrivate *priv; + GError *error = NULL; + + if (!self) + return; + + priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->introspect_proxy); + g_return_if_fail (!g_cancellable_is_cancelled (priv->async_cancellable)); + g_return_if_fail (!priv->bluez_version); + + priv->introspect_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->introspect_proxy) { + char *reason = g_strdup_printf ("bluez error creating dbus proxy: %s", error->message); + check_bluez_and_try_setup_final_step (self, 0, reason); + g_error_free (error); + g_free (reason); + return; + } + + g_dbus_proxy_call (priv->introspect_proxy, + "Introspect", + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + priv->async_cancellable, + check_bluez_and_try_setup_do_introspect, + async_data_pack (self)); +} + +static void +check_bluez_and_try_setup (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->bluez_version); + + /* there should be no ongoing detection. Anyway, cleanup_checking. */ + cleanup_checking (self, FALSE); + + priv->async_cancellable = g_cancellable_new (); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + BLUEZ_SERVICE, + "/", + DBUS_INTERFACE_INTROSPECTABLE, + priv->async_cancellable, + check_bluez_and_try_setup_on_new_proxy, + async_data_pack (self)); +} + + void nm_bluez_manager_query_devices (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - GHashTableIter iter; - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - if (nm_bluez_device_get_usable (device)) - emit_bdaddr_added (self, device); + switch (priv->bluez_version) { + case 4: + nm_bluez4_manager_query_devices (priv->manager4); + break; + case 5: + nm_bluez5_manager_query_devices (priv->manager5); + break; + default: + /* the proxy implementation does nothing in this case. */ + break; } } -static void -remove_device (NMBluezManager *self, NMBluezDevice *device) -{ - if (nm_bluez_device_get_usable (device)) { - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); - } - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); -} - -static void -remove_all_devices (NMBluezManager *self) -{ - GHashTableIter iter; - NMBluezDevice *device; - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - g_hash_table_iter_steal (&iter); - remove_device (self, device); - g_object_unref (device); - } -} - -static void -device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self) -{ - gboolean usable = nm_bluez_device_get_usable (device); - - nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", - nm_bluez_device_get_path (device), - usable ? "usable" : "unusable"); - - if (usable) { - nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", - nm_bluez_device_get_path (device), - nm_bluez_device_get_address (device)); - emit_bdaddr_added (self, device); - } else - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); -} - -static void -device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - nm_log_dbg (LOGD_BT, "(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); - if (!success) - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); -} - -static void -device_added (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - - device = nm_bluez_device_new (path, priv->provider); - g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); - g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); - - nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); -} - -static void -device_removed (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - - nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); - - device = g_hash_table_lookup (priv->devices, path); - if (device) { - g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); - remove_device (NM_BLUEZ_MANAGER (self), device); - g_object_unref (device); - } -} - -static void -object_manager_g_signal (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - NMBluezManager *self) -{ - GVariant *variant; - const gchar *path; - - if (!strcmp (signal_name, "InterfacesRemoved")) { - const gchar **ifaces; - gsize i, length; - - g_variant_get (parameters, "(&o*)", &path, &variant); - - ifaces = g_variant_get_strv (variant, &length); - - for (i = 0; i < length; i++) { - if (!strcmp (ifaces[i], BLUEZ_DEVICE_INTERFACE)) { - device_removed (proxy, path, self); - break; - } - } - - g_free (ifaces); - - } else if (!strcmp (signal_name, "InterfacesAdded")) { - g_variant_get (parameters, "(&o*)", &path, &variant); - - if (g_variant_lookup_value (variant, BLUEZ_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) - device_added (proxy, path, self); - } -} - -static void -get_managed_objects_cb (GDBusProxy *proxy, - GAsyncResult *res, - NMBluezManager *self) -{ - GVariant *variant, *ifaces; - GVariantIter i; - GError *error = NULL; - const char *path; - - variant = g_dbus_proxy_call_finish (proxy, res, &error); - - if (!variant) { - if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) - nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?"); - else { - nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", - error && error->message ? error->message : "(unknown)"); - } - g_clear_error (&error); - return; - } - g_variant_iter_init (&i, g_variant_get_child_value (variant, 0)); - while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { - if (g_variant_lookup_value (ifaces, BLUEZ_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) { - device_added (proxy, path, self); - } - } - - g_variant_unref (variant); -} - -static void -on_proxy_acquired (GObject *object, - GAsyncResult *res, - NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - - priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->proxy) { - nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - return; - } - - /* Get already managed devices. */ - g_dbus_proxy_call (priv->proxy, "GetManagedObjects", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) get_managed_objects_cb, - self); - - g_signal_connect (priv->proxy, "g-signal", - G_CALLBACK (object_manager_g_signal), self); -} - -static void -bluez_connect (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - g_return_if_fail (priv->proxy == NULL); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - OBJECT_MANAGER_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - self); -} - -static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); - - /* Can't handle the signal if its not from the Bluez */ - if (strcmp (BLUEZ_SERVICE, name)) - return; - - if (old_owner_good && !new_owner_good) { - if (priv->devices) - remove_all_devices (self); - } -} - -static void -bluez_cleanup (NMBluezManager *self, gboolean do_signal) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - - if (do_signal) - remove_all_devices (self); - else - g_hash_table_remove_all (priv->devices); -} - -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusGConnection *connection, - gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - - if (!connection) - bluez_cleanup (self, TRUE); - else - bluez_connect (self); -} - -/****************************************************************/ NMBluezManager * -nm_bluez_manager_get (NMConnectionProvider *provider) +nm_bluez_manager_new (NMConnectionProvider *provider) { - static NMBluezManager *singleton = NULL; + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (provider), NULL); - if (singleton) - return g_object_ref (singleton); + return g_object_new (NM_TYPE_BLUEZ_MANAGER, + NM_BLUEZ_MANAGER_PROVIDER, + provider, + NULL); +} - 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; +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (object); - return singleton; + switch (prop_id) { + case PROP_PROVIDER: + /* Construct only */ + priv->provider = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -nm_bluez_manager_init (NMBluezManager *self) +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (object); - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - self); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - self); - - bluez_connect (self); - - priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, g_object_unref); + switch (prop_id) { + case PROP_PROVIDER: + g_value_set_object (value, priv->provider); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } + static void dispose (GObject *object) { NMBluezManager *self = NM_BLUEZ_MANAGER (object); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - bluez_cleanup (self, FALSE); + g_clear_object (&priv->provider); - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - priv->dbus_mgr = NULL; + if (priv->manager4) { + g_signal_handlers_disconnect_by_func (priv->manager4, G_CALLBACK (manager_bdaddr_added_cb), self); + g_signal_handlers_disconnect_by_func (priv->manager4, G_CALLBACK (manager_bdaddr_removed_cb), self); + g_clear_object (&priv->manager4); + } + if (priv->manager5) { + g_signal_handlers_disconnect_by_func (priv->manager5, G_CALLBACK (manager_bdaddr_added_cb), self); + g_signal_handlers_disconnect_by_func (priv->manager5, G_CALLBACK (manager_bdaddr_removed_cb), self); + g_clear_object (&priv->manager5); } - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); + cleanup_checking (self, TRUE); + + priv->bluez_version = 0; } static void -finalize (GObject *object) +constructed (GObject *object) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (object); + NMBluezManager *self = NM_BLUEZ_MANAGER (object); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - g_hash_table_destroy (priv->devices); + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->constructed (object); - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->finalize (object); + g_return_if_fail (priv->provider); + + check_bluez_and_try_setup (self); +} + +static void +nm_bluez_manager_init (NMBluezManager *self) +{ } static void @@ -420,23 +481,34 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) /* virtual methods */ object_class->dispose = dispose; - object_class->finalize = finalize; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->constructed = constructed; + + g_object_class_install_property + (object_class, PROP_PROVIDER, + g_param_spec_object (NM_BLUEZ_MANAGER_PROVIDER, + "Provider", + "Connection Provider", + NM_TYPE_CONNECTION_PROVIDER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /* Signals */ signals[BDADDR_ADDED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), - NULL, NULL, NULL, - G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); signals[BDADDR_REMOVED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); } + diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h index 95e319c5e0..836416fa8c 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 - 2012 Red Hat, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. */ #ifndef NM_BLUEZ_MANAGER_H @@ -40,6 +40,8 @@ G_BEGIN_DECLS #define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" #define NM_BLUEZ_MANAGER_BDADDR_REMOVED "bdaddr-removed" +#define NM_BLUEZ_MANAGER_PROVIDER "provider" + typedef struct { GObject parent; } NMBluezManager; @@ -61,7 +63,7 @@ typedef struct { GType nm_bluez_manager_get_type (void); -NMBluezManager *nm_bluez_manager_get (NMConnectionProvider *provider); +NMBluezManager *nm_bluez_manager_new (NMConnectionProvider *provider); void nm_bluez_manager_query_devices (NMBluezManager *manager); diff --git a/src/bluez-manager/nm-bluez4-adapter.c b/src/bluez-manager/nm-bluez4-adapter.c index e9f806f71b..ad1786f02a 100644 --- a/src/bluez-manager/nm-bluez4-adapter.c +++ b/src/bluez-manager/nm-bluez4-adapter.c @@ -30,9 +30,9 @@ #include "nm-logging.h" -G_DEFINE_TYPE (NMBluezAdapter, nm_bluez_adapter, G_TYPE_OBJECT) +G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) -#define NM_BLUEZ_ADAPTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapterPrivate)) +#define NM_BLUEZ4_ADAPTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterPrivate)) typedef struct { char *path; @@ -44,7 +44,7 @@ typedef struct { /* Cached for devices */ NMConnectionProvider *provider; -} NMBluezAdapterPrivate; +} NMBluez4AdapterPrivate; enum { @@ -64,38 +64,40 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; -const char * -nm_bluez_adapter_get_path (NMBluezAdapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_ADAPTER (self), NULL); +static void device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device); - return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->path; +const char * +nm_bluez4_adapter_get_path (NMBluez4Adapter *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), NULL); + + return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->path; } const char * -nm_bluez_adapter_get_address (NMBluezAdapter *self) +nm_bluez4_adapter_get_address (NMBluez4Adapter *self) { - g_return_val_if_fail (NM_IS_BLUEZ_ADAPTER (self), NULL); + g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), NULL); - return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->address; + return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->address; } gboolean -nm_bluez_adapter_get_initialized (NMBluezAdapter *self) +nm_bluez4_adapter_get_initialized (NMBluez4Adapter *self) { - g_return_val_if_fail (NM_IS_BLUEZ_ADAPTER (self), FALSE); + g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), FALSE); - return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->initialized; + return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->initialized; } GSList * -nm_bluez_adapter_get_devices (NMBluezAdapter *self) +nm_bluez4_adapter_get_devices (NMBluez4Adapter *self) { GSList *devices = NULL; GHashTableIter iter; NMBluezDevice *device; - g_hash_table_iter_init (&iter, NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->devices); + g_hash_table_iter_init (&iter, NM_BLUEZ4_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); @@ -103,46 +105,64 @@ nm_bluez_adapter_get_devices (NMBluezAdapter *self) return devices; } +static void +emit_device_removed (NMBluez4Adapter *self, NMBluezDevice *device) +{ + nm_log_dbg (LOGD_BT, "(%s): bluez device now unusable", + nm_bluez_device_get_path (device)); + g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); +} + static void device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) { - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - gboolean usable = nm_bluez_device_get_usable (device); + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - 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)); + if (nm_bluez_device_get_usable (device)) { + nm_log_dbg (LOGD_BT, "(%s): bluez device now usable (device address is %s)", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); } else - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); + emit_device_removed (self, device); } static void device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) { - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); nm_log_dbg (LOGD_BT, "(%s): bluez device %s", nm_bluez_device_get_path (device), success ? "initialized" : "failed to initialize"); if (!success) - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); + device_do_remove (self, device); +} + +static void +device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + + if (g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device))) { + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); + + if (nm_bluez_device_get_usable (device)) + emit_device_removed (self, device); + + g_object_unref (device); + } } static void device_created (DBusGProxy *proxy, const char *path, gpointer user_data) { - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path, priv->provider); + device = nm_bluez_device_new (path, priv->provider, 4); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); @@ -153,27 +173,23 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data) static void device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) { - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_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, nm_bluez_device_get_path (device)); - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); - g_object_unref (device); - } + if (device) + device_do_remove (self, device); } static void get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); GHashTable *properties = NULL; GError *err = NULL; GValue *value; @@ -207,9 +223,9 @@ done: } static void -query_properties (NMBluezAdapter *self) +query_properties (NMBluez4Adapter *self) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); DBusGProxyCall *call; call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", @@ -224,20 +240,20 @@ query_properties (NMBluezAdapter *self) /***********************************************************/ -NMBluezAdapter * -nm_bluez_adapter_new (const char *path, NMConnectionProvider *provider) +NMBluez4Adapter * +nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider) { - NMBluezAdapter *self; - NMBluezAdapterPrivate *priv; + NMBluez4Adapter *self; + NMBluez4AdapterPrivate *priv; DBusGConnection *connection; - self = (NMBluezAdapter *) g_object_new (NM_TYPE_BLUEZ_ADAPTER, - NM_BLUEZ_ADAPTER_PATH, path, - NULL); + self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, + NM_BLUEZ4_ADAPTER_PATH, path, + NULL); if (!self) return NULL; - priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); priv->provider = provider; @@ -246,7 +262,7 @@ nm_bluez_adapter_new (const char *path, NMConnectionProvider *provider) priv->proxy = dbus_g_proxy_new_for_name (connection, BLUEZ_SERVICE, priv->path, - BLUEZ_ADAPTER_INTERFACE); + BLUEZ4_ADAPTER_INTERFACE); dbus_g_proxy_add_signal (priv->proxy, "DeviceCreated", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); @@ -263,48 +279,51 @@ nm_bluez_adapter_new (const char *path, NMConnectionProvider *provider) } static void -nm_bluez_adapter_init (NMBluezAdapter *self) +nm_bluez4_adapter_init (NMBluez4Adapter *self) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, g_object_unref); + NULL, NULL); +} + +static gboolean +_find_all (gpointer key, gpointer value, gpointer user_data) +{ + return TRUE; } static void dispose (GObject *object) { - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (object); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - GHashTableIter iter; + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); 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); + while ((device = g_hash_table_find (priv->devices, _find_all, NULL))) + device_do_remove (self, device); - G_OBJECT_CLASS (nm_bluez_adapter_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->dispose (object); } static void finalize (GObject *object) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (object); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (object); g_hash_table_destroy (priv->devices); g_free (priv->address); g_free (priv->path); g_object_unref (priv->proxy); - G_OBJECT_CLASS (nm_bluez_adapter_parent_class)->finalize (object); + G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object); } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (object); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (object); switch (prop_id) { case PROP_PATH: @@ -323,7 +342,7 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (object); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (object); switch (prop_id) { case PROP_PATH: @@ -337,11 +356,11 @@ set_property (GObject *object, guint prop_id, } static void -nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) +nm_bluez4_adapter_class_init (NMBluez4AdapterClass *config_class) { GObjectClass *object_class = G_OBJECT_CLASS (config_class); - g_type_class_add_private (config_class, sizeof (NMBluezAdapterPrivate)); + g_type_class_add_private (config_class, sizeof (NMBluez4AdapterPrivate)); /* virtual methods */ object_class->get_property = get_property; @@ -352,7 +371,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) /* Properties */ g_object_class_install_property (object_class, PROP_PATH, - g_param_spec_string (NM_BLUEZ_ADAPTER_PATH, + g_param_spec_string (NM_BLUEZ4_ADAPTER_PATH, "DBus Path", "DBus Path", NULL, @@ -360,7 +379,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) g_object_class_install_property (object_class, PROP_ADDRESS, - g_param_spec_string (NM_BLUEZ_ADAPTER_ADDRESS, + g_param_spec_string (NM_BLUEZ4_ADAPTER_ADDRESS, "Address", "Address", NULL, @@ -370,7 +389,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) signals[INITIALIZED] = g_signal_new ("initialized", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezAdapterClass, initialized), + G_STRUCT_OFFSET (NMBluez4AdapterClass, initialized), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); @@ -378,7 +397,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) signals[DEVICE_ADDED] = g_signal_new ("device-added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezAdapterClass, device_added), + G_STRUCT_OFFSET (NMBluez4AdapterClass, device_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); @@ -386,7 +405,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) signals[DEVICE_REMOVED] = g_signal_new ("device-removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezAdapterClass, device_removed), + G_STRUCT_OFFSET (NMBluez4AdapterClass, device_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); diff --git a/src/bluez-manager/nm-bluez4-adapter.h b/src/bluez-manager/nm-bluez4-adapter.h index 8e53b40d1b..454ca557eb 100644 --- a/src/bluez-manager/nm-bluez4-adapter.h +++ b/src/bluez-manager/nm-bluez4-adapter.h @@ -18,8 +18,8 @@ * Copyright (C) 2009 - 2012 Red Hat, Inc. */ -#ifndef NM_BLUEZ_ADAPTER_H -#define NM_BLUEZ_ADAPTER_H +#ifndef NM_BLUEZ4_ADAPTER_H +#define NM_BLUEZ4_ADAPTER_H #include #include @@ -27,43 +27,43 @@ #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)) -#define NM_BLUEZ_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapterClass)) -#define NM_IS_BLUEZ_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_ADAPTER)) -#define NM_IS_BLUEZ_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_ADAPTER)) -#define NM_BLUEZ_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapterClass)) +#define NM_TYPE_BLUEZ4_ADAPTER (nm_bluez4_adapter_get_type ()) +#define NM_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4Adapter)) +#define NM_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) +#define NM_IS_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ4_ADAPTER)) +#define NM_IS_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_ADAPTER)) +#define NM_BLUEZ4_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) -#define NM_BLUEZ_ADAPTER_PATH "path" -#define NM_BLUEZ_ADAPTER_ADDRESS "address" +#define NM_BLUEZ4_ADAPTER_PATH "path" +#define NM_BLUEZ4_ADAPTER_ADDRESS "address" typedef struct { GObject parent; -} NMBluezAdapter; +} NMBluez4Adapter; typedef struct { GObjectClass parent; /* virtual functions */ - void (*initialized) (NMBluezAdapter *self, gboolean success); + void (*initialized) (NMBluez4Adapter *self, gboolean success); - void (*device_added) (NMBluezAdapter *self, NMBluezDevice *device); + void (*device_added) (NMBluez4Adapter *self, NMBluezDevice *device); - void (*device_removed) (NMBluezAdapter *self, NMBluezDevice *device); -} NMBluezAdapterClass; + void (*device_removed) (NMBluez4Adapter *self, NMBluezDevice *device); +} NMBluez4AdapterClass; -GType nm_bluez_adapter_get_type (void); +GType nm_bluez4_adapter_get_type (void); -NMBluezAdapter *nm_bluez_adapter_new (const char *path, - NMConnectionProvider *provider); +NMBluez4Adapter *nm_bluez4_adapter_new (const char *path, + NMConnectionProvider *provider); -const char *nm_bluez_adapter_get_path (NMBluezAdapter *self); +const char *nm_bluez4_adapter_get_path (NMBluez4Adapter *self); -const char *nm_bluez_adapter_get_address (NMBluezAdapter *self); +const char *nm_bluez4_adapter_get_address (NMBluez4Adapter *self); -gboolean nm_bluez_adapter_get_initialized (NMBluezAdapter *self); +gboolean nm_bluez4_adapter_get_initialized (NMBluez4Adapter *self); -GSList *nm_bluez_adapter_get_devices (NMBluezAdapter *self); +GSList *nm_bluez4_adapter_get_devices (NMBluez4Adapter *self); -#endif /* NM_BLUEZ_ADAPTER_H */ +#endif /* NM_BLUEZ4_ADAPTER_H */ diff --git a/src/bluez-manager/nm-bluez4-manager.c b/src/bluez-manager/nm-bluez4-manager.c index 882028cd04..58162f0a81 100644 --- a/src/bluez-manager/nm-bluez4-manager.c +++ b/src/bluez-manager/nm-bluez4-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 - 2012 Red Hat, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. */ #include @@ -27,6 +27,7 @@ #include "nm-logging.h" #include "nm-dbus-glib-types.h" #include "nm-bluez-manager.h" +#include "nm-bluez4-manager.h" #include "nm-bluez4-adapter.h" #include "nm-dbus-manager.h" #include "nm-bluez-common.h" @@ -40,12 +41,12 @@ typedef struct { DBusGProxy *proxy; - NMBluezAdapter *adapter; -} NMBluezManagerPrivate; + NMBluez4Adapter *adapter; +} NMBluez4ManagerPrivate; -#define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) +#define NM_BLUEZ4_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerPrivate)) -G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT) +G_DEFINE_TYPE (NMBluez4Manager, nm_bluez4_manager, G_TYPE_OBJECT) enum { BDADDR_ADDED, @@ -58,7 +59,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; static void -emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) +emit_bdaddr_added (NMBluez4Manager *self, NMBluezDevice *device) { g_signal_emit (self, signals[BDADDR_ADDED], 0, device, @@ -69,30 +70,30 @@ emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) } void -nm_bluez_manager_query_devices (NMBluezManager *self) +nm_bluez4_manager_query_devices (NMBluez4Manager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); GSList *devices, *iter; if (!priv->adapter) return; - devices = nm_bluez_adapter_get_devices (priv->adapter); + devices = nm_bluez4_adapter_get_devices (priv->adapter); for (iter = devices; iter; iter = g_slist_next (iter)) emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); g_slist_free (devices); } static void -device_added (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) +device_added (NMBluez4Adapter *adapter, NMBluezDevice *device, gpointer user_data) { - emit_bdaddr_added (NM_BLUEZ_MANAGER (user_data), device); + emit_bdaddr_added (NM_BLUEZ4_MANAGER (user_data), device); } static void -device_removed (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) +device_removed (NMBluez4Adapter *adapter, NMBluezDevice *device, gpointer user_data) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); g_signal_emit (self, signals[BDADDR_REMOVED], 0, nm_bluez_device_get_address (device), @@ -100,15 +101,15 @@ device_removed (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_da } static void -adapter_initialized (NMBluezAdapter *adapter, gboolean success, gpointer user_data) +adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_data) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); if (success) { GSList *devices, *iter; - devices = nm_bluez_adapter_get_devices (adapter); + devices = nm_bluez4_adapter_get_devices (adapter); for (iter = devices; iter; iter = g_slist_next (iter)) emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); g_slist_free (devices); @@ -122,15 +123,15 @@ adapter_initialized (NMBluezAdapter *adapter, gboolean success, gpointer user_da } static void -adapter_removed (DBusGProxy *proxy, const char *path, NMBluezManager *self) +adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - if (priv->adapter && !strcmp (path, nm_bluez_adapter_get_path (priv->adapter))) { - if (nm_bluez_adapter_get_initialized (priv->adapter)) { + if (priv->adapter && !strcmp (path, nm_bluez4_adapter_get_path (priv->adapter))) { + if (nm_bluez4_adapter_get_initialized (priv->adapter)) { GSList *devices, *iter; - devices = nm_bluez_adapter_get_devices (priv->adapter); + devices = nm_bluez4_adapter_get_devices (priv->adapter); for (iter = devices; iter; iter = g_slist_next (iter)) { NMBluezDevice *device = NM_BLUEZ_DEVICE (iter->data); @@ -147,13 +148,13 @@ adapter_removed (DBusGProxy *proxy, const char *path, NMBluezManager *self) } static void -default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *self) +default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); const char *cur_path = NULL; if (priv->adapter) - cur_path = nm_bluez_adapter_get_path (priv->adapter); + cur_path = nm_bluez4_adapter_get_path (priv->adapter); if (cur_path) { if (!path || strcmp (path, cur_path)) { @@ -167,7 +168,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->provider); + priv->adapter = nm_bluez4_adapter_new (path, priv->provider); g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); } } @@ -175,8 +176,8 @@ default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *se static void default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); const char *default_adapter = NULL; GError *err = NULL; @@ -198,9 +199,9 @@ default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) } static void -query_default_adapter (NMBluezManager *self) +query_default_adapter (NMBluez4Manager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); DBusGProxyCall *call; call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", @@ -212,9 +213,9 @@ query_default_adapter (NMBluezManager *self) } static void -bluez_connect (NMBluezManager *self) +bluez_connect (NMBluez4Manager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); DBusGConnection *connection; g_return_if_fail (priv->proxy == NULL); @@ -226,7 +227,7 @@ bluez_connect (NMBluezManager *self) priv->proxy = dbus_g_proxy_new_for_name (connection, BLUEZ_SERVICE, BLUEZ_MANAGER_PATH, - BLUEZ_MANAGER_INTERFACE); + BLUEZ4_MANAGER_INTERFACE); dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); @@ -248,8 +249,8 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, const char *new_owner, gpointer user_data) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); gboolean old_owner_good = (old_owner && strlen (old_owner)); gboolean new_owner_good = (new_owner && strlen (new_owner)); @@ -269,9 +270,9 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, } static void -bluez_cleanup (NMBluezManager *self, gboolean do_signal) +bluez_cleanup (NMBluez4Manager *self, gboolean do_signal) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); if (priv->proxy) { g_object_unref (priv->proxy); @@ -289,7 +290,7 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, DBusGConnection *connection, gpointer user_data) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); if (!connection) bluez_cleanup (self, TRUE); @@ -299,27 +300,20 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, /****************************************************************/ -NMBluezManager * -nm_bluez_manager_get (NMConnectionProvider *provider) +NMBluez4Manager * +nm_bluez4_manager_new (NMConnectionProvider *provider) { - static NMBluezManager *singleton = NULL; + NMBluez4Manager *instance; - 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; + instance = g_object_new (NM_TYPE_BLUEZ4_MANAGER, NULL); + NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->provider = provider; + return instance; } static void -nm_bluez_manager_init (NMBluezManager *self) +nm_bluez4_manager_init (NMBluez4Manager *self) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); priv->dbus_mgr = nm_dbus_manager_get (); g_assert (priv->dbus_mgr); @@ -340,8 +334,8 @@ nm_bluez_manager_init (NMBluezManager *self) static void dispose (GObject *object) { - NMBluezManager *self = NM_BLUEZ_MANAGER (object); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); bluez_cleanup (self, FALSE); @@ -351,15 +345,15 @@ dispose (GObject *object) priv->dbus_mgr = NULL; } - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); } static void -nm_bluez_manager_class_init (NMBluezManagerClass *klass) +nm_bluez4_manager_class_init (NMBluez4ManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); + g_type_class_add_private (klass, sizeof (NMBluez4ManagerPrivate)); /* virtual methods */ object_class->dispose = dispose; @@ -369,7 +363,7 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), + G_STRUCT_OFFSET (NMBluez4ManagerClass, bdaddr_added), NULL, NULL, NULL, G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); @@ -378,7 +372,7 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), + G_STRUCT_OFFSET (NMBluez4ManagerClass, bdaddr_removed), NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); } diff --git a/src/bluez-manager/nm-bluez4-manager.h b/src/bluez-manager/nm-bluez4-manager.h new file mode 100644 index 0000000000..20e6c1bc18 --- /dev/null +++ b/src/bluez-manager/nm-bluez4-manager.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ4_MANAGER_H +#define NM_BLUEZ4_MANAGER_H + +#include +#include + +#include +#include "nm-connection-provider.h" + +G_BEGIN_DECLS + +#define NM_TYPE_BLUEZ4_MANAGER (nm_bluez4_manager_get_type ()) +#define NM_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4Manager)) +#define NM_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) +#define NM_IS_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ4_MANAGER)) +#define NM_IS_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_MANAGER)) +#define NM_BLUEZ4_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) + +typedef struct { + GObject parent; +} NMBluez4Manager; + +typedef struct { + GObjectClass parent; + + /* Virtual functions */ + void (*bdaddr_added) (NMBluez4Manager *manager, + const char *bdaddr, + const char *name, + const char *object_path, + guint uuids); + + void (*bdaddr_removed) (NMBluez4Manager *manager, + const char *bdaddr, + const char *object_path); +} NMBluez4ManagerClass; + +GType nm_bluez4_manager_get_type (void); + +NMBluez4Manager *nm_bluez4_manager_new (NMConnectionProvider *provider); + +void nm_bluez4_manager_query_devices (NMBluez4Manager *manager); + +#endif /* NM_BLUEZ4_MANAGER_H */ + diff --git a/src/bluez-manager/nm-bluez5-manager.c b/src/bluez-manager/nm-bluez5-manager.c new file mode 100644 index 0000000000..77e5bdd4ba --- /dev/null +++ b/src/bluez-manager/nm-bluez5-manager.c @@ -0,0 +1,436 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. + */ + +#include +#include +#include +#include + +#include "nm-logging.h" +#include "nm-bluez-manager.h" +#include "nm-bluez5-manager.h" +#include "nm-bluez-device.h" +#include "nm-bluez-common.h" + +#include "nm-dbus-manager.h" + +typedef struct { + NMDBusManager *dbus_mgr; + gulong name_owner_changed_id; + + NMConnectionProvider *provider; + + GDBusProxy *proxy; + + GHashTable *devices; +} NMBluez5ManagerPrivate; + +#define NM_BLUEZ5_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerPrivate)) + +G_DEFINE_TYPE (NMBluez5Manager, nm_bluez5_manager, G_TYPE_OBJECT) + +enum { + BDADDR_ADDED, + BDADDR_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self); +static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *self); + +static void +emit_bdaddr_added (NMBluez5Manager *self, NMBluezDevice *device) +{ + g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, + nm_bluez_device_get_address (device), + nm_bluez_device_get_name (device), + nm_bluez_device_get_path (device), + nm_bluez_device_get_capabilities (device)); +} + +void +nm_bluez5_manager_query_devices (NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + GHashTableIter iter; + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + emit_bdaddr_added (self, device); + } +} + +static void +remove_device (NMBluez5Manager *self, NMBluezDevice *device) +{ + if (nm_bluez_device_get_usable (device)) { + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); + } + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); +} + +static void +remove_all_devices (NMBluez5Manager *self) +{ + GHashTableIter iter; + NMBluezDevice *device; + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + g_hash_table_iter_steal (&iter); + remove_device (self, device); + g_object_unref (device); + } +} + +static void +device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *self) +{ + gboolean usable = nm_bluez_device_get_usable (device); + + nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", + nm_bluez_device_get_path (device), + usable ? "usable" : "unusable"); + + if (usable) { + nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); + emit_bdaddr_added (self, device); + } else + g_signal_emit (self, signals[BDADDR_REMOVED], 0, + nm_bluez_device_get_address (device), + nm_bluez_device_get_path (device)); +} + +static void +device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + nm_log_dbg (LOGD_BT, "(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); + if (!success) + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); +} + +static void +device_added (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + device = nm_bluez_device_new (path, priv->provider, 5); + g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); + + nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); +} + +static void +device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + + device = g_hash_table_lookup (priv->devices, path); + if (device) { + g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); + remove_device (NM_BLUEZ5_MANAGER (self), device); + g_object_unref (device); + } +} + +static void +object_manager_g_signal (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + NMBluez5Manager *self) +{ + GVariant *variant; + const gchar *path; + + if (!strcmp (signal_name, "InterfacesRemoved")) { + const gchar **ifaces; + gsize i, length; + + g_variant_get (parameters, "(&o*)", &path, &variant); + + ifaces = g_variant_get_strv (variant, &length); + + for (i = 0; i < length; i++) { + if (!strcmp (ifaces[i], BLUEZ5_DEVICE_INTERFACE)) { + device_removed (proxy, path, self); + break; + } + } + + g_free (ifaces); + + } else if (!strcmp (signal_name, "InterfacesAdded")) { + g_variant_get (parameters, "(&o*)", &path, &variant); + + if (g_variant_lookup_value (variant, BLUEZ5_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) + device_added (proxy, path, self); + } +} + +static void +get_managed_objects_cb (GDBusProxy *proxy, + GAsyncResult *res, + NMBluez5Manager *self) +{ + GVariant *variant, *ifaces; + GVariantIter i; + GError *error = NULL; + const char *path; + + variant = g_dbus_proxy_call_finish (proxy, res, &error); + + if (!variant) { + if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) + nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?"); + else { + nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", + error && error->message ? error->message : "(unknown)"); + } + g_clear_error (&error); + return; + } + g_variant_iter_init (&i, g_variant_get_child_value (variant, 0)); + while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { + if (g_variant_lookup_value (ifaces, BLUEZ5_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) { + device_added (proxy, path, self); + } + } + + g_variant_unref (variant); +} + +static void +on_proxy_acquired (GObject *object, + GAsyncResult *res, + NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + GError *error = NULL; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + /* Get already managed devices. */ + g_dbus_proxy_call (priv->proxy, "GetManagedObjects", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) get_managed_objects_cb, + self); + + g_signal_connect (priv->proxy, "g-signal", + G_CALLBACK (object_manager_g_signal), self); +} + +static void +bluez_connect (NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (priv->proxy == NULL); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + OBJECT_MANAGER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); +} + +static void +name_owner_changed_cb (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + /* Can't handle the signal if its not from the Bluez */ + if (strcmp (BLUEZ_SERVICE, name)) + return; + + if (old_owner_good && !new_owner_good) { + if (priv->devices) + remove_all_devices (self); + } +} + +static void +bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (do_signal) + remove_all_devices (self); + else + g_hash_table_remove_all (priv->devices); +} + +static void +dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + gpointer user_data) +{ + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); + + if (!connection) + bluez_cleanup (self, TRUE); + else + bluez_connect (self); +} + +/****************************************************************/ + +NMBluez5Manager * +nm_bluez5_manager_new (NMConnectionProvider *provider) +{ + NMBluez5Manager *instance = NULL; + + instance = g_object_new (NM_TYPE_BLUEZ5_MANAGER, NULL); + NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->provider = provider; + return instance; +} + +static void +nm_bluez5_manager_init (NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + priv->dbus_mgr = nm_dbus_manager_get (); + g_assert (priv->dbus_mgr); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (name_owner_changed_cb), + self); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + self); + + bluez_connect (self); + + priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, g_object_unref); +} + +static void +dispose (GObject *object) +{ + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + bluez_cleanup (self, FALSE); + + if (priv->dbus_mgr) { + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); + priv->dbus_mgr = NULL; + } + + G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (object); + + g_hash_table_destroy (priv->devices); + + G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->finalize (object); +} + +static void +nm_bluez5_manager_class_init (NMBluez5ManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMBluez5ManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* Signals */ + signals[BDADDR_ADDED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluez5ManagerClass, bdaddr_added), + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + + signals[BDADDR_REMOVED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluez5ManagerClass, bdaddr_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); +} diff --git a/src/bluez-manager/nm-bluez5-manager.h b/src/bluez-manager/nm-bluez5-manager.h new file mode 100644 index 0000000000..9cef5fd344 --- /dev/null +++ b/src/bluez-manager/nm-bluez5-manager.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ5_MANAGER_H +#define NM_BLUEZ5_MANAGER_H + +#include +#include + +#include +#include "nm-connection-provider.h" + +G_BEGIN_DECLS + +#define NM_TYPE_BLUEZ5_MANAGER (nm_bluez5_manager_get_type ()) +#define NM_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5Manager)) +#define NM_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) +#define NM_IS_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ5_MANAGER)) +#define NM_IS_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ5_MANAGER)) +#define NM_BLUEZ5_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) + +typedef struct { + GObject parent; +} NMBluez5Manager; + +typedef struct { + GObjectClass parent; + + /* Virtual functions */ + void (*bdaddr_added) (NMBluez5Manager *manager, + const char *bdaddr, + const char *name, + const char *object_path, + guint uuids); + + void (*bdaddr_removed) (NMBluez5Manager *manager, + const char *bdaddr, + const char *object_path); +} NMBluez5ManagerClass; + +GType nm_bluez5_manager_get_type (void); + +NMBluez5Manager *nm_bluez5_manager_new (NMConnectionProvider *provider); + +void nm_bluez5_manager_query_devices (NMBluez5Manager *manager); + +#endif /* NM_BLUEZ5_MANAGER_H */ + diff --git a/src/nm-manager.c b/src/nm-manager.c index 008c62d99a..810f5a15f0 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4458,7 +4458,7 @@ nm_manager_new (NMSettings *settings, G_CALLBACK (rfkill_manager_rfkill_changed_cb), singleton); - priv->bluez_mgr = nm_bluez_manager_get (NM_CONNECTION_PROVIDER (priv->settings)); + priv->bluez_mgr = nm_bluez_manager_new (NM_CONNECTION_PROVIDER (priv->settings)); g_signal_connect (priv->bluez_mgr, NM_BLUEZ_MANAGER_BDADDR_ADDED,