mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-02 00:40:11 +01:00
bluez: merge rework of BlueZ to detect BlueZ 4 vs. 5 at runtime (bgo #709412)
Before, you had to select at compile time to run BlueZ4 or BlueZ5. Now, both versions are enabled together and NM detects the actual version at runtime. The configure option --enable-bluez4 got removed. The advantage is now, that you can switch between the two versions of BlueZ without rebuilding NetworkManager. Note however, that you still must restart NetworkManager, because once a version is detected, it will not switch again as long as the process runs. Another advantage is that before not all code was build, and you had to build two configurations for testing. https://bugzilla.gnome.org/show_bug.cgi?id=709412 Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
commit
d5bc540150
14 changed files with 1411 additions and 842 deletions
13
configure.ac
13
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"
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <signal.h>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <signal.h>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
66
src/bluez-manager/nm-bluez4-manager.h
Normal file
66
src/bluez-manager/nm-bluez4-manager.h
Normal file
|
|
@ -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 <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <config.h>
|
||||
#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 */
|
||||
|
||||
436
src/bluez-manager/nm-bluez5-manager.c
Normal file
436
src/bluez-manager/nm-bluez5-manager.c
Normal file
|
|
@ -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 <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
66
src/bluez-manager/nm-bluez5-manager.h
Normal file
66
src/bluez-manager/nm-bluez5-manager.h
Normal file
|
|
@ -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 <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <config.h>
|
||||
#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 */
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue