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;
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;
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);
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)
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;
+}
/**
* @}
*/
+/**
+ * @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)(
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);
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);
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)
{
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,
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);
+}
#include "common.h"
#include "bluetooth.h"
+#include "bluez.h"
#define INPUT_SIZE 255
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;
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;
}
{"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"},