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