/*
- * Bluetooth-frwk
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Hocheol Seo <hocheol.seo@samsung.com>
- * Girishashok Joshi <girish.joshi@samsung.com>
- * Chanyeol Park <chanyeol.park@samsung.com>
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "bt-event-handler.h"
#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
+#define HID_DEVICE_UUID "00001124-0000-1000-8000-00805f9b43bf"
#define REPORTID_MOUSE 1
#define BT_HID_BUFFER_LEN 100
/* HIDP header masks */
-#define HIDP_HEADER_TRANS_MASK 0xf0
-#define HIDP_HEADER_PARAM_MASK 0x0f
+#define BT_HID_HEADER_TRANS_MASK 0xf0
+#define BT_HID_HEADER_PARAM_MASK 0x0f
/* HIDP transaction types */
-#define HIDP_TRANS_HANDSHAKE 0x00
-#define HIDP_TRANS_HID_CONTROL 0x10
-#define HIDP_TRANS_GET_REPORT 0x40
-#define HIDP_TRANS_SET_REPORT 0x50
-#define HIDP_TRANS_GET_PROTOCOL 0x60
-#define HIDP_TRANS_SET_PROTOCOL 0x70
-#define HIDP_TRANS_GET_IDLE 0x80
-#define HIDP_TRANS_SET_IDLE 0x90
-#define HIDP_TRANS_DATA 0xa0
-#define HIDP_TRANS_DATC 0xb0
-
-#define HIDP_DATA_RTYPE_INPUT 0x01
-#define HIDP_DATA_RTYPE_OUTPUT 0x02
-
-#define HIDP_HSHK_SUCCESSFUL 0x00
-#define HIDP_HSHK_NOT_READY 0x01
-#define HIDP_HSHK_ERR_INVALID_REPORT_ID 0x02
-#define HIDP_HSHK_ERR_UNSUPPORTED_REQUEST 0x03
-#define HIDP_HSHK_ERR_INVALID_PARAMETER 0x04
-#define HIDP_HSHK_ERR_UNKNOWN 0x0E
-#define HIDP_HSHK_ERR_FATAL 0x0F
-
-typedef struct {
- guint object_id;
- gchar *path;
- int id;
- char *uuid;
- GSList *device_list;
-} hid_info_t;
+#define BT_HID_TRANS_HANDSHAKE 0x00
+#define BT_HID_TRANS_HID_CONTROL 0x10
+#define BT_HID_TRANS_GET_REPORT 0x40
+#define BT_HID_TRANS_SET_REPORT 0x50
+#define BT_HID_TRANS_GET_PROTOCOL 0x60
+#define BT_HID_TRANS_SET_PROTOCOL 0x70
+#define BT_HID_TRANS_GET_IDLE 0x80
+#define BT_HID_TRANS_SET_IDLE 0x90
+#define BT_HID_TRANS_DATA 0xa0
+#define BT_HID_TRANS_DATC 0xb0
+
+#define BT_HID_DATA_RTYPE_INPUT 0x01
+#define BT_HID_DATA_RTYPE_OUTPUT 0x02
+
+#define BT_HID_HSHK_SUCCESSFUL 0x00
+#define BT_HID_HSHK_NOT_READY 0x01
+#define BT_HID_HSHK_ERR_INVALID_REPORT_ID 0x02
+#define BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST 0x03
+#define BT_HID_HSHK_ERR_INVALID_PARAMETER 0x04
+#define BT_HID_HSHK_ERR_UNKNOWN 0x0E
+#define BT_HID_HSHK_ERR_FATAL 0x0F
+
+#define BT_HID_SERVICE_NAME "org.bluez.hid_agent"
+#define BT_HID_AGENT_OBJECT_PATH "/org/bluez/hid_agent"
+#define BT_HID_SERVICE_INTERFACE "org.tizen.HidApp"
typedef struct {
int ctrl_fd;
guint disconnect_idle_id;
} hid_connected_device_info_t;
-struct reports{
+struct reports {
guint8 type;
guint8 rep_data[20];
-}__attribute__((__packed__));
+} __attribute__((__packed__));
-static hid_info_t *hid_info = NULL;
+static GSList *device_list;
/* Variable for privilege, only for write API,
before we should reduce time to bt-service dbus calling
static int privilege_token_send_key = 0;
static int privilege_token_reply = 0;
-static gboolean __hid_disconnect(hid_connected_device_info_t *info);
+static GVariant* __bt_hid_agent_dbus_send(const char *path,
+ const char *interface, const char *method,
+ GError **err, GVariant *parameters)
+{
+ GVariant *reply = NULL;
+ GDBusProxy *proxy = NULL;
+ GDBusConnection *conn = NULL;
+
+ conn = _bt_get_system_private_conn();
+ retv_if(conn == NULL, NULL);
+
+ proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL, BT_HID_SERVICE_NAME, path, interface, NULL, err);
+ if (proxy == NULL) {
+ BT_ERR("Unable to allocate new proxy");
+ return NULL;
+ }
+
+ reply = g_dbus_proxy_call_sync(proxy, method, parameters,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
+
+ g_object_unref(proxy);
+ return reply;
+}
static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
{
GSList *l;
- for ( l = hid_info->device_list; l != NULL; l = l->next) {
+ for (l = device_list; l != NULL; l = l->next) {
hid_connected_device_info_t *info = l->data;
- if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
+ if (strcasecmp((const char *)info->address, (const char *)remote_addr) == 0)
return info;
}
return NULL;
}
static void __hid_connected_cb(hid_connected_device_info_t *info,
- bt_event_info_t *event_info)
+ int result)
{
- bluetooth_hid_request_t conn_info;
+ bluetooth_device_address_t bd_addr;
+ bt_event_info_t *event_info = NULL;
+
+ event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
+ if (event_info == NULL)
+ return;
+
+ memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
+ _bt_convert_addr_string_to_type(bd_addr.addr, info->address);
- memset(&conn_info, 0x00, sizeof(bluetooth_hid_request_t));
- if (info->intr_fd != -1 && info->ctrl_fd == -1)
- conn_info.socket_fd = info->intr_fd;
- else
- conn_info.socket_fd = info->ctrl_fd;
- _bt_convert_addr_string_to_type (conn_info.device_addr.addr , info->address);
+ if (result == BLUETOOTH_ERROR_NONE)
+ BT_INFO_C("Connected [HID Device]");
- BT_INFO_C("Connected [HID Device]");
_bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
- BLUETOOTH_ERROR_NONE, &conn_info,
+ result, &bd_addr,
event_info->cb, event_info->user_data);
}
+static void __hid_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
+ gpointer user_data)
+
+{
+ int result;
+ GError *error = NULL;
+ GVariant *ret = NULL;
+ hid_connected_device_info_t info;
+ const char *path;
+
+ BT_DBG("+");
+
+ ret = g_dbus_proxy_call_finish(proxy, res, &error);
+ if (ret == NULL) {
+ g_dbus_error_strip_remote_error(error);
+ BT_ERR("Error : %s \n", error->message);
+
+ info.ctrl_fd = -1;
+ info.intr_fd = -1;
+
+ info.address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+
+ path = g_dbus_proxy_get_object_path(proxy);
+ _bt_convert_device_path_to_address(path, info.address);
+
+ if (g_strcmp0(error->message, "Already Connected") == 0) {
+ bluetooth_device_address_t dev_address = { {0} };
+ int ctrl = -1, intr = -1;
+
+ _bt_convert_addr_string_to_type(dev_address.addr,
+ info.address);
+ _bt_hid_device_get_fd(info.address, &ctrl, &intr);
+ if (ctrl != -1 && intr != -1)
+ _bt_hid_new_connection(&dev_address, ctrl, intr);
+ else
+ BT_ERR("fd is invalid.(ctrl=%d, intr=%d)", ctrl, intr);
+ } else {
+ if (g_strcmp0(error->message, "In Progress") == 0)
+ result = BLUETOOTH_ERROR_IN_PROGRESS;
+ else
+ result = BLUETOOTH_ERROR_INTERNAL;
+
+ __hid_connected_cb(&info, result);
+ }
+
+ g_free(info.address);
+ g_error_free(error);
+ } else {
+ g_variant_unref(ret);
+ }
+
+ if (proxy)
+ g_object_unref(proxy);
+
+ BT_DBG("-");
+}
+
static gboolean __hid_disconnect(hid_connected_device_info_t *info)
{
- bluetooth_hid_request_t disconn_info;
- int fd = info->ctrl_fd;
+ bluetooth_device_address_t bd_addr;
bt_event_info_t *event_info;
BT_INFO_C("Disconnected [HID Device]");
- hid_info->device_list = g_slist_remove(hid_info->device_list, info);
+ device_list = g_slist_remove(device_list, info);
if (info->ctrl_data_id > 0) {
g_source_remove(info->ctrl_data_id);
info->ctrl_data_id = 0;
info->intr_data_id = 0;
}
- if (info->intr_fd >= 0) {
- close(info->ctrl_fd);
- close(info->intr_fd);
- info->intr_fd = -1;
- info->ctrl_fd = -1;
- }
-
if (info->ctrl_data_io) {
g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
g_io_channel_unref(info->ctrl_data_io);
g_io_channel_unref(info->intr_data_io);
info->intr_data_io = NULL;
}
+ if (info->intr_fd >= 0) {
+ close(info->ctrl_fd);
+ close(info->intr_fd);
+ info->intr_fd = -1;
+ info->ctrl_fd = -1;
+ }
info->disconnect_idle_id = 0;
event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
- if (event_info == NULL)
- return FALSE;
+ if (event_info != NULL) {
+ memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
+ _bt_convert_addr_string_to_type(bd_addr.addr , info->address);
+ _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
+ BLUETOOTH_ERROR_NONE, &bd_addr,
+ event_info->cb, event_info->user_data);
+ }
- memset(&disconn_info, 0x00, sizeof(bluetooth_hid_request_t));
- disconn_info.socket_fd = fd;
- _bt_convert_addr_string_to_type (disconn_info.device_addr.addr , info->address);
- _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
- BLUETOOTH_ERROR_NONE, &disconn_info,
- event_info->cb, event_info->user_data);
- if (info->address)
- g_free(info->address);
+ g_free(info->address);
g_free(info);
- info = NULL;
- BT_DBG("-");
+
return FALSE;
}
-void __free_hid_info(hid_info_t *info)
+static gboolean __is_error_by_disconnect(GError *err)
{
- BT_DBG("");
-
- _bt_unregister_gdbus(info->object_id);
-
- while (info->device_list) {
- hid_connected_device_info_t *dev_info = NULL;
- dev_info = (hid_connected_device_info_t *)info->device_list->data;
-
- if (dev_info->disconnect_idle_id > 0) {
- BT_INFO("Disconnect idle still not process remove source");
- g_source_remove(dev_info->disconnect_idle_id);
- dev_info->disconnect_idle_id = 0;
- }
- __hid_disconnect(dev_info);
- }
-
- g_free(info->path);
- g_free(info->uuid);
- g_free(info);
+ return !g_strcmp0(err->message, "Connection reset by peer") ||
+ !g_strcmp0(err->message, "Connection timed out") ||
+ !g_strcmp0(err->message, "Software caused connection abort");
}
static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
{
hid_connected_device_info_t *info = data;
GIOStatus status = G_IO_STATUS_NORMAL;
- char buffer[20];
+ char buffer[BT_RFCOMM_BUFFER_LEN];
gsize len = 0;
GError *err = NULL;
guint8 header, type, param;
if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
- if (info->disconnect_idle_id > 0) {
- BT_INFO("Disconnect idle still not process remove source");
- g_source_remove(info->disconnect_idle_id);
- info->disconnect_idle_id = 0;
- }
+ if (info->disconnect_idle_id > 0) {
+ BT_INFO("Disconnect idle still not process remove source");
+ g_source_remove(info->disconnect_idle_id);
+ info->disconnect_idle_id = 0;
+ }
__hid_disconnect(info);
return FALSE;
}
+
status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
&len, &err);
if (status == G_IO_STATUS_NORMAL) {
BT_INFO("Parsing Data");
- bluetooth_hid_received_data_t data = {0};
+ bluetooth_hid_received_data_t recv_data = {0};
header = buffer[0];
- type = header & HIDP_HEADER_TRANS_MASK;
- param = header & HIDP_HEADER_PARAM_MASK;
+ type = header & BT_HID_HEADER_TRANS_MASK;
+ param = header & BT_HID_HEADER_PARAM_MASK;
BT_INFO("type %d , param %d", type, param);
BT_INFO("Data Reveived from %s" , info->address);
- data.address = g_strdup(info->address);
+
+ event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
+ if (event_info == NULL)
+ return FALSE;
+
+ recv_data.address = g_strdup(info->address);
switch (type) {
- case HIDP_TRANS_HANDSHAKE:
- BT_INFO("TRANS HANDSHAKE");
- data.type = HTYPE_TRANS_HANDSHAKE;
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- break;
- case HIDP_TRANS_HID_CONTROL:
- BT_INFO("HID CONTROL");
- data.type = HTYPE_TRANS_HID_CONTROL;
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- break;
- case HIDP_TRANS_DATA:
- BT_INFO("TRANS DATA");
- data.type = HTYPE_TRANS_DATA;
- if ( param & HIDP_DATA_RTYPE_INPUT) {
- BT_INFO("Input Report");
- data.param = PTYPE_DATA_RTYPE_INPUT;
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- }
- else {
- BT_INFO("Out Report");
- data.param = PTYPE_DATA_RTYPE_OUTPUT;
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- }
- break;
- case HIDP_TRANS_GET_REPORT: {
- BT_INFO("Get Report");
- data.type = HTYPE_TRANS_GET_REPORT;
- if (param & HIDP_DATA_RTYPE_INPUT) {
- BT_INFO("Input Report");
- data.param = PTYPE_DATA_RTYPE_INPUT;
- } else {
- BT_INFO("Output Report");
- data.param = PTYPE_DATA_RTYPE_OUTPUT;
- }
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- break;
- }
- case HIDP_TRANS_SET_REPORT: {
- BT_INFO("Set Report");
- data.type = HTYPE_TRANS_SET_REPORT;
- if (param & HIDP_DATA_RTYPE_INPUT) {
- BT_INFO("Input Report");
- data.param = PTYPE_DATA_RTYPE_INPUT;
- } else {
- BT_INFO("Output Report");
- data.param = PTYPE_DATA_RTYPE_OUTPUT;
- }
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- break;
- }
- case HIDP_TRANS_GET_PROTOCOL:{
- BT_INFO("Get_PROTOCOL");
- data.type = HTYPE_TRANS_GET_PROTOCOL;
- data.param = PTYPE_DATA_RTYPE_INPUT;
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- break;
+ case BT_HID_TRANS_HANDSHAKE:
+ BT_INFO("TRANS HANDSHAKE");
+ recv_data.type = HTYPE_TRANS_HANDSHAKE;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+
+ case BT_HID_TRANS_HID_CONTROL:
+ BT_INFO("HID CONTROL");
+ recv_data.type = HTYPE_TRANS_HID_CONTROL;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+
+ case BT_HID_TRANS_DATA:
+ BT_INFO("TRANS DATA");
+ recv_data.type = HTYPE_TRANS_DATA;
+ if (param & BT_HID_DATA_RTYPE_INPUT) {
+ BT_INFO("Input Report");
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ } else {
+ BT_INFO("Out Report");
+ recv_data.param = PTYPE_DATA_RTYPE_OUTPUT;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
}
- case HIDP_TRANS_SET_PROTOCOL:{
- BT_INFO("Set_PROTOCOL");
- data.type = HTYPE_TRANS_SET_PROTOCOL;
- data.param = PTYPE_DATA_RTYPE_INPUT;
- data.buffer_size = len;
- data.buffer = (char *) malloc(sizeof(char) * len);
- /* Fix : NULL_RETURNS */
- if (NULL == data.buffer) {
- BT_ERR("Failed to allocate memory");
- data.buffer_size = 0;
- } else {
- memcpy(data.buffer, buffer, len);
- }
- break;
+ break;
+
+ case BT_HID_TRANS_GET_REPORT: {
+ BT_INFO("Get Report");
+ recv_data.type = HTYPE_TRANS_GET_REPORT;
+ if (param & BT_HID_DATA_RTYPE_INPUT) {
+ BT_INFO("Input Report");
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ } else {
+ BT_INFO("Output Report");
+ recv_data.param = PTYPE_DATA_RTYPE_OUTPUT;
}
- default: {
- BT_INFO("unsupported HIDP control message");
- BT_ERR("Send Handshake Message");
- guint8 type = HIDP_TRANS_HANDSHAKE |
- HIDP_HSHK_ERR_UNSUPPORTED_REQUEST;
- data.type = HTYPE_TRANS_UNKNOWN;
- int fd = g_io_channel_unix_get_fd(chan);
- int bytes = write(fd, &type, sizeof(type));
- BT_INFO("Bytes Written %d", bytes);
- break;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+ }
+
+ case BT_HID_TRANS_SET_REPORT: {
+ BT_INFO("Set Report");
+ recv_data.type = HTYPE_TRANS_SET_REPORT;
+ if (param & BT_HID_DATA_RTYPE_INPUT) {
+ BT_INFO("Input Report");
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ } else {
+ BT_INFO("Output Report");
+ recv_data.param = PTYPE_DATA_RTYPE_OUTPUT;
}
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
}
- event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
- if (event_info == NULL)
- return FALSE;
- _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
- BLUETOOTH_ERROR_NONE, &data,
+ case BT_HID_TRANS_GET_PROTOCOL:{
+ BT_INFO("Get_PROTOCOL");
+ recv_data.type = HTYPE_TRANS_GET_PROTOCOL;
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+ }
+
+ case BT_HID_TRANS_SET_PROTOCOL:{
+ BT_INFO("Set_PROTOCOL");
+ recv_data.type = HTYPE_TRANS_SET_PROTOCOL;
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+ }
+
+ case BT_HID_TRANS_GET_IDLE:{
+ BT_INFO("Get_IDLE");
+ recv_data.type = HTYPE_TRANS_GET_IDLE;
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+ }
+
+ case BT_HID_TRANS_SET_IDLE:{
+ BT_INFO("Set_IDLE");
+ recv_data.type = HTYPE_TRANS_SET_IDLE;
+ recv_data.param = PTYPE_DATA_RTYPE_INPUT;
+ recv_data.buffer_size = len;
+ recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
+ memcpy(recv_data.buffer, buffer, len);
+ break;
+ }
+
+ default: {
+ BT_INFO("unsupported HIDP control message");
+ BT_ERR("Send Handshake Message");
+ guint8 type = BT_HID_TRANS_HANDSHAKE |
+ BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
+ recv_data.type = HTYPE_TRANS_UNKNOWN;
+ int fd = g_io_channel_unix_get_fd(chan);
+ int bytes = write(fd, &type, sizeof(type));
+ BT_INFO("Bytes Written %d", bytes);
+ break;
+ }
+ }
+
+ _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
+ BLUETOOTH_ERROR_NONE, &recv_data,
event_info->cb, event_info->user_data);
- if (data.buffer)
- g_free(data.buffer);
- if (data.address)
- g_free((char *)data.address);
+ if (recv_data.buffer)
+ g_free(recv_data.buffer);
+
+ if (recv_data.address)
+ g_free((char *)recv_data.address);
} else {
- BT_INFO("Error while reading data");
+ BT_ERR("Error while reading data %d [%s]", status, info->address);
+ if (err) {
+ BT_ERR("IO Channel read error [%s]", err->message);
+ if (status == G_IO_STATUS_ERROR &&
+ __is_error_by_disconnect(err)) {
+ BT_DBG("cond : %d", cond);
+ g_error_free(err);
+ __hid_disconnect(info);
+ return FALSE;
+ }
+ g_error_free(err);
+ } else if (status == G_IO_STATUS_EOF) {
+ __hid_disconnect(info);
+ return FALSE;
+ }
}
return TRUE;
}
-int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
+static void __free_hid_info(void *data)
+{
+ BT_DBG("");
+
+ hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
+
+ if (dev_info->disconnect_idle_id > 0) {
+ BT_INFO("Disconnect idle still not process remove source");
+ g_source_remove(dev_info->disconnect_idle_id);
+ dev_info->disconnect_idle_id = 0;
+ }
+ __hid_disconnect(dev_info);
+}
+
+int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
+{
+
+ int ret = BLUETOOTH_ERROR_NONE;
+ char *adapter_path;
+ GVariant *result = NULL;
+ GError *err = NULL;
+ GDBusConnection *conn;
+ GDBusProxy *server_proxy;
+ int index1 = 0;
+ int index2 = 0;
+ GUnixFDList *out_fd_list = NULL;
+ conn = _bt_get_system_private_conn();
+ retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+ adapter_path = _bt_get_device_object_path((char *)address);
+ retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
+ BT_INFO_C("Device : %s", adapter_path);
+ server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL, BT_BLUEZ_NAME,
+ adapter_path, "org.bluez.Input1", NULL, NULL);
+ g_free(adapter_path);
+
+ if (server_proxy == NULL) {
+ BT_ERR("Failed to get the network server proxy\n");
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &out_fd_list,
+ NULL,
+ &err);
+ if (result == NULL) {
+ if (err != NULL) {
+ g_dbus_error_strip_remote_error(err);
+ BT_ERR("INPUT server register Error: %s\n", err->message);
+ if (g_strcmp0(err->message, "Already Exists") == 0)
+ ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
+ else
+ ret = BLUETOOTH_ERROR_INTERNAL;
+
+ g_error_free(err);
+ }
+ } else {
+ g_variant_get(result, "(hh)", &index1, &index2);
+ int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
+ int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
+
+ *ctrl = fd1;
+ *intr = fd2;
+ g_object_unref(out_fd_list);
+ g_variant_unref(result);
+ }
+ g_object_unref(server_proxy);
+ return ret;
+}
+
+int _bt_hid_new_connection(bluetooth_device_address_t *addr,
+ int ctrl_fd, int intr_fd)
{
- hid_info_t *info = NULL;
hid_connected_device_info_t *dev_info = NULL;
- bt_event_info_t *event_info = NULL;
char address[18];
- info = hid_info;
+ char secure_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
- if (info == NULL)
- return -1;
_bt_convert_addr_type_to_string((char *)address, addr->addr);
- BT_INFO("Address [%s]", address);
+ _bt_convert_addr_string_to_secure_string(secure_addr, address);
+ BT_INFO("Address [%s]", secure_addr);
dev_info = __find_hid_info_with_address(address);
- if (dev_info == NULL) {
- dev_info = (hid_connected_device_info_t *)
- g_malloc0(sizeof(hid_connected_device_info_t));
- dev_info->intr_fd = -1;
- dev_info->ctrl_fd = -1;
- dev_info->intr_fd = fd;
- dev_info->address = g_strdup(address);
- dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
- g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
- g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
-
- dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- __received_cb, dev_info);
- hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
- } else {
- dev_info->ctrl_fd = fd;
- dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
- g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
- g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
-
- dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- __received_cb, dev_info);
- }
- if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1) {
- event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
- if (event_info)
- __hid_connected_cb(dev_info, event_info);
- }
+ if (dev_info != NULL)
+ __free_hid_info(dev_info);
+
+ dev_info = (hid_connected_device_info_t *)
+ g_malloc0(sizeof(hid_connected_device_info_t));
+
+ dev_info->ctrl_fd = ctrl_fd;
+ dev_info->intr_fd = intr_fd;
+ dev_info->address = g_strdup(address);
+ dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
+ dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
+ g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
+ g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
+ g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
+ g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
+ dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ __received_cb, dev_info);
+ dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ __received_cb, dev_info);
+ device_list = g_slist_append(device_list, dev_info);
+
+ __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
return 0;
}
-static hid_info_t *__register_method()
-{
- int object_id;
- hid_info_t *info = NULL;
- char *path = NULL;
- path = g_strdup_printf("/org/socket/server/%d", getpid());
- object_id = _bt_register_new_conn(path, new_hid_connection);
- if (object_id < 0) {
- return NULL;
- }
- info = g_new(hid_info_t, 1);
- info->object_id = (guint)object_id;
- info->path = path;
- info->id = 0;
- info->device_list = NULL;
+void _bt_hid_free_hid_info(void)
+{
+ g_slist_free_full(device_list, __free_hid_info);
- return info;
+ device_list = NULL;
}
BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
BT_EXPORT_API int bluetooth_hid_device_activate(void)
{
- bt_register_profile_info_t profile_info;
- int result = BLUETOOTH_ERROR_NONE;
+ GVariant *reply;
+ GError *err = NULL;
+
+ BT_CHECK_ENABLED(return);
if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
== BLUETOOTH_ERROR_PERMISSION_DEINED) {
return BLUETOOTH_ERROR_PERMISSION_DEINED;
}
- if (hid_info != NULL)
- return BLUETOOTH_ERROR_IN_PROGRESS;
-
- hid_info = __register_method();
- if (hid_info == NULL)
- return BLUETOOTH_ERROR_INTERNAL;
-
- hid_info->uuid = g_strdup(HID_UUID);
-
- profile_info.authentication = TRUE;
- profile_info.authorization = TRUE;
- profile_info.obj_path = hid_info->path;
- profile_info.role = g_strdup("Hid");
- profile_info.service = hid_info->uuid;
- profile_info.uuid = hid_info->uuid;
+ reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
+ BT_HID_SERVICE_INTERFACE,
+ "RegisterApplication", &err, NULL);
+
+ if (!reply) {
+ int ret = BLUETOOTH_ERROR_INTERNAL;
+ BT_ERR("Error returned in method call");
+ if (err) {
+ BT_ERR("Error = %s", err->message);
+ if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
+ ret = BLUETOOTH_ERROR_IN_PROGRESS;
+ else
+ ret = BLUETOOTH_ERROR_INTERNAL;
+ g_clear_error(&err);
+ }
+ return ret;
+ }
- BT_INFO("uuid %s", profile_info.uuid);
- result = _bt_register_profile_platform(&profile_info, FALSE);
+ g_variant_unref(reply);
- return result;
+ return BLUETOOTH_ERROR_NONE;
}
BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
{
+ GVariant *reply;
+ GError *err = NULL;
+
+ BT_CHECK_ENABLED(return);
+
if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
== BLUETOOTH_ERROR_PERMISSION_DEINED) {
BT_ERR("Don't have a privilege to use this API");
return BLUETOOTH_ERROR_PERMISSION_DEINED;
}
- if (hid_info == NULL)
- return BLUETOOTH_ERROR_NOT_IN_OPERATION;
+ reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
+ BT_HID_SERVICE_INTERFACE,
+ "UnregisterApplication", &err, NULL);
+
+ if (!reply) {
+ int ret = BLUETOOTH_ERROR_INTERNAL;
+ BT_ERR("Error returned in method call");
+ if (err) {
+ BT_ERR("Error = %s", err->message);
+ if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
+ ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
+ else
+ ret = BLUETOOTH_ERROR_INTERNAL;
+ g_clear_error(&err);
+ }
+ return ret;
+ }
+
+ g_variant_unref(reply);
- _bt_unregister_profile(hid_info->path);
+ _bt_hid_free_hid_info();
- __free_hid_info(hid_info);
- hid_info = NULL;
return BLUETOOTH_ERROR_NONE;
}
{
char device_address[BT_ADDRESS_STRING_SIZE] = {0};
hid_connected_device_info_t *info = NULL;
+ int ret;
BT_DBG("+");
BT_CHECK_PARAMETER(remote_addr, return);
+ BT_CHECK_ENABLED(return);
+
info = __find_hid_info_with_address(remote_addr);
if (info) {
BT_ERR("Connection Already Exists");
}
memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
- _bt_connect_profile(device_address, HID_UUID, NULL, NULL);
+ ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
+ __hid_connect_response_cb, NULL);
- return BLUETOOTH_ERROR_NONE;
+ return ret;
}
BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
{
+ BT_CHECK_PARAMETER(remote_addr, return);
+
+ BT_CHECK_ENABLED(return);
+
if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
== BLUETOOTH_ERROR_PERMISSION_DEINED) {
BT_ERR("Don't have a privilege to use this API");
return BLUETOOTH_ERROR_PERMISSION_DEINED;
}
+
hid_connected_device_info_t *info = NULL;
info = __find_hid_info_with_address(remote_addr);
if (info == NULL)
return BLUETOOTH_ERROR_INVALID_PARAM;
- _bt_disconnect_profile((char *)remote_addr, HID_UUID, NULL, NULL);
+ _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
int written = 0;
hid_connected_device_info_t *info = NULL;
+ BT_CHECK_PARAMETER(remote_addr, return);
+
switch (privilege_token_send_mouse) {
case 0:
- result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
+ result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
if (result == BLUETOOTH_ERROR_NONE) {
privilege_token_send_mouse = 1; /* Have a permission */
BT_ERR("Connection Information not found");
return BLUETOOTH_ERROR_INVALID_PARAM;
}
- int socket_fd;
-
- if (info == NULL)
- return -1;
-
- if (info->intr_fd != -1 && info->ctrl_fd == -1)
- socket_fd = info->intr_fd;
- else
- socket_fd = info->ctrl_fd;
- written = write(socket_fd, &send_event, sizeof(send_event));
+ if (info->intr_fd >= 0) {
+ written = write(info->intr_fd, &send_event, sizeof(send_event));
+ } else {
+ BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
+ __free_hid_info(info);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
return written;
}
int written = 0;
hid_connected_device_info_t *info = NULL;
+ BT_CHECK_PARAMETER(remote_addr, return);
+
switch (privilege_token_send_key) {
case 0:
- result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_KEY_EVENT);
+ result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
if (result == BLUETOOTH_ERROR_NONE) {
privilege_token_send_key = 1; /* Have a permission */
return BLUETOOTH_ERROR_INVALID_PARAM;
}
- int socket_fd;
+ if (info->intr_fd >= 0) {
+ written = write(info->intr_fd, &send_event, sizeof(send_event));
+ } else {
+ BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
+ __free_hid_info(info);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
- if (info == NULL)
- return -1;
+ return written;
+}
+
+BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
+ unsigned char btcode, unsigned char report_id,
+ const char *data, unsigned int data_len)
+{
+ int result;
+ int written = 0;
+ hid_connected_device_info_t *info = NULL;
+ char *send_event = NULL;
+
+ BT_CHECK_PARAMETER(remote_addr, return);
+ BT_CHECK_PARAMETER(data, return);
+
+ switch (privilege_token_send_key) {
+ case 0:
+ result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
+
+ if (result == BLUETOOTH_ERROR_NONE) {
+ privilege_token_send_key = 1; /* Have a permission */
+ } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
+ BT_ERR("Don't have a privilege to use this API");
+ privilege_token_send_key = -1; /* Don't have a permission */
+ return BLUETOOTH_ERROR_PERMISSION_DEINED;
+ } else {
+ /* Just break - It is not related with permission error */
+ }
+ break;
+ case 1:
+ /* Already have a privilege */
+ break;
+ case -1:
+ return BLUETOOTH_ERROR_PERMISSION_DEINED;
+ default:
+ /* Invalid privilge token value */
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
- if (info->intr_fd != -1 && info->ctrl_fd == -1)
- socket_fd = info->intr_fd;
- else
- socket_fd = info->ctrl_fd;
+ info = __find_hid_info_with_address(remote_addr);
+ if (info == NULL) {
+ BT_ERR("Connection Information not found");
+ return BLUETOOTH_ERROR_INVALID_PARAM;
+ }
+
+ if (info->intr_fd >= 0) {
+ send_event = g_malloc0(data_len + 2);
+
+ send_event[0] = (char)btcode;
+ send_event[1] = (char)report_id;
+ memcpy(send_event + 2, data, data_len);
+
+ written = write(info->intr_fd, send_event, data_len + 2);
+ g_free(send_event);
+ } else {
+ BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
+ __free_hid_info(info);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
- written = write(socket_fd, &send_event, sizeof(send_event));
return written;
}
{
int result;
struct reports output_report = { 0 };
- int bytes = 0;
+ int bytes = -1;
hid_connected_device_info_t *info = NULL;
+
+ BT_CHECK_PARAMETER(remote_addr, return);
+ if (data_len > 20) {
+ BT_ERR("data(len:%d) overflow", data_len);
+ return BLUETOOTH_ERROR_INVALID_PARAM;
+ }
+
info = __find_hid_info_with_address(remote_addr);
if (info == NULL) {
BT_ERR("Connection Information not found");
return BLUETOOTH_ERROR_INVALID_PARAM;
}
+ if (info->ctrl_fd < 0) {
+ BT_ERR("ctrl_fd(%d) is invalid.", info->ctrl_fd);
+ __free_hid_info(info);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
switch (privilege_token_reply) {
case 0:
- result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
+ result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
if (result == BLUETOOTH_ERROR_NONE) {
privilege_token_reply = 1; /* Have a permission */
}
BT_INFO("htype %d ptype %d", htype, ptype);
- switch(htype) {
- case HTYPE_TRANS_GET_REPORT: {
- switch(ptype) {
- case PTYPE_DATA_RTYPE_INPUT: {
- output_report.type = HIDP_TRANS_DATA |
- HIDP_DATA_RTYPE_INPUT;
- memcpy(output_report.rep_data, data, data_len);
- bytes = write(info->intr_fd, &output_report,
- sizeof(output_report));
- BT_DBG("Bytes Written %d", bytes);
- break;
- }
- default:
- BT_INFO("Not Supported");
- break;
- }
- break;
- case HTYPE_TRANS_GET_PROTOCOL: {
- BT_DBG("Replying to Get_PROTOCOL");
- output_report.type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUTPUT;
- output_report.rep_data[0] = data[0];
- bytes = write(info->intr_fd, &output_report, 2);
- BT_DBG("Bytes Written %d", bytes);
- break;
- }
- case HTYPE_TRANS_SET_PROTOCOL: {
- BT_DBG("Reply to Set_Protocol");
- output_report.type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT;
+ switch (htype) {
+ case HTYPE_TRANS_GET_REPORT: {
+ switch (ptype) {
+ case PTYPE_DATA_RTYPE_INPUT: {
+ output_report.type = BT_HID_TRANS_DATA |
+ BT_HID_DATA_RTYPE_INPUT;
memcpy(output_report.rep_data, data, data_len);
bytes = write(info->ctrl_fd, &output_report,
- sizeof(output_report));
+ sizeof(output_report));
BT_DBG("Bytes Written %d", bytes);
break;
}
- case HTYPE_TRANS_HANDSHAKE: {
- BT_DBG("Replying Handshake");
- output_report.type = HIDP_TRANS_HANDSHAKE | data[0];
- memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
- bytes = write(info->intr_fd, &output_report.type,
- sizeof(output_report.type));
- BT_DBG("Bytes Written %d", bytes);
+ default:
+ BT_INFO("Not Supported");
break;
- }
- default:
- break;
+ }
+ break;
+
+ case HTYPE_TRANS_GET_PROTOCOL: {
+ output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
+ output_report.rep_data[0] = data[0];
+ bytes = write(info->ctrl_fd, &output_report, 2);
+ break;
+ }
+
+ case HTYPE_TRANS_SET_PROTOCOL: {
+ output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
+ memcpy(output_report.rep_data, data, data_len);
+ bytes = write(info->ctrl_fd, &output_report,
+ sizeof(output_report));
+ break;
+ }
+
+ case HTYPE_TRANS_HANDSHAKE: {
+ output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
+ memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
+ bytes = write(info->ctrl_fd, &output_report.type,
+ sizeof(output_report.type));
+ break;
+ }
+
+ case HTYPE_TRANS_DATA: {
+ output_report.type = BT_HID_TRANS_DATA;
+ memcpy(output_report.rep_data, data, data_len);
+ bytes = write(info->ctrl_fd, &output_report.type,
+ data_len + 1);
+ break;
+ }
+
+ case HTYPE_TRANS_GET_IDLE: {
+ output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
+ output_report.rep_data[0] = data[0];
+ bytes = write(info->ctrl_fd, &output_report, 2);
+ break;
+ }
+
+ case HTYPE_TRANS_SET_IDLE: {
+ output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
+ memcpy(output_report.rep_data, data, data_len);
+ bytes = write(info->ctrl_fd, &output_report,
+ sizeof(output_report));
+ break;
+ }
+
+ default:
+ break;
}
}
+
+ BT_DBG("Bytes Written %d", bytes);
+
return bytes;
}