diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h index 612962552f..26ef1e31a7 100644 --- a/src/bluez-manager/nm-bluez-common.h +++ b/src/bluez-manager/nm-bluez-common.h @@ -21,6 +21,9 @@ #ifndef NM_BLUEZ_COMMON_H #define NM_BLUEZ_COMMON_H +#define BLUETOOTH_CONNECT_DUN "dun" +#define BLUETOOTH_CONNECT_NAP "nap" + #define BLUEZ_SERVICE "org.bluez" #define BLUEZ_MANAGER_PATH "/" diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index ba7403addf..434c85ffd3 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -40,6 +41,8 @@ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) typedef struct { char *path; DBusGProxy *proxy; + DBusGProxy *type_proxy; + gboolean initialized; gboolean usable; @@ -50,6 +53,8 @@ typedef struct { gint rssi; gboolean connected; + char *rfcomm_iface; + NMConnectionProvider *provider; GSList *connections; } NMBluezDevicePrivate; @@ -246,6 +251,121 @@ cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) /***********************************************************/ +void +nm_bluez_device_call_disconnect (NMBluezDevice *self, gboolean dun) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (!priv->type_proxy) + return; + + if (dun) { + /* Don't ever pass NULL through dbus; rfcomm_iface + * might happen to be NULL for some reason. + */ + if (priv->rfcomm_iface) + dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", + G_TYPE_STRING, priv->rfcomm_iface, + G_TYPE_INVALID); + } else { + dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", + G_TYPE_INVALID); + } + + g_clear_object (&priv->type_proxy); +} + +static void +bluez_connect_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + NMBluezDevice *self = NM_BLUEZ_DEVICE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + char *device; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, + G_TYPE_STRING, &device, + G_TYPE_INVALID) == FALSE) + g_simple_async_result_take_error (result, error); + else if (!device || !strlen (device)) { + g_simple_async_result_set_error(result, G_IO_ERROR, G_IO_ERROR_FAILED, + "Invalid argument received"); + } else { + g_simple_async_result_set_op_res_gpointer (result, + g_strdup (device), + g_free); + priv->rfcomm_iface = device; + } + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + gboolean dun, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + DBusGConnection *connection; + + connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); + + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); + + priv->type_proxy = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + priv->path, + dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); + if (!priv->type_proxy) + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Unable to create proxy"); + else + dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", + bluez_connect_cb, + simple, + NULL, + 20000, + G_TYPE_STRING, dun ? BLUETOOTH_CONNECT_DUN : BLUETOOTH_CONNECT_NAP, + G_TYPE_INVALID); +} + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + const char *device; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (self), + nm_bluez_device_connect_async), + NULL); + + simple = (GSimpleAsyncResult *) result; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); + return device; +} + +/***********************************************************/ + static guint32 convert_uuids_to_capabilities (const char **strings) { @@ -469,6 +589,8 @@ 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); + g_clear_object (&priv->type_proxy); + G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); } @@ -480,6 +602,7 @@ finalize (GObject *object) g_free (priv->path); g_free (priv->address); g_free (priv->name); + g_free (priv->rfcomm_iface); g_object_unref (priv->proxy); G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index e659dce7ef..b49f56b5cb 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -23,6 +23,7 @@ #include #include +#include #include "nm-connection.h" #include "nm-connection-provider.h" @@ -77,5 +78,20 @@ gint nm_bluez_device_get_rssi (NMBluezDevice *self); gboolean nm_bluez_device_get_connected (NMBluezDevice *self); +void +nm_bluez_device_connect_async (NMBluezDevice *self, + gboolean dun, + GAsyncReadyCallback callback, + gpointer user_data); + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error); + +void +nm_bluez_device_call_disconnect (NMBluezDevice *self, + gboolean dun); + #endif /* NM_BLUEZ_DEVICE_H */ diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index 6a066c0eac..8b9c704f2f 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -26,6 +26,7 @@ #include #include +#include #include "nm-glib-compat.h" #include "nm-bluez-common.h" @@ -48,8 +49,6 @@ #define MM_OLD_DBUS_SERVICE "org.freedesktop.ModemManager" #define MM_NEW_DBUS_SERVICE "org.freedesktop.ModemManager1" -#define BLUETOOTH_DUN_UUID "dun" -#define BLUETOOTH_NAP_UUID "nap" G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) @@ -71,8 +70,6 @@ typedef struct { gboolean connected; gboolean have_iface; - DBusGProxy *type_proxy; - char *rfcomm_iface; NMModem *modem; guint32 timeout_id; @@ -711,18 +708,19 @@ check_connect_continue (NMDeviceBt *self) } static void -bluez_connect_cb (DBusGProxy *proxy, - DBusGProxyCall *call_id, +bluez_connect_cb (GObject *object, + GAsyncResult *res, void *user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); GError *error = NULL; - char *device; + const char *device; - if (dbus_g_proxy_end_call (proxy, call_id, &error, - G_TYPE_STRING, &device, - G_TYPE_INVALID) == FALSE) { + device = nm_bluez_device_connect_finish (NM_BLUEZ_DEVICE (object), + res, &error); + + if (!device) { nm_log_warn (LOGD_BT, "Error connecting with bluez: %s", error && error->message ? error->message : "(unknown)"); g_clear_error (&error); @@ -733,20 +731,11 @@ bluez_connect_cb (DBusGProxy *proxy, return; } - if (!device || !strlen (device)) { - nm_log_warn (LOGD_BT, "Invalid network device returned by bluez"); - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - } - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { g_free (priv->rfcomm_iface); - priv->rfcomm_iface = device; + priv->rfcomm_iface = g_strdup (device); } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { nm_device_set_ip_iface (NM_DEVICE (self), device); - g_free (device); } nm_log_dbg (LOGD_BT, "(%s): connect request successful", @@ -819,7 +808,6 @@ static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - DBusGConnection *bus; gboolean dun = FALSE; NMConnection *connection; @@ -843,28 +831,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) else g_assert_not_reached (); - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - - priv->type_proxy = dbus_g_proxy_new_for_name (bus, - BLUEZ_SERVICE, - nm_device_get_udi (device), - dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); - if (!priv->type_proxy) { - // FIXME: set a reason code - return NM_ACT_STAGE_RETURN_FAILURE; - } - nm_log_dbg (LOGD_BT, "(%s): requesting connection to the device", nm_device_get_iface (device)); /* Connect to the BT device */ - dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", - bluez_connect_cb, - device, - NULL, - 20000, - G_TYPE_STRING, dun ? BLUETOOTH_DUN_UUID : BLUETOOTH_NAP_UUID, - G_TYPE_INVALID); + nm_bluez_device_connect_async (priv->bt_device, dun, bluez_connect_cb, device); if (priv->timeout_id) g_source_remove (priv->timeout_id); @@ -915,11 +886,14 @@ static void deactivate (NMDevice *device) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + gboolean dun; + + dun = priv->bt_type == NM_BT_CAPABILITY_DUN; priv->have_iface = FALSE; priv->connected = FALSE; - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + if (dun) { if (priv->modem) { nm_modem_deactivate (priv->modem, device); @@ -934,28 +908,10 @@ deactivate (NMDevice *device) g_object_unref (priv->modem); priv->modem = NULL; } - - if (priv->type_proxy) { - /* Don't ever pass NULL through dbus; rfcomm_iface - * might happen to be NULL for some reason. - */ - if (priv->rfcomm_iface) { - dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", - G_TYPE_STRING, priv->rfcomm_iface, - G_TYPE_INVALID); - } - g_object_unref (priv->type_proxy); - priv->type_proxy = NULL; - } - } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { - if (priv->type_proxy) { - dbus_g_proxy_call_no_reply (priv->type_proxy, "Disconnect", - G_TYPE_INVALID); - g_object_unref (priv->type_proxy); - priv->type_proxy = NULL; - } } + nm_bluez_device_call_disconnect (priv->bt_device, dun); + if (priv->timeout_id) { g_source_remove (priv->timeout_id); priv->timeout_id = 0; @@ -1209,7 +1165,6 @@ dispose (GObject *object) } priv->dbus_mgr = NULL; - g_clear_object (&priv->type_proxy); g_clear_object (&priv->modem); g_clear_object (&priv->bt_device);