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