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