connect le device is ok 56/20356/2
authorGu Chaojie <chao.jie.gu@intel.com>
Fri, 9 May 2014 08:25:26 +0000 (16:25 +0800)
committerGu Chaojie <chao.jie.gu@intel.com>
Fri, 9 May 2014 08:27:07 +0000 (16:27 +0800)
Change-Id: I8555f67200c85af159ec0871d3aaf2201a8898e3
Signed-off-by: Gu Chaojie <chao.jie.gu@intel.com>
capi/bluetooth.c
include/bluetooth.h
include/bluez.h
lib/bluez.c
test/bluez-capi-test.c

index cc06cb5..84f0ee7 100644 (file)
@@ -52,6 +52,16 @@ static void profile_connect_callback(bluez_device_t *device,
 static void profile_disconnect_callback(bluez_device_t *device,
                                        enum device_profile_state state);
 
+struct device_connect_cb_node {
+       bt_device_gatt_state_changed_cb cb;
+       void *user_data;
+};
+
+struct device_disconnect_cb_node {
+       bt_device_gatt_state_changed_cb cb;
+       void *user_data;
+};
+
 struct device_created_cb_node {
        bt_adapter_device_discovery_state_changed_cb cb;
        void *user_data;
@@ -158,6 +168,8 @@ struct hdp_set_data_received_cb_node {
        void *user_data;
 };
 
+static struct device_connect_cb_node *device_connect_node;
+static struct device_disconnect_cb_node *device_disconnect_node;
 static struct avrcp_repeat_mode_changed_node *avrcp_repeat_node;
 static struct avrcp_set_shuffle_mode_changed_node *avrcp_shuffle_node;
 static struct adapter_name_cb_node *adapter_name_node;
@@ -781,6 +793,60 @@ done:
        node->cb(BT_SUCCESS, discoverable_mode, node->user_data);
 }
 
+static void bluez_device_connect_changed(bluez_device_t *device,
+                                       enum device_state state,
+                                       gpointer user_data)
+{
+       struct device_connect_cb_node *data = user_data;
+
+       switch (state) {
+       case DEVICE_CONNECT_SUCCESS:
+               DBG("Connect device: %s", "DEVICE_CONNECT_SUCCESS");
+               break;
+       case DEVICE_NOT_READY:
+               DBG("Connect device: %s", "DEVICE_NOT_READY");
+               break;
+       case DEVICE_ALREADY_CONNECTED:
+               DBG("Connect device: %s", "DEVICE_ALREADY_CONNECTED");
+               break;
+       case DEVICE_CONNECT_FAILED:
+               DBG("Connect device: %s", "DEVICE_CONNECT_FAILED");
+               break;
+       case DEVICE_CONNECT_INPROGRESS:
+               DBG("Connect device: %s", "DEVICE_CONNECT_INPROGRESS");
+               break;
+       default:
+               ERROR("Unknown error code");
+               break;
+       }
+
+       if (data->cb)
+               data->cb(state, data->user_data);
+
+}
+
+static void bluez_device_disconnect_changed(bluez_device_t *device,
+                                       enum device_state state,
+                                       gpointer user_data)
+{
+       struct device_disconnect_cb_node *data = user_data;
+
+       switch (state) {
+       case DEVICE_DISCONNECT_SUCCESS:
+               DBG("Disconnect device: %s", "DEVICE_DISCONNECT_SUCCESS");
+               break;
+       case DEVICE_NOT_CONNECTED:
+               DBG("Disconnect device: %s", "DEVICE_NOT_CONNECTED");
+               break;
+       default:
+               ERROR("Unknown error code");
+               break;
+       }
+
+       if (data->cb)
+               data->cb(state, data->user_data);
+}
+
 static void _bt_update_bluetooth_callbacks(void)
 {
        DBG("default_adpater: %p", default_adapter);
@@ -841,6 +907,15 @@ static void _bt_update_bluetooth_callbacks(void)
                bluez_set_avrcp_shuffle_changed_cb(
                                        bluez_avrcp_shuffle_changed,
                                        avrcp_shuffle_node);
+       if (device_connect_node)
+               bluez_set_device_connect_changed_cb(
+                                       bluez_device_connect_changed,
+                                       device_connect_node);
+
+       if (device_disconnect_node)
+               bluez_set_device_disconnect_changed_cb(
+                                       bluez_device_disconnect_changed,
+                                       device_disconnect_node);
 }
 
 static void setup_bluez_lib(void)
@@ -4401,3 +4476,97 @@ int bt_hdp_unset_data_received_cb(void)
 
        return BT_SUCCESS;
 }
