[Boiler Plate] Update Boiler plate to remove unwanted information
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-hid-device.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 #include <gio/gio.h>
18 #include <gio/gunixfdlist.h>
19 #include <sys/socket.h>
20
21 #include "bluetooth-api.h"
22 #include "bt-internal-types.h"
23 #include "bluetooth-hid-api.h"
24 #include "bt-common.h"
25 #include "bt-request-sender.h"
26 #include "bt-event-handler.h"
27
28 #define HID_UUID                "00001124-0000-1000-8000-00805f9b34fb"
29 #define REPORTID_MOUSE  1
30 #define BT_HID_BUFFER_LEN 100
31
32 /* The types of HIDP transaction */
33 #define BT_HIDP_TRANSACTION_SET_PROTOCOL                0x70
34 #define BT_HIDP_TRANSACTION_GET_IDLE                    0x80
35 #define BT_HIDP_TRANSACTION_SET_IDLE                    0x90
36 #define BT_HIDP_TRANSACTION_DATA                        0xa0
37 #define BT_HIDP_TRANSACTION_DATC                        0xb0
38 #define BT_HIDP_TRANSACTION_HANDSHAKE                   0x00
39 #define BT_HIDP_TRANSACTION_HID_CONTROL                 0x10
40 #define BT_HIDP_TRANSACTION_GET_REPORT                  0x40
41 #define BT_HIDP_TRANSACTION_SET_REPORT                  0x50
42 #define BT_HIDP_TRANSACTION_GET_PROTOCOL                0x60
43
44 #define BT_HIDP_DATA_OUT_RTYPE                          0x02
45 #define BT_HIDP_DATA_IN_RTYPE                           0x01
46
47 #define BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST          0x03
48 #define BT_HIDP_HSHK_ERROR_INVALID_PARAM                0x04
49 #define BT_HIDP_HSHK_ERROR_UNKNOWN                      0x0E
50 #define BT_HIDP_HSHK_ERROR_FATAL                        0x0F
51 #define BT_HIDP_HSHK_OK_SUCCESSFUL                      0x00
52 #define BT_HIDP_HSHK_NOT_AVAILABLE                      0x01
53 #define BT_HIDP_HSHK_ERROR_INVALID_REPORT_ID            0x02
54
55 /* The masks of BT_HIDP header */
56 #define BT_HIDP_HEADER_PARAMETER_MASK                   0x0f
57 #define BT_HIDP_HEADER_TRANSACTION_MASK                 0xf0
58
59 typedef struct {
60         guint object_id;
61         gchar *path;
62         int id;
63         char *uuid;
64         GSList *device_list;
65 } hid_info_t;
66
67 typedef struct {
68         int ctrl_fd;
69         int intr_fd;
70         GIOChannel *ctrl_data_io;
71         GIOChannel *intr_data_io;
72         guint ctrl_data_id;
73         guint intr_data_id;
74         char *address;
75         guint disconnect_idle_id;
76 } hid_connected_device_info_t;
77
78 struct reports{
79         guint8 type;
80         guint8 rep_data[20];
81 }__attribute__((__packed__));
82
83 static hid_info_t *hid_info = NULL;
84
85 /* Variable for privilege, only for write API,
86   before we should reduce time to bt-service dbus calling
87   -1 : Don't have a permission to access API
88   0 : Initial value, not yet check
89   1 : Have a permission to access API
90 */
91 static int privilege_token_send_mouse = 0;
92 static int privilege_token_send_key = 0;
93 static int privilege_token_reply = 0;
94
95 static gboolean __hid_disconnect(hid_connected_device_info_t *info);
96
97 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
98 {
99         GSList *l;
100
101         for ( l = hid_info->device_list; l != NULL; l = l->next) {
102                 hid_connected_device_info_t *info = l->data;
103                 if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
104                         return info;
105         }
106         return NULL;
107 }
108
109 static void __hid_connected_cb(hid_connected_device_info_t *info,
110                         bt_event_info_t *event_info)
111 {
112         bluetooth_hid_request_t conn_info;
113
114         memset(&conn_info, 0x00, sizeof(bluetooth_hid_request_t));
115         if (info->intr_fd != -1 && info->ctrl_fd == -1)
116                 conn_info.socket_fd = info->intr_fd;
117         else
118                 conn_info.socket_fd = info->ctrl_fd;
119         _bt_convert_addr_string_to_type (conn_info.device_addr.addr , info->address);
120
121         BT_INFO_C("Connected [HID Device]");
122         _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
123                         BLUETOOTH_ERROR_NONE, &conn_info,
124                         event_info->cb, event_info->user_data);
125 }
126
127 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
128 {
129         bluetooth_hid_request_t disconn_info;
130         int fd = info->ctrl_fd;
131         bt_event_info_t *event_info;
132
133         BT_INFO_C("Disconnected [HID Device]");
134         hid_info->device_list = g_slist_remove(hid_info->device_list, info);
135         if (info->ctrl_data_id > 0) {
136                 g_source_remove(info->ctrl_data_id);
137                 info->ctrl_data_id = 0;
138         }
139         if (info->intr_data_id > 0) {
140                 g_source_remove(info->intr_data_id);
141                 info->intr_data_id = 0;
142         }
143
144         if (info->intr_fd >= 0) {
145                 close(info->ctrl_fd);
146                 close(info->intr_fd);
147                 info->intr_fd = -1;
148                 info->ctrl_fd = -1;
149         }
150
151         if (info->ctrl_data_io) {
152                 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
153                 g_io_channel_unref(info->ctrl_data_io);
154                 info->ctrl_data_io = NULL;
155         }
156         if (info->intr_data_io) {
157                 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
158                 g_io_channel_unref(info->intr_data_io);
159                 info->intr_data_io = NULL;
160         }
161         info->disconnect_idle_id = 0;
162         event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
163         if (event_info == NULL)
164                 return FALSE;
165
166         memset(&disconn_info, 0x00, sizeof(bluetooth_hid_request_t));
167         disconn_info.socket_fd = fd;
168         _bt_convert_addr_string_to_type (disconn_info.device_addr.addr , info->address);
169         _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
170                         BLUETOOTH_ERROR_NONE, &disconn_info,
171                         event_info->cb, event_info->user_data);
172         if (info->address)
173                 g_free(info->address);
174         g_free(info);
175         info = NULL;
176         BT_DBG("-");
177         return FALSE;
178 }
179
180 void __free_hid_info(hid_info_t *info)
181 {
182         BT_DBG("");
183
184         _bt_unregister_gdbus(info->object_id);
185
186         while (info->device_list) {
187                 hid_connected_device_info_t *dev_info = NULL;
188                 dev_info = (hid_connected_device_info_t *)info->device_list->data;
189
190                 if (dev_info->disconnect_idle_id > 0) {
191                         BT_INFO("Disconnect idle still not process remove source");
192                         g_source_remove(dev_info->disconnect_idle_id);
193                         dev_info->disconnect_idle_id = 0;
194                 }
195                 __hid_disconnect(dev_info);
196         }
197
198         g_free(info->path);
199         g_free(info->uuid);
200         g_free(info);
201 }
202
203 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
204                                                                 gpointer data)
205 {
206         hid_connected_device_info_t *info = data;
207         GIOStatus status = G_IO_STATUS_NORMAL;
208         char buffer[20];
209         gsize len = 0;
210         GError *err = NULL;
211         guint8  header, type, param;
212         bt_event_info_t *event_info;
213         retv_if(info == NULL, FALSE);
214
215         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
216                 BT_ERR_C("HID  disconnected: %d", info->ctrl_fd);
217                if (info->disconnect_idle_id > 0) {
218                         BT_INFO("Disconnect idle still not process remove source");
219                         g_source_remove(info->disconnect_idle_id);
220                         info->disconnect_idle_id = 0;
221                }
222                 __hid_disconnect(info);
223                 return FALSE;
224         }
225         status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
226                         &len, &err);
227         if (status == G_IO_STATUS_NORMAL) {
228                 BT_INFO("Parsing Data");
229                 bluetooth_hid_received_data_t data = {0};
230                 header = buffer[0];
231                 type = header & BT_HIDP_HEADER_TRANSACTION_MASK;
232                 param = header & BT_HIDP_HEADER_PARAMETER_MASK;
233                 BT_INFO("type %d , param %d", type, param);
234                 BT_INFO("Data Reveived from %s" , info->address);
235                 data.address = g_strdup(info->address);
236                 switch (type) {
237                         case BT_HIDP_TRANSACTION_HANDSHAKE:
238                                 BT_INFO("TRANS HANDSHAKE");
239                                 data.type = HTYPE_TRANS_HANDSHAKE;
240                                 data.buffer_size = len;
241                                 data.buffer = (char *) malloc(sizeof(char) * len);
242                                 if (data.buffer)
243                                         memcpy(data.buffer, buffer, len);
244                         break;
245                         case BT_HIDP_TRANSACTION_HID_CONTROL:
246                                 BT_INFO("HID CONTROL");
247                                 data.type = HTYPE_TRANS_HID_CONTROL;
248                                 data.buffer_size = len;
249                                 data.buffer = (char *) malloc(sizeof(char) * len);
250                                 if (data.buffer)
251                                         memcpy(data.buffer, buffer, len);
252                         break;
253                         case BT_HIDP_TRANSACTION_DATA:
254                                 BT_INFO("TRANS DATA");
255                                 data.type = HTYPE_TRANS_DATA;
256                                 if ( param & BT_HIDP_DATA_IN_RTYPE) {
257                                         BT_INFO("Input Report");
258                                         data.param = PTYPE_DATA_RTYPE_INPUT;
259                                         data.buffer_size = len;
260                                         data.buffer = (char *) malloc(sizeof(char) * len);
261                                         if (data.buffer)
262                                                 memcpy(data.buffer, buffer, len);
263                                 }
264                                 else {
265                                         BT_INFO("Out Report");
266                                         data.param = PTYPE_DATA_RTYPE_OUTPUT;
267                                         data.buffer_size = len;
268                                         data.buffer = (char *) malloc(sizeof(char) * len);
269                                         if (data.buffer)
270                                                 memcpy(data.buffer, buffer, len);
271                                 }
272                         break;
273                         case BT_HIDP_TRANSACTION_GET_REPORT: {
274                                 BT_INFO("Get Report");
275                                 data.type = HTYPE_TRANS_GET_REPORT;
276                                 if (param & BT_HIDP_DATA_IN_RTYPE) {
277                                         BT_INFO("Input Report");
278                                         data.param = PTYPE_DATA_RTYPE_INPUT;
279                                 } else {
280                                         BT_INFO("Output Report");
281                                         data.param = PTYPE_DATA_RTYPE_OUTPUT;
282                                 }
283                                 data.buffer_size = len;
284                                 data.buffer = (char *) malloc(sizeof(char) * len);
285                                 if (data.buffer)
286                                         memcpy(data.buffer, buffer, len);
287                                 break;
288                         }
289                         case BT_HIDP_TRANSACTION_SET_REPORT: {
290                                 BT_INFO("Set Report");
291                                 data.type = HTYPE_TRANS_SET_REPORT;
292                                 if (param & BT_HIDP_DATA_IN_RTYPE) {
293                                         BT_INFO("Input Report");
294                                         data.param = PTYPE_DATA_RTYPE_INPUT;
295                                 } else {
296                                         BT_INFO("Output Report");
297                                         data.param = PTYPE_DATA_RTYPE_OUTPUT;
298                                 }
299                                 data.buffer_size = len;
300                                 data.buffer = (char *) malloc(sizeof(char) * len);
301                                 if (data.buffer)
302                                         memcpy(data.buffer, buffer, len);
303                                 break;
304                         }
305                         case BT_HIDP_TRANSACTION_GET_PROTOCOL:{
306                                 BT_INFO("Get_PROTOCOL");
307                                 data.type = HTYPE_TRANS_GET_PROTOCOL;
308                                 data.param = PTYPE_DATA_RTYPE_INPUT;
309                                 data.buffer_size = len;
310                                 data.buffer = (char *) malloc(sizeof(char) * len);
311                                 if (data.buffer)
312                                         memcpy(data.buffer, buffer, len);
313                                 break;
314                         }
315                         case BT_HIDP_TRANSACTION_SET_PROTOCOL:{
316                                 BT_INFO("Set_PROTOCOL");
317                                 data.type = HTYPE_TRANS_SET_PROTOCOL;
318                                 data.param = PTYPE_DATA_RTYPE_INPUT;
319                                 data.buffer_size = len;
320                                 data.buffer = (char *) malloc(sizeof(char) * len);
321                                 if (data.buffer)
322                                         memcpy(data.buffer, buffer, len);
323                                 break;
324                         }
325                         default: {
326                                 BT_INFO("unsupported HIDP control message");
327                                 BT_ERR("Send Handshake Message");
328                                 guint8 type = BT_HIDP_TRANSACTION_HANDSHAKE |
329                                         BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST;
330                                 data.type = HTYPE_TRANS_UNKNOWN;
331                                 int fd = g_io_channel_unix_get_fd(chan);
332                                 int bytes = write(fd,  &type, sizeof(type));
333                                 BT_INFO("Bytes Written %d", bytes);
334                                 break;
335                         }
336                 }
337                 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
338                 if (event_info == NULL) {
339                         g_free(data.buffer);
340                         g_free((char *)data.address);
341                         return FALSE;
342                 }
343
344                 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
345                                 BLUETOOTH_ERROR_NONE, &data,
346                                 event_info->cb, event_info->user_data);
347
348                 g_free(data.buffer);
349                 g_free((char *)data.address);
350         } else {
351                 BT_INFO("Error while reading data");
352         }
353         return TRUE;
354 }
355
356 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
357 {
358         hid_info_t *info = NULL;
359         hid_connected_device_info_t *dev_info = NULL;
360         bt_event_info_t *event_info = NULL;
361         char address[18];
362         info = hid_info;
363
364         if (info == NULL)
365                 return -1;
366         _bt_convert_addr_type_to_string((char *)address, addr->addr);
367         BT_INFO("Address [%s]", address);
368         dev_info = __find_hid_info_with_address(address);
369         if (dev_info == NULL) {
370                 dev_info = (hid_connected_device_info_t *)
371                         g_malloc0(sizeof(hid_connected_device_info_t));
372                 if (dev_info == NULL) {
373                         BT_ERR("Fail to allocation memory");
374                         return -1;
375                 }
376
377                 dev_info->intr_fd = -1;
378                 dev_info->ctrl_fd = -1;
379                 dev_info->intr_fd = fd;
380                 dev_info->address = g_strdup(address);
381                 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
382                 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
383                 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
384
385                 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
386                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
387                                 __received_cb, dev_info);
388                 hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
389         } else {
390                 dev_info->ctrl_fd = fd;
391                 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
392                 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
393                 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
394
395                 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
396                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
397                                 __received_cb, dev_info);
398         }
399         if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1) {
400                 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
401                 if (event_info)
402                         __hid_connected_cb(dev_info, event_info);
403         }
404
405         return 0;
406 }
407 static hid_info_t *__register_method()
408 {
409         int object_id;
410         hid_info_t *info = NULL;
411         char *path = NULL;
412         path = g_strdup_printf("/org/socket/server/%d", getpid());
413
414         object_id = _bt_register_new_conn(path, new_hid_connection);
415         if (object_id < 0) {
416                 return NULL;
417         }
418         info = g_new(hid_info_t, 1);
419         info->object_id = (guint)object_id;
420         info->path = path;
421         info->id = 0;
422         info->device_list = NULL;
423
424         return info;
425 }
426
427 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
428 {
429         int ret;
430
431         /* Register HID Device events */
432         BT_INFO("BT_HID_DEVICE_EVENT");
433         ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
434
435         if (ret != BLUETOOTH_ERROR_NONE &&
436              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
437                 BT_ERR("Fail to init the event handler");
438                 return ret;
439         }
440
441         _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
442
443         return BLUETOOTH_ERROR_NONE;
444 }
445
446 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
447 {
448         int ret;
449
450         ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
451
452         if (ret != BLUETOOTH_ERROR_NONE) {
453                 BT_ERR("Fail to deinit the event handler");
454                 return ret;
455         }
456
457         _bt_set_user_data(BT_HID, NULL, NULL);
458
459         return BLUETOOTH_ERROR_NONE;
460 }
461
462 BT_EXPORT_API int bluetooth_hid_device_activate(void)
463 {
464         bt_register_profile_info_t profile_info;
465         int result = BLUETOOTH_ERROR_NONE;
466
467         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
468                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
469                 BT_ERR("Don't have a privilege to use this API");
470                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
471         }
472
473         if (hid_info != NULL)
474                 return BLUETOOTH_ERROR_IN_PROGRESS;
475
476         hid_info = __register_method();
477         if (hid_info == NULL)
478                 return BLUETOOTH_ERROR_INTERNAL;
479
480         hid_info->uuid = g_strdup(HID_UUID);
481
482         profile_info.authentication = TRUE;
483         profile_info.authorization = TRUE;
484         profile_info.obj_path = hid_info->path;
485         profile_info.role = g_strdup("Hid");
486         profile_info.service = hid_info->uuid;
487         profile_info.uuid = hid_info->uuid;
488
489         BT_INFO("uuid %s", profile_info.uuid);
490         result = _bt_register_profile_platform(&profile_info, FALSE);
491
492         return result;
493 }
494
495 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
496 {
497         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
498                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
499                 BT_ERR("Don't have a privilege to use this API");
500                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
501         }
502
503         if (hid_info == NULL)
504                 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
505
506         _bt_unregister_profile(hid_info->path);
507
508         __free_hid_info(hid_info);
509         hid_info = NULL;
510         return BLUETOOTH_ERROR_NONE;
511 }
512
513 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
514 {
515         char device_address[BT_ADDRESS_STRING_SIZE] = {0};
516         hid_connected_device_info_t *info = NULL;
517         int ret;
518         BT_DBG("+");
519         BT_CHECK_PARAMETER(remote_addr, return);
520
521         info = __find_hid_info_with_address(remote_addr);
522         if (info) {
523                 BT_ERR("Connection Already Exists");
524                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
525         }
526         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
527                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
528                 BT_ERR("Don't have a privilege to use this API");
529                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
530         }
531
532         memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
533         ret = _bt_connect_profile(device_address, HID_UUID, NULL, NULL);
534
535         return ret;
536 }
537 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
538 {
539         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
540                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
541                 BT_ERR("Don't have a privilege to use this API");
542                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
543         }
544         hid_connected_device_info_t *info = NULL;
545
546         info = __find_hid_info_with_address(remote_addr);
547         if (info == NULL)
548                 return BLUETOOTH_ERROR_INVALID_PARAM;
549
550         _bt_disconnect_profile((char *)remote_addr, HID_UUID, NULL, NULL);
551
552         info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
553
554         BT_DBG("-");
555         return BLUETOOTH_ERROR_NONE;
556 }
557 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
558                                         hid_send_mouse_event_t send_event)
559 {
560         int result;
561         int written = 0;
562         int socket_fd;
563         hid_connected_device_info_t *info = NULL;
564
565         switch (privilege_token_send_mouse) {
566         case 0:
567                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
568
569                 if (result == BLUETOOTH_ERROR_NONE) {
570                         privilege_token_send_mouse = 1; /* Have a permission */
571                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
572                         BT_ERR("Don't have a privilege to use this API");
573                         privilege_token_send_mouse = -1; /* Don't have a permission */
574                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
575                 } else {
576                         /* Just break - It is not related with permission error */
577                 }
578                 break;
579         case 1:
580                 /* Already have a privilege */
581                 break;
582         case -1:
583                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
584         default:
585                 /* Invalid privilge token value */
586                 return BLUETOOTH_ERROR_INTERNAL;
587         }
588         info = __find_hid_info_with_address(remote_addr);
589         if (info == NULL) {
590                 BT_ERR("Connection Information not found");
591                 return BLUETOOTH_ERROR_INVALID_PARAM;
592         }
593
594         if (info->intr_fd != -1 && info->ctrl_fd == -1)
595                 socket_fd = info->intr_fd;
596         else
597                 socket_fd = info->ctrl_fd;
598
599         written = write(socket_fd, &send_event, sizeof(send_event));
600
601         return written;
602 }
603
604 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
605                                         hid_send_key_event_t send_event)
606 {
607         int result;
608         int written = 0;
609         int socket_fd;
610         hid_connected_device_info_t *info = NULL;
611
612         switch (privilege_token_send_key) {
613         case 0:
614                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_KEY_EVENT);
615
616                 if (result == BLUETOOTH_ERROR_NONE) {
617                         privilege_token_send_key = 1; /* Have a permission */
618                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
619                         BT_ERR("Don't have a privilege to use this API");
620                         privilege_token_send_key = -1; /* Don't have a permission */
621                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
622                 } else {
623                         /* Just break - It is not related with permission error */
624                 }
625                 break;
626         case 1:
627                 /* Already have a privilege */
628                 break;
629         case -1:
630                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
631         default:
632                 /* Invalid privilge token value */
633                 return BLUETOOTH_ERROR_INTERNAL;
634         }
635
636         info = __find_hid_info_with_address(remote_addr);
637         if (info == NULL) {
638                 BT_ERR("Connection Information not found");
639                 return BLUETOOTH_ERROR_INVALID_PARAM;
640         }
641
642         if (info->intr_fd != -1 && info->ctrl_fd == -1)
643                 socket_fd = info->intr_fd;
644         else
645                 socket_fd = info->ctrl_fd;
646
647         written = write(socket_fd, &send_event, sizeof(send_event));
648         return written;
649 }
650
651 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
652                                 bt_hid_header_type_t htype,
653                                 bt_hid_param_type_t ptype,
654                                 const char *data,
655                                 unsigned int data_len)
656 {
657         int result;
658         struct reports output_report = { 0 };
659         int bytes = 0;
660         hid_connected_device_info_t *info = NULL;
661         info = __find_hid_info_with_address(remote_addr);
662         if (info == NULL) {
663                 BT_ERR("Connection Information not found");
664                 return BLUETOOTH_ERROR_INVALID_PARAM;
665         }
666
667         switch (privilege_token_reply) {
668         case 0:
669                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
670
671                 if (result == BLUETOOTH_ERROR_NONE) {
672                         privilege_token_reply = 1; /* Have a permission */
673                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
674                         BT_ERR("Don't have a privilege to use this API");
675                         privilege_token_reply = -1; /* Don't have a permission */
676                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
677                 } else {
678                         /* Just break - It is not related with permission error */
679                 }
680                 break;
681         case 1:
682                 /* Already have a privilege */
683                 break;
684         case -1:
685                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
686         default:
687                 /* Invalid privilge token value */
688                 return BLUETOOTH_ERROR_INTERNAL;
689         }
690
691         BT_INFO("htype %d ptype %d", htype, ptype);
692         switch(htype) {
693                 case HTYPE_TRANS_GET_REPORT: {
694                         switch(ptype) {
695                                 case PTYPE_DATA_RTYPE_INPUT: {
696                                         output_report.type = BT_HIDP_TRANSACTION_DATA |
697                                                         BT_HIDP_DATA_IN_RTYPE;
698                                         memcpy(output_report.rep_data, data, data_len);
699                                         bytes = write(info->intr_fd, &output_report,
700                                                                 sizeof(output_report));
701                                         BT_DBG("Bytes Written %d", bytes);
702                                         break;
703                                 }
704                                 default:
705                                         BT_INFO("Not Supported");
706                                         break;
707                         }
708                         break;
709                 case HTYPE_TRANS_GET_PROTOCOL: {
710                         BT_DBG("Replying to Get_PROTOCOL");
711                         output_report.type = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_OUT_RTYPE;
712                         output_report.rep_data[0] = data[0];
713                         bytes = write(info->intr_fd, &output_report, 2);
714                         BT_DBG("Bytes Written %d", bytes);
715                         break;
716                 }
717                 case HTYPE_TRANS_SET_PROTOCOL: {
718                         BT_DBG("Reply to Set_Protocol");
719                         output_report.type = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_IN_RTYPE;
720                         memcpy(output_report.rep_data, data, data_len);
721                         bytes = write(info->ctrl_fd, &output_report,
722                                         sizeof(output_report));
723                         BT_DBG("Bytes Written %d", bytes);
724                         break;
725                 }
726                 case HTYPE_TRANS_HANDSHAKE: {
727                         BT_DBG("Replying Handshake");
728                         output_report.type = BT_HIDP_TRANSACTION_HANDSHAKE | data[0];
729                         memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
730                         bytes = write(info->intr_fd,  &output_report.type,
731                                         sizeof(output_report.type));
732                         BT_DBG("Bytes Written %d", bytes);
733                         break;
734                 }
735                         default:
736                                 break;
737                 }
738         }
739         return bytes;
740 }