static void
adapter5_on_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
{
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
	GError *error;
	GVariant *v;

	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->adapter5, "g-properties-changed",
		                  G_CALLBACK (adapter5_on_properties_changed), self);

		/* Check adapter's powered state */
		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);

		priv->initialized = TRUE;
		g_signal_emit (self, signals[INITIALIZED], 0, TRUE);

		check_emit_usable (self);
	}

	g_object_unref (self);
}
static void
_internal_add_connection (NMBluezDevice *self, NMConnection *connection)
{
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);

	if (!g_slist_find (priv->connections, connection)) {
		priv->connections = g_slist_prepend (priv->connections, g_object_ref (connection));
		check_emit_usable (self);
	}
}
static void
properties_changed (GDBusProxy *proxy,
                    GVariant *changed_properties,
                    GStrv invalidated_properties,
                    gpointer user_data)
{
	NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);

	_set_properties (self, changed_properties);
	check_emit_usable (self);
}
static void
on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
{
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
	GError *error = NULL;

	priv->dbus_connection = g_bus_get_finish (res, &error);

	if (!priv->dbus_connection) {
		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);
	} else
		check_emit_usable (self);

	g_object_unref (self);
}
static void
cp_connection_removed (NMConnectionProvider *provider,
                       NMConnection *connection,
                       NMBluezDevice *self)
{
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);

	if (g_slist_find (priv->connections, connection)) {
		priv->connections = g_slist_remove (priv->connections, connection);
		if (priv->pan_connection == connection) {
			priv->pan_connection = NULL;
			g_clear_object (&priv->pan_connection_original);
		}
		g_object_unref (connection);
		check_emit_usable (self);
	}
}
static void
bluez4_property_changed (GDBusProxy *proxy,
                         const char *sender,
                         const char *signal_name,
                         GVariant   *parameters,
                         gpointer user_data)
{
	NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);

	if (g_strcmp0 (signal_name, "PropertyChanged") == 0) {
		const char *property = NULL;
		GVariant *v = NULL;

		g_variant_get (parameters, "(&sv)", &property, &v);
		_take_one_variant_property (self, property, v);
		check_emit_usable (self);
	}
}
static void
get_properties_cb (DBusGProxy *proxy, 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;
	const char **uuids;

	if (!dbus_g_proxy_end_call (proxy, 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)");
		g_error_free (err);
		g_signal_emit (self, signals[INITIALIZED], 0, FALSE);
		return;
	}

	value = g_hash_table_lookup (properties, "Address");
	priv->address = value ? g_value_dup_string (value) : NULL;

	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) {
		uuids = (const char **) g_value_get_boxed (value);
		priv->capabilities = convert_uuids_to_capabilities (uuids);
	} else
		priv->capabilities = NM_BT_CAPABILITY_NONE;

	g_hash_table_unref (properties);

	priv->initialized = TRUE;
	g_signal_emit (self, signals[INITIALIZED], 0, TRUE);

	check_emit_usable (self);
}
static void
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);
	GError *err = NULL;
	GVariant *v_properties, *v_dict;
	GVariantType *v_type;

	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);
		goto END;
	}

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

	g_variant_unref (v_properties);

	/* Check if any connections match this device */
	load_connections (self);

	priv->initialized = TRUE;
	g_signal_emit (self, signals[INITIALIZED], 0, TRUE);


	check_emit_usable (self);

END:
	g_object_unref (self);
}
static void
property_changed (DBusGProxy *proxy,
                  const char *property,
                  GValue *value,
                  gpointer user_data)
{
	NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data);
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
	const char *str;
	guint32 uint_val;
	gint int_val;

	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")) {
		uint_val = convert_uuids_to_capabilities ((const char **) g_value_get_boxed (value));
		if (priv->capabilities != uint_val) {
			priv->capabilities = uint_val;
			g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES);
		}
	}

	check_emit_usable (self);
}
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);
	GVariantIter i;
	const char *property;
	GVariant *v;

	g_variant_iter_init (&i, changed_properties);
	while (g_variant_iter_next (&i, "{&sv}", &property, &v)) {
		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;
		}
		g_variant_unref (v);
	}

	check_emit_usable (self);
}