When compare address, ignoring the case of the characters
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-hid-device.c
index a623fea..e0e8a53 100644 (file)
@@ -1,11 +1,5 @@
 /*
- * 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
 
-/* The types of HIDP transaction */
-#define BT_HIDP_TRANSACTION_SET_PROTOCOL               0x70
-#define BT_HIDP_TRANSACTION_GET_IDLE                   0x80
-#define BT_HIDP_TRANSACTION_SET_IDLE                   0x90
-#define BT_HIDP_TRANSACTION_DATA                       0xa0
-#define BT_HIDP_TRANSACTION_DATC                       0xb0
-#define BT_HIDP_TRANSACTION_HANDSHAKE                   0x00
-#define BT_HIDP_TRANSACTION_HID_CONTROL                 0x10
-#define BT_HIDP_TRANSACTION_GET_REPORT                  0x40
-#define BT_HIDP_TRANSACTION_SET_REPORT                  0x50
-#define BT_HIDP_TRANSACTION_GET_PROTOCOL                0x60
-
-#define BT_HIDP_DATA_OUT_RTYPE                         0x02
-#define BT_HIDP_DATA_IN_RTYPE                          0x01
-
-#define BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST          0x03
-#define BT_HIDP_HSHK_ERROR_INVALID_PARAM                0x04
-#define BT_HIDP_HSHK_ERROR_UNKNOWN                      0x0E
-#define BT_HIDP_HSHK_ERROR_FATAL                        0x0F
-#define BT_HIDP_HSHK_OK_SUCCESSFUL                     0x00
-#define BT_HIDP_HSHK_NOT_AVAILABLE                     0x01
-#define BT_HIDP_HSHK_ERROR_INVALID_REPORT_ID           0x02
-
-/* The masks of BT_HIDP header */
-#define BT_HIDP_HEADER_PARAMETER_MASK                   0x0f
-#define BT_HIDP_HEADER_TRANSACTION_MASK                 0xf0
-
-typedef struct {
-       guint object_id;
-       gchar *path;
-       int id;
-       char *uuid;
-       GSList *device_list;
-} hid_info_t;
+/* HIDP header masks */
+#define BT_HID_HEADER_TRANS_MASK                       0xf0
+#define BT_HID_HEADER_PARAM_MASK                       0x0f
+
+/* HIDP transaction types */
+#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;
@@ -81,12 +72,12 @@ typedef struct {
        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
@@ -98,46 +89,128 @@ static int privilege_token_send_mouse = 0;
 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(&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);
+       memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
+       _bt_convert_addr_string_to_type(bd_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;
@@ -147,13 +220,6 @@ static gboolean __hid_disconnect(hid_connected_device_info_t *info)
                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);
@@ -164,46 +230,33 @@ static gboolean __hid_disconnect(hid_connected_device_info_t *info)
                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,
@@ -211,7 +264,7 @@ 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;
@@ -220,214 +273,300 @@ static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
 
        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 & BT_HIDP_HEADER_TRANSACTION_MASK;
-               param = header & BT_HIDP_HEADER_PARAMETER_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 BT_HIDP_TRANSACTION_HANDSHAKE:
-                               BT_INFO("TRANS HANDSHAKE");
-                               data.type = HTYPE_TRANS_HANDSHAKE;
-                               data.buffer_size = len;
-                               data.buffer = (char *) malloc(sizeof(char) * len);
-                               if (data.buffer)
-                                       memcpy(data.buffer, buffer, len);
-                       break;
-                       case BT_HIDP_TRANSACTION_HID_CONTROL:
-                               BT_INFO("HID CONTROL");
-                               data.type = HTYPE_TRANS_HID_CONTROL;
-                               data.buffer_size = len;
-                               data.buffer = (char *) malloc(sizeof(char) * len);
-                               if (data.buffer)
-                                       memcpy(data.buffer, buffer, len);
-                       break;
-                       case BT_HIDP_TRANSACTION_DATA:
-                               BT_INFO("TRANS DATA");
-                               data.type = HTYPE_TRANS_DATA;
-                               if ( param & BT_HIDP_DATA_IN_RTYPE) {
-                                       BT_INFO("Input Report");
-                                       data.param = PTYPE_DATA_RTYPE_INPUT;
-                                       data.buffer_size = len;
-                                       data.buffer = (char *) malloc(sizeof(char) * len);
-                                       if (data.buffer)
-                                               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);
-                                       if (data.buffer)
-                                               memcpy(data.buffer, buffer, len);
-                               }
-                       break;
-                       case BT_HIDP_TRANSACTION_GET_REPORT: {
-                               BT_INFO("Get Report");
-                               data.type = HTYPE_TRANS_GET_REPORT;
-                               if (param & BT_HIDP_DATA_IN_RTYPE) {
-                                       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);
-                               if (data.buffer)
-                                       memcpy(data.buffer, buffer, len);
-                               break;
-                       }
-                       case BT_HIDP_TRANSACTION_SET_REPORT: {
-                               BT_INFO("Set Report");
-                               data.type = HTYPE_TRANS_SET_REPORT;
-                               if (param & BT_HIDP_DATA_IN_RTYPE) {
-                                       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);
-                               if (data.buffer)
-                                       memcpy(data.buffer, buffer, len);
-                               break;
-                       }
-                       case BT_HIDP_TRANSACTION_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);
-                               if (data.buffer)
-                                       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 BT_HIDP_TRANSACTION_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);
-                               if (data.buffer)
-                                       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 = BT_HIDP_TRANSACTION_HANDSHAKE |
-                                       BT_HIDP_HSHK_ERROR_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) {
-                       g_free(data.buffer);
-                       g_free((char *)data.address);
-                       return FALSE;
+
+               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, &data,
+       _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
+                               BLUETOOTH_ERROR_NONE, &recv_data,
                                event_info->cb, event_info->user_data);
+       if (recv_data.buffer)
+               g_free(recv_data.buffer);
 
-               g_free(data.buffer);
-               g_free((char *)data.address);
+       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)
 {
-       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;
+       BT_DBG("");
 
-       if (info == NULL)
-               return -1;
-       _bt_convert_addr_type_to_string((char *)address, addr->addr);
-       BT_INFO("Address [%s]", address);
-       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));
-               if (dev_info == NULL) {
-                       BT_ERR("Fail to allocation memory");
-                       return -1;
-               }
+       hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
 
-               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);
+       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)
+{
 
-               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);
+       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;
        }
-       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);
+
+       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_connected_device_info_t *dev_info = NULL;
+       char address[18];
+       char secure_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+       _bt_convert_addr_type_to_string((char *)address, addr->addr);
+       _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)
+               __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)
@@ -467,8 +606,10 @@ BT_EXPORT_API int bluetooth_hid_device_deinit(void)
 
 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) {
@@ -476,43 +617,64 @@ BT_EXPORT_API int bluetooth_hid_device_activate(void)
                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;
 }
 
@@ -524,6 +686,8 @@ BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
        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");
@@ -536,24 +700,30 @@ BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
        }
 
        memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
-       ret = _bt_connect_profile(device_address, HID_UUID, NULL, NULL);
+       ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
+                               __hid_connect_response_cb, NULL);
 
        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);
 
@@ -565,12 +735,13 @@ BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
 {
        int result;
        int written = 0;
-       int socket_fd;
        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 */
@@ -597,12 +768,13 @@ BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
                return BLUETOOTH_ERROR_INVALID_PARAM;
        }
 
-       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;
 }
@@ -612,12 +784,13 @@ BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
 {
        int result;
        int written = 0;
-       int socket_fd;
        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 */
@@ -645,12 +818,74 @@ BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
                return BLUETOOTH_ERROR_INVALID_PARAM;
        }
 
-       if (info->intr_fd != -1 && info->ctrl_fd == -1)
-               socket_fd = info->intr_fd;
-       else
-               socket_fd = info->ctrl_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;
+       }
+
+       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;
+       }
+
+       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;
 }
 
@@ -662,17 +897,26 @@ BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
 {
        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);
+
        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 */
@@ -695,52 +939,68 @@ BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
        }
 
        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 = BT_HIDP_TRANSACTION_DATA |
-                                                       BT_HIDP_DATA_IN_RTYPE;
-                                       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 = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_OUT_RTYPE;
-                       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 = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_IN_RTYPE;
+       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 = BT_HIDP_TRANSACTION_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_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;
 }