+
+int bt_device_connect_le(bt_device_gatt_state_changed_cb callback,
+                       const char *remote_address)
+{
+       bluez_device_t *device;
+
+       struct device_connect_cb_node *node_data = NULL;
+
+       DBG("");
+
+       if (initialized == false)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (default_adapter == NULL)
+               return BT_ERROR_ADAPTER_NOT_FOUND;
+
+       if (callback == NULL)
+               return BT_ERROR_INVALID_PARAMETER;
+
+       device = bluez_adapter_get_device_by_address(default_adapter,
+                                                       remote_address);
+       if (device == NULL)
+               return BT_ERROR_OPERATION_FAILED;
+
+       if (device_connect_node) {
+               DBG("device disconnect callback already set.");
+               return BT_ERROR_ALREADY_DONE;
+       }
+
+       node_data =
+               g_new0(struct device_connect_cb_node, 1);
+       if (node_data == NULL) {
+               ERROR("no memory");
+               return BT_ERROR_OUT_OF_MEMORY;
+       }
+
+       node_data->cb = callback;
+       node_data->user_data = NULL;
+
+       device_connect_node = node_data;
+
+       _bt_update_bluetooth_callbacks();
+
+       bluez_device_connect_le(device);
+
+       return BT_SUCCESS;
+}
+
+int bt_device_disconnect_le(bt_device_gatt_state_changed_cb callback,
+                       const char *remote_address)
+{
+       bluez_device_t *device;
+
+       struct device_disconnect_cb_node *node_data = NULL;
+
+       DBG("");
+
+       if (initialized == false)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (default_adapter == NULL)
+               return BT_ERROR_ADAPTER_NOT_FOUND;
+
+       if (callback == NULL)
+               return BT_ERROR_INVALID_PARAMETER;
+
+       device = bluez_adapter_get_device_by_address(default_adapter,
+                                                       remote_address);
+       if (device == NULL)
+               return BT_ERROR_OPERATION_FAILED;
+
+       if (device_disconnect_node) {
+               DBG("device disconnect callback already set.");
+               return BT_ERROR_ALREADY_DONE;
+       }
+
+       node_data =
+               g_new0(struct device_disconnect_cb_node, 1);
+       if (node_data == NULL) {
+               ERROR("no memory");
+               return BT_ERROR_OUT_OF_MEMORY;
+       }
+
+       node_data->cb = callback;
+       node_data->user_data = NULL;
+
+       device_disconnect_node = node_data;
+
+       _bt_update_bluetooth_callbacks();
+
+       bluez_device_disconnect_le(device);
+
+       return BT_SUCCESS;
+}
index 9d38f88..0caf335 100644 (file)
@@ -3744,6 +3744,74 @@ void bt_agent_pincode_cancel(bt_req_t *requestion);
 /**
  * @}
  */
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE
+ * @brief  Called when GATT connection state is changed.
+ * @param[in]  result  The connection result (1 - Connected 0 - Disconnected)
+ * @param[in]  user_data  The user data passed from the foreach function
+ * @see bt_device_connect_le()
+ * @see bt_device_disconnect_le()
+ */
+typedef void (*bt_device_gatt_state_changed_cb)(int result, void *user_data);
+
+/**
+ * * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE
+ * * @brief Connects to remote BLE device, asynchronously.
+ *
+ * @remarks A Connection can be destroyed by bt_device_disconnect_le()
+ *
+ * @param[in] callback  The result callback
+ * @param[in] address The address of the remote BLE device with
+ * which the connection should be created
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE  Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED  Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval #BT_ERROR_NOT_ENABLED  Not enabled
+ * @retval #BT_ERROR_RESOURCE_BUSY      Device or resource busy
+ * @retval #BT_ERROR_OPERATION_FAILED  Operation failed
+ *
+ * @pre The state of local Bluetooth must be #BT_ADAPTER_ENABLED with bt_adapter_enable()
+ * @pre The remote device must be discoverable with bt_adapter_start_device_discovery().
+ * @post This function invokes bt_device_gatt_state_changed_cb().
+ *
+ * @see bt_adapter_enable()
+ * @see bt_adapter_start_device_discovery()
+ */
+int bt_device_connect_le(bt_device_gatt_state_changed_cb callback,
+                       const char *address);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE
+ * @brief Disconnects remote BLE device, asynchronously.
+ *
+ * @remarks A Connection can be established by bt_device_connect_le()
+ *
+ * @param[in] callback  The result callback
+ * @param[in] address The address of the remote BLE device with
+ * which the connection should be created
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE  Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED  Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval #BT_ERROR_NOT_ENABLED  Not enabled
+ * @retval #BT_ERROR_RESOURCE_BUSY      Device or resource busy
+ * @retval #BT_ERROR_OPERATION_FAILED  Operation failed
+ *
+ * @pre The state of local Bluetooth must be #BT_ADAPTER_ENABLED
+ * with bt_adapter_enable()
+ * @pre The remote device must be discoverable with
+ * bt_adapter_start_device_discovery().
+ * @pre The remote device must be connected with bt_device_connect_le().
+ * @post This function invokes bt_device_gatt_state_changed_cb().
+ *
+ * @see bt_adapter_enable()
+ * @see bt_adapter_start_device_discovery()
+ */
+int bt_device_disconnect_le(bt_device_gatt_state_changed_cb callback,
+                       const char *address);
 
 /* SPP */
 typedef void (*bt_spp_new_connection_cb)(
index 729de8a..443ccb0 100644 (file)
@@ -399,6 +399,34 @@ enum device_profile_state {
        PROFILE_NOT_SUPPORTED
 };
 
+enum device_state {
+       DEVICE_DISCONNECT_SUCCESS,
+       DEVICE_CONNECT_SUCCESS,
+       DEVICE_ALREADY_CONNECTED,
+       DEVICE_CONNECT_FAILED,
+       DEVICE_CONNECT_INPROGRESS,
+       DEVICE_NOT_READY,
+       DEVICE_NOT_CONNECTED
+};
+
+typedef void (*device_connect_cb_t)(
+                               struct _bluez_device *device,
+                               enum device_state state,
+                               gpointer user_data);
+void bluez_set_device_connect_changed_cb(device_connect_cb_t cb,
+                                       gpointer user_data);
+
+void bluez_device_connect_le(struct _bluez_device *device);
+
+typedef void (*device_disconnect_cb_t)(
+                               struct _bluez_device *device,
+                               enum device_state state,
+                               gpointer user_data);
+void bluez_set_device_disconnect_changed_cb(device_disconnect_cb_t cb,
+                                       gpointer user_data);
+
+void bluez_device_disconnect_le(struct _bluez_device *device);
+
 typedef void (*profile_connect_cb_t)(
                                struct _bluez_device *device,
                                enum device_profile_state state);
index f371801..5319976 100644 (file)
@@ -145,6 +145,10 @@ static bluez_avrcp_target_cb_t avrcp_target_cb;
 static gpointer avrcp_target_cb_data;
 static bluez_audio_state_cb_t audio_state_cb;
 static gpointer audio_state_cb_data;
+static device_connect_cb_t dev_connect_cb;
+static gpointer dev_connect_data;
+static device_disconnect_cb_t dev_disconnect_cb;
+static gpointer dev_disconnect_data;
 
 static GDBusNodeInfo *introspection_data;
 static guint bt_register_avrcp_property(struct _bluez_adapter *adapter);
@@ -989,6 +993,20 @@ struct _bluez_agent *bluez_agent_get_agent(void)
        return this_agent;
 }
 
+void bluez_set_device_connect_changed_cb(device_connect_cb_t cb,
+                                       gpointer user_data)
+{
+       dev_connect_cb = cb;
+       dev_connect_data = user_data;
+}
+
+void bluez_set_device_disconnect_changed_cb(device_disconnect_cb_t cb,
+                                       gpointer user_data)
+{
+       dev_disconnect_cb = cb;
+       dev_disconnect_data = user_data;
+}
+
 void bluez_set_avrcp_repeat_changed_cb(bluez_avrcp_repeat_changed_cb_t cb,
                                                gpointer user_data)
 {
@@ -1958,6 +1976,16 @@ struct profile_disconnect_state_notify {
        profile_disconnect_cb_t cb;
 };
 
+struct device_connect_state_notify {
+       struct _bluez_device *device;
+       device_connect_cb_t cb;
+};
+
+struct device_disconnect_state_notify {
+       struct _bluez_device *device;
+       device_disconnect_cb_t cb;
+};
+
 static inline enum device_pair_state get_pairing_error_state(GError *error)
 {
        if (g_strrstr(error->message,
@@ -2793,3 +2821,128 @@ static guint bt_register_avrcp_property(struct _bluez_adapter *adapter)
 
        return rid;
 }
+
+static void bluez_device_connect_cb(GObject *source_object,
+                                               GAsyncResult *res,
+                                               gpointer user_data)
+{
+       GVariant *ret;
+       struct _bluez_device *device;
+       device_connect_cb_t device_connect_cb;
+       struct device_connect_state_notify *notify = user_data;
+       GError *error = NULL;
+
+       DBG("");
+
+       device = notify->device;
+       device_connect_cb = notify->cb;
+
+       if (device_connect_cb == NULL)
+               return;
+
+       ret = g_dbus_proxy_call_finish(device->proxy,
+                                       res, &error);
+
+       if (ret == NULL) {
+               if (g_strrstr(error->message,
+                               "org.bluez.Error.NotReady"))
+                       device_connect_cb(device, DEVICE_NOT_READY,
+                                       dev_connect_data);
+               else if (g_strrstr(error->message,
+                               "org.bluez.Error.AlreadyConnected"))
+                       device_connect_cb(device, DEVICE_ALREADY_CONNECTED,
+                                       dev_connect_data);
+               else if (g_strrstr(error->message,
+                               "org.bluez.Error.Failed"))
+                       device_connect_cb(device, DEVICE_CONNECT_FAILED,
+                                       dev_connect_data);
+               else if (g_strrstr(error->message,
+                               "org.bluez.Error.InProgress"))
+                       device_connect_cb(device, DEVICE_CONNECT_INPROGRESS,
+                                       dev_connect_data);
+               else
+                       DBG("error: %s", error->message);
+       } else {
+               device_connect_cb(device, DEVICE_CONNECT_SUCCESS,
+                               dev_connect_data);
+
+               g_variant_unref(ret);
+       }
+
+       g_free(notify);
+}
+
+void bluez_device_connect_le(struct _bluez_device *device)
+{
+       struct device_connect_state_notify *notify;
+
+       notify = g_try_new0(struct device_connect_state_notify, 1);
+       if (notify == NULL) {
+               ERROR("no memory");
+               return;
+       }
+
+       notify->device = device;
+       notify->cb = dev_connect_cb;
+
+       g_dbus_proxy_call(device->proxy,
+                       "Connect", NULL,
+                       0, -1, NULL,
+                       bluez_device_connect_cb, notify);
+
+}
+
+static void bluez_device_disconnect_cb(GObject *source_object,
+                                               GAsyncResult *res,
+                                               gpointer user_data)
+{
+       GVariant *ret;
+       struct _bluez_device *device;
+       device_disconnect_cb_t device_disconnect_cb;
+       struct device_disconnect_state_notify *notify = user_data;
+       GError *error = NULL;
+
+       DBG("");
+
+       device = notify->device;
+       device_disconnect_cb = notify->cb;
+
+       if (device_disconnect_cb == NULL)
+               return;
+
+       ret = g_dbus_proxy_call_finish(device->proxy,
+                                       res, &error);
+
+       if (ret == NULL) {
+               if (g_strrstr(error->message,
+                               "org.bluez.Error.NotConnected"))
+                       device_disconnect_cb(device, DEVICE_NOT_CONNECTED,
+                                       dev_disconnect_data);
+       } else {
+               device_disconnect_cb(device, DEVICE_DISCONNECT_SUCCESS,
+                               dev_disconnect_data);
+
+               g_variant_unref(ret);
+       }
+
+       g_free(notify);
+}
+
+void bluez_device_disconnect_le(struct _bluez_device *device)
+{
+       struct device_disconnect_state_notify *notify;
+
+       notify = g_try_new0(struct device_disconnect_state_notify, 1);
+       if (notify == NULL) {
+               ERROR("no memory");
+               return;
+       }
+
+       notify->device = device;
+       notify->cb = dev_disconnect_cb;
+
+       g_dbus_proxy_call(device->proxy,
+                       "Disconnect", NULL,
+                       0, -1, NULL,
+                       bluez_device_disconnect_cb, notify);
+}
index 52b518f..2651315 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "common.h"
 #include "bluetooth.h"
+#include "bluez.h"
 
 #define INPUT_SIZE 255
 
@@ -950,6 +951,24 @@ static int set_device_alias(const char *p1, const char *p2)
        return 0;
 }
 
+static void device_connect_callback(int result, void *user_data)
+{
+       DBG("device connect callback result is %d", result);
+}
+
+static int device_connect_le(const char *p1, const char *p2)
+{
+       int err;
+
+       err = bt_device_connect_le(device_connect_callback, p1);
+       if (err != BT_SUCCESS) {
+               ERROR("bt_device_connect_le error: %d", err);
+               return 0;
+       }
+
+       return 0;
+}
+
 static int hid_connect(const char *p1, const char *p2)
 {
        int err;
@@ -1084,13 +1103,31 @@ static int get_bonded_device_info(const char *p1, const char *p2)
        return 0;
 }
 
+static void device_disconnect_callback(int result, void *user_data)
+{
+       DBG("device disconnect callback result is %d", result);
+}
+
+static int device_disconnect_le(const char *p1, const char *p2)
+{
+       int err;
+
+       err = bt_device_disconnect_le(device_disconnect_callback, p1);
+       if (err != BT_SUCCESS) {
+               ERROR("bt_device_disconnect_le error: %d", err);
+               return 0;
+       }
+
+       return 0;
+}
+
 static int hid_disconnect(const char *p1, const char *p2)
 {
        int err;
 
        err = bt_hid_host_disconnect(p1);
        if (err != BT_SUCCESS) {
-               ERROR("bt_hid_host_connect error: %d", err);
+               ERROR("bt_hid_host_disconnect error: %d", err);
                return 0;
        }
 
@@ -1837,6 +1874,12 @@ struct {
        {"set_device_authorization", set_device_authorization,
                "Usage: set_device_authorization 70:F9:27:64:DF:65 1/0\n\tSet device authorization"},
 
+       {"device_connect_le", device_connect_le,
+               "Usage: device_connect_le 70:F9:27:64:DF:65\n\tConnect LE device"},
+
+       {"device_disconnect_le", device_disconnect_le,
+               "Usage: device_disconnect_le 70:F9:27:64:DF:65\n\tDisconnect LE device"},
+
        {"hid_connect", hid_connect,
                "Usage: hid_connect 70:F9:27:64:DF:65\n\tConnect HID profile"},