Merge the code from tizen_2.4
[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 /* The types of HIDP transaction */
39 #define BT_HIDP_TRANSACTION_SET_PROTOCOL                0x70
40 #define BT_HIDP_TRANSACTION_GET_IDLE                    0x80
41 #define BT_HIDP_TRANSACTION_SET_IDLE                    0x90
42 #define BT_HIDP_TRANSACTION_DATA                        0xa0
43 #define BT_HIDP_TRANSACTION_DATC                        0xb0
44 #define BT_HIDP_TRANSACTION_HANDSHAKE                   0x00
45 #define BT_HIDP_TRANSACTION_HID_CONTROL                 0x10
46 #define BT_HIDP_TRANSACTION_GET_REPORT                  0x40
47 #define BT_HIDP_TRANSACTION_SET_REPORT                  0x50
48 #define BT_HIDP_TRANSACTION_GET_PROTOCOL                0x60
49
50 #define BT_HIDP_DATA_OUT_RTYPE                          0x02
51 #define BT_HIDP_DATA_IN_RTYPE                           0x01
52
53 #define BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST          0x03
54 #define BT_HIDP_HSHK_ERROR_INVALID_PARAM                0x04
55 #define BT_HIDP_HSHK_ERROR_UNKNOWN                      0x0E
56 #define BT_HIDP_HSHK_ERROR_FATAL                        0x0F
57 #define BT_HIDP_HSHK_OK_SUCCESSFUL                      0x00
58 #define BT_HIDP_HSHK_NOT_AVAILABLE                      0x01
59 #define BT_HIDP_HSHK_ERROR_INVALID_REPORT_ID            0x02
60
61 /* The masks of BT_HIDP header */
62 #define BT_HIDP_HEADER_PARAMETER_MASK                   0x0f
63 #define BT_HIDP_HEADER_TRANSACTION_MASK                 0xf0
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 & BT_HIDP_HEADER_TRANSACTION_MASK;
238                 param = header & BT_HIDP_HEADER_PARAMETER_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 BT_HIDP_TRANSACTION_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                                 if (data.buffer)
249                                         memcpy(data.buffer, buffer, len);
250                         break;
251                         case BT_HIDP_TRANSACTION_HID_CONTROL:
252                                 BT_INFO("HID CONTROL");
253                                 data.type = HTYPE_TRANS_HID_CONTROL;
254                                 data.buffer_size = len;
255                                 data.buffer = (char *) malloc(sizeof(char) * len);
256                                 if (data.buffer)
257                                         memcpy(data.buffer, buffer, len);
258                         break;
259                         case BT_HIDP_TRANSACTION_DATA:
260                                 BT_INFO("TRANS DATA");
261                                 data.type = HTYPE_TRANS_DATA;
262                                 if ( param & BT_HIDP_DATA_IN_RTYPE) {
263                                         BT_INFO("Input Report");
264                                         data.param = PTYPE_DATA_RTYPE_INPUT;
265                                         data.buffer_size = len;
266                                         data.buffer = (char *) malloc(sizeof(char) * len);
267                                         if (data.buffer)
268                                                 memcpy(data.buffer, buffer, len);
269                                 }
270                                 else {
271                                         BT_INFO("Out Report");
272                                         data.param = PTYPE_DATA_RTYPE_OUTPUT;
273                                         data.buffer_size = len;
274                                         data.buffer = (char *) malloc(sizeof(char) * len);
275                                         if (data.buffer)
276                                                 memcpy(data.buffer, buffer, len);
277                                 }
278                         break;
279                         case BT_HIDP_TRANSACTION_GET_REPORT: {
280                                 BT_INFO("Get Report");
281                                 data.type = HTYPE_TRANS_GET_REPORT;
282                                 if (param & BT_HIDP_DATA_IN_RTYPE) {
283                                         BT_INFO("Input Report");
284                                         data.param = PTYPE_DATA_RTYPE_INPUT;
285                                 } else {
286                                         BT_INFO("Output Report");
287                                         data.param = PTYPE_DATA_RTYPE_OUTPUT;
288                                 }
289                                 data.buffer_size = len;
290                                 data.buffer = (char *) malloc(sizeof(char) * len);
291                                 if (data.buffer)
292                                         memcpy(data.buffer, buffer, len);
293                                 break;
294                         }
295                         case BT_HIDP_TRANSACTION_SET_REPORT: {
296                                 BT_INFO("Set Report");
297                                 data.type = HTYPE_TRANS_SET_REPORT;
298                                 if (param & BT_HIDP_DATA_IN_RTYPE) {
299                                         BT_INFO("Input Report");
300                                         data.param = PTYPE_DATA_RTYPE_INPUT;
301                                 } else {
302                                         BT_INFO("Output Report");
303                                         data.param = PTYPE_DATA_RTYPE_OUTPUT;
304                                 }
305                                 data.buffer_size = len;
306                                 data.buffer = (char *) malloc(sizeof(char) * len);
307                                 if (data.buffer)
308                                         memcpy(data.buffer, buffer, len);
309                                 break;
310                         }
311                         case BT_HIDP_TRANSACTION_GET_PROTOCOL:{
312                                 BT_INFO("Get_PROTOCOL");
313                                 data.type = HTYPE_TRANS_GET_PROTOCOL;
314                                 data.param = PTYPE_DATA_RTYPE_INPUT;
315                                 data.buffer_size = len;
316                                 data.buffer = (char *) malloc(sizeof(char) * len);
317                                 if (data.buffer)
318                                         memcpy(data.buffer, buffer, len);
319                                 break;
320                         }
321                         case BT_HIDP_TRANSACTION_SET_PROTOCOL:{
322                                 BT_INFO("Set_PROTOCOL");
323                                 data.type = HTYPE_TRANS_SET_PROTOCOL;
324                                 data.param = PTYPE_DATA_RTYPE_INPUT;
325                                 data.buffer_size = len;
326                                 data.buffer = (char *) malloc(sizeof(char) * len);
327                                 if (data.buffer)
328                                         memcpy(data.buffer, buffer, len);
329                                 break;
330                         }
331                         default: {
332                                 BT_INFO("unsupported HIDP control message");
333                                 BT_ERR("Send Handshake Message");
334                                 guint8 type = BT_HIDP_TRANSACTION_HANDSHAKE |
335                                         BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST;
336                                 data.type = HTYPE_TRANS_UNKNOWN;
337                                 int fd = g_io_channel_unix_get_fd(chan);
338                                 int bytes = write(fd,  &type, sizeof(type));
339                                 BT_INFO("Bytes Written %d", bytes);
340                                 break;
341                         }
342                 }
343                 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
344                 if (event_info == NULL) {
345                         g_free(data.buffer);
346                         g_free((char *)data.address);
347                         return FALSE;
348                 }
349
350                 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
351                                 BLUETOOTH_ERROR_NONE, &data,
352                                 event_info->cb, event_info->user_data);
353
354                 g_free(data.buffer);
355                 g_free((char *)data.address);
356         } else {
357                 BT_INFO("Error while reading data");
358         }
359         return TRUE;
360 }
361
362 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
363 {
364         hid_info_t *info = NULL;
365         hid_connected_device_info_t *dev_info = NULL;
366         bt_event_info_t *event_info = NULL;
367         char address[18];
368         info = hid_info;
369
370         if (info == NULL)
371                 return -1;
372         _bt_convert_addr_type_to_string((char *)address, addr->addr);
373         BT_INFO("Address [%s]", address);
374         dev_info = __find_hid_info_with_address(address);
375         if (dev_info == NULL) {
376                 dev_info = (hid_connected_device_info_t *)
377                         g_malloc0(sizeof(hid_connected_device_info_t));
378                 if (dev_info == NULL) {
379                         BT_ERR("Fail to allocation memory");
380                         return -1;
381                 }
382
383                 dev_info->intr_fd = -1;
384                 dev_info->ctrl_fd = -1;
385                 dev_info->intr_fd = fd;
386                 dev_info->address = g_strdup(address);
387                 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
388                 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
389                 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
390
391                 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
392                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
393                                 __received_cb, dev_info);
394                 hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
395         } else {
396                 dev_info->ctrl_fd = fd;
397                 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
398                 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
399                 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
400
401                 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
402                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
403                                 __received_cb, dev_info);
404         }
405         if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1) {
406                 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
407                 if (event_info)
408                         __hid_connected_cb(dev_info, event_info);
409         }
410
411         return 0;
412 }
413 static hid_info_t *__register_method()
414 {
415         int object_id;
416         hid_info_t *info = NULL;
417         char *path = NULL;
418         path = g_strdup_printf("/org/socket/server/%d", getpid());
419
420         object_id = _bt_register_new_conn(path, new_hid_connection);
421         if (object_id < 0) {
422                 return NULL;
423         }
424         info = g_new(hid_info_t, 1);
425         info->object_id = (guint)object_id;
426         info->path = path;
427         info->id = 0;
428         info->device_list = NULL;
429
430         return info;
431 }
432
433 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
434 {
435         int ret;
436
437         /* Register HID Device events */
438         BT_INFO("BT_HID_DEVICE_EVENT");
439         ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
440
441         if (ret != BLUETOOTH_ERROR_NONE &&
442              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
443                 BT_ERR("Fail to init the event handler");
444                 return ret;
445         }
446
447         _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
448
449         return BLUETOOTH_ERROR_NONE;
450 }
451
452 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
453 {
454         int ret;
455
456         ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
457
458         if (ret != BLUETOOTH_ERROR_NONE) {
459                 BT_ERR("Fail to deinit the event handler");
460                 return ret;
461         }
462
463         _bt_set_user_data(BT_HID, NULL, NULL);
464
465         return BLUETOOTH_ERROR_NONE;
466 }
467
468 BT_EXPORT_API int bluetooth_hid_device_activate(void)
469 {
470         bt_register_profile_info_t profile_info;
471         int result = BLUETOOTH_ERROR_NONE;
472
473         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
474                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
475                 BT_ERR("Don't have a privilege to use this API");
476                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
477         }
478
479         if (hid_info != NULL)
480                 return BLUETOOTH_ERROR_IN_PROGRESS;
481
482         hid_info = __register_method();
483         if (hid_info == NULL)
484                 return BLUETOOTH_ERROR_INTERNAL;
485
486         hid_info->uuid = g_strdup(HID_UUID);
487
488         profile_info.authentication = TRUE;
489         profile_info.authorization = TRUE;
490         profile_info.obj_path = hid_info->path;
491         profile_info.role = g_strdup("Hid");
492         profile_info.service = hid_info->uuid;
493         profile_info.uuid = hid_info->uuid;
494
495         BT_INFO("uuid %s", profile_info.uuid);
496         result = _bt_register_profile_platform(&profile_info, FALSE);
497
498         return result;
499 }
500
501 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
502 {
503         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
504                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
505                 BT_ERR("Don't have a privilege to use this API");
506                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
507         }
508
509         if (hid_info == NULL)
510                 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
511
512         _bt_unregister_profile(hid_info->path);
513
514         __free_hid_info(hid_info);
515         hid_info = NULL;
516         return BLUETOOTH_ERROR_NONE;
517 }
518
519 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
520 {
521         char device_address[BT_ADDRESS_STRING_SIZE] = {0};
522         hid_connected_device_info_t *info = NULL;
523         int ret;
524         BT_DBG("+");
525         BT_CHECK_PARAMETER(remote_addr, return);
526
527         info = __find_hid_info_with_address(remote_addr);
528         if (info) {
529                 BT_ERR("Connection Already Exists");
530                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
531         }
532         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
533                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
534                 BT_ERR("Don't have a privilege to use this API");
535                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
536         }
537
538         memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
539         ret = _bt_connect_profile(device_address, HID_UUID, NULL, NULL);
540
541         return ret;
542 }
543 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
544 {
545         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
546                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
547                 BT_ERR("Don't have a privilege to use this API");
548                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
549         }
550         hid_connected_device_info_t *info = NULL;
551
552         info = __find_hid_info_with_address(remote_addr);
553         if (info == NULL)
554                 return BLUETOOTH_ERROR_INVALID_PARAM;
555
556         _bt_disconnect_profile((char *)remote_addr, HID_UUID, NULL, NULL);
557
558         info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
559
560         BT_DBG("-");
561         return BLUETOOTH_ERROR_NONE;
562 }
563 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
564                                         hid_send_mouse_event_t send_event)
565 {
566         int result;
567         int written = 0;
568         int socket_fd;
569         hid_connected_device_info_t *info = NULL;
570
571         switch (privilege_token_send_mouse) {
572         case 0:
573                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
574
575                 if (result == BLUETOOTH_ERROR_NONE) {
576                         privilege_token_send_mouse = 1; /* Have a permission */
577                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
578                         BT_ERR("Don't have a privilege to use this API");
579                         privilege_token_send_mouse = -1; /* Don't have a permission */
580                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
581                 } else {
582                         /* Just break - It is not related with permission error */
583                 }
584                 break;
585         case 1:
586                 /* Already have a privilege */
587                 break;
588         case -1:
589                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
590         default:
591                 /* Invalid privilge token value */
592                 return BLUETOOTH_ERROR_INTERNAL;
593         }
594         info = __find_hid_info_with_address(remote_addr);
595         if (info == NULL) {
596                 BT_ERR("Connection Information not found");
597                 return BLUETOOTH_ERROR_INVALID_PARAM;
598         }
599
600         if (info->intr_fd != -1 && info->ctrl_fd == -1)
601                 socket_fd = info->intr_fd;
602         else
603                 socket_fd = info->ctrl_fd;
604
605         written = write(socket_fd, &send_event, sizeof(send_event));
606
607         return written;
608 }
609
610 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
611                                         hid_send_key_event_t send_event)
612 {
613         int result;
614         int written = 0;
615         int socket_fd;
616         hid_connected_device_info_t *info = NULL;
617
618         switch (privilege_token_send_key) {
619         case 0:
620                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_KEY_EVENT);
621
622                 if (result == BLUETOOTH_ERROR_NONE) {
623                         privilege_token_send_key = 1; /* Have a permission */
624                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
625                         BT_ERR("Don't have a privilege to use this API");
626                         privilege_token_send_key = -1; /* Don't have a permission */
627                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
628                 } else {
629                         /* Just break - It is not related with permission error */
630                 }
631                 break;
632         case 1:
633                 /* Already have a privilege */
634                 break;
635         case -1:
636                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
637         default:
638                 /* Invalid privilge token value */
639                 return BLUETOOTH_ERROR_INTERNAL;
640         }
641
642         info = __find_hid_info_with_address(remote_addr);
643         if (info == NULL) {
644                 BT_ERR("Connection Information not found");
645                 return BLUETOOTH_ERROR_INVALID_PARAM;
646         }
647
648         if (info->intr_fd != -1 && info->ctrl_fd == -1)
649                 socket_fd = info->intr_fd;
650         else
651                 socket_fd = info->ctrl_fd;
652
653         written = write(socket_fd, &send_event, sizeof(send_event));
654         return written;
655 }
656
657 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
658                                 bt_hid_header_type_t htype,
659                                 bt_hid_param_type_t ptype,
660                                 const char *data,
661                                 unsigned int data_len)
662 {
663         int result;
664         struct reports output_report = { 0 };
665         int bytes = 0;
666         hid_connected_device_info_t *info = NULL;
667         info = __find_hid_info_with_address(remote_addr);
668         if (info == NULL) {
669                 BT_ERR("Connection Information not found");
670                 return BLUETOOTH_ERROR_INVALID_PARAM;
671         }
672
673         switch (privilege_token_reply) {
674         case 0:
675                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
676
677                 if (result == BLUETOOTH_ERROR_NONE) {
678                         privilege_token_reply = 1; /* Have a permission */
679                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
680                         BT_ERR("Don't have a privilege to use this API");
681                         privilege_token_reply = -1; /* Don't have a permission */
682                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
683                 } else {
684                         /* Just break - It is not related with permission error */
685                 }
686                 break;
687         case 1:
688                 /* Already have a privilege */
689                 break;
690         case -1:
691                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
692         default:
693                 /* Invalid privilge token value */
694                 return BLUETOOTH_ERROR_INTERNAL;
695         }
696
697         BT_INFO("htype %d ptype %d", htype, ptype);
698         switch(htype) {
699                 case HTYPE_TRANS_GET_REPORT: {
700                         switch(ptype) {
701                                 case PTYPE_DATA_RTYPE_INPUT: {
702                                         output_report.type = BT_HIDP_TRANSACTION_DATA |
703                                                         BT_HIDP_DATA_IN_RTYPE;
704                                         memcpy(output_report.rep_data, data, data_len);
705                                         bytes = write(info->intr_fd, &output_report,
706                                                                 sizeof(output_report));
707                                         BT_DBG("Bytes Written %d", bytes);
708                                         break;
709                                 }
710                                 default:
711                                         BT_INFO("Not Supported");
712                                         break;
713                         }
714                         break;
715                 case HTYPE_TRANS_GET_PROTOCOL: {
716                         BT_DBG("Replying to Get_PROTOCOL");
717                         output_report.type = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_OUT_RTYPE;
718                         output_report.rep_data[0] = data[0];
719                         bytes = write(info->intr_fd, &output_report, 2);
720                         BT_DBG("Bytes Written %d", bytes);
721                         break;
722                 }
723                 case HTYPE_TRANS_SET_PROTOCOL: {
724                         BT_DBG("Reply to Set_Protocol");
725                         output_report.type = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_IN_RTYPE;
726                         memcpy(output_report.rep_data, data, data_len);
727                         bytes = write(info->ctrl_fd, &output_report,
728                                         sizeof(output_report));
729                         BT_DBG("Bytes Written %d", bytes);
730                         break;
731                 }
732                 case HTYPE_TRANS_HANDSHAKE: {
733                         BT_DBG("Replying Handshake");
734                         output_report.type = BT_HIDP_TRANSACTION_HANDSHAKE | data[0];
735                         memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
736                         bytes = write(info->intr_fd,  &output_report.type,
737                                         sizeof(output_report.type));
738                         BT_DBG("Bytes Written %d", bytes);
739                         break;
740                 }
741                         default:
742                                 break;
743                 }
744         }
745         return bytes;
746 }