Proceed HID connection procedure when it's already connected.
[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 HID_DEVICE_UUID "00001124-0000-1000-8000-00805f9b43bf"
30 #define REPORTID_MOUSE  1
31 #define BT_HID_BUFFER_LEN 100
32
33 /* HIDP header masks */
34 #define BT_HID_HEADER_TRANS_MASK                        0xf0
35 #define BT_HID_HEADER_PARAM_MASK                        0x0f
36
37 /* HIDP transaction types */
38 #define BT_HID_TRANS_HANDSHAKE                  0x00
39 #define BT_HID_TRANS_HID_CONTROL                        0x10
40 #define BT_HID_TRANS_GET_REPORT                 0x40
41 #define BT_HID_TRANS_SET_REPORT                 0x50
42 #define BT_HID_TRANS_GET_PROTOCOL                       0x60
43 #define BT_HID_TRANS_SET_PROTOCOL                       0x70
44 #define BT_HID_TRANS_GET_IDLE                   0x80
45 #define BT_HID_TRANS_SET_IDLE                   0x90
46 #define BT_HID_TRANS_DATA                               0xa0
47 #define BT_HID_TRANS_DATC                               0xb0
48
49 #define BT_HID_DATA_RTYPE_INPUT                 0x01
50 #define BT_HID_DATA_RTYPE_OUTPUT                        0x02
51
52 #define BT_HID_HSHK_SUCCESSFUL  0x00
53 #define BT_HID_HSHK_NOT_READY   0x01
54 #define BT_HID_HSHK_ERR_INVALID_REPORT_ID       0x02
55 #define BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST     0x03
56 #define BT_HID_HSHK_ERR_INVALID_PARAMETER       0x04
57 #define BT_HID_HSHK_ERR_UNKNOWN 0x0E
58 #define BT_HID_HSHK_ERR_FATAL   0x0F
59
60 #define BT_HID_SERVICE_NAME "org.bluez.hid_agent"
61 #define BT_HID_AGENT_OBJECT_PATH "/org/bluez/hid_agent"
62 #define BT_HID_SERVICE_INTERFACE "org.tizen.HidApp"
63
64 typedef struct {
65         int ctrl_fd;
66         int intr_fd;
67         GIOChannel *ctrl_data_io;
68         GIOChannel *intr_data_io;
69         guint ctrl_data_id;
70         guint intr_data_id;
71         char *address;
72         guint disconnect_idle_id;
73 } hid_connected_device_info_t;
74
75 struct reports {
76         guint8 type;
77         guint8 rep_data[20];
78 } __attribute__((__packed__));
79
80 static GSList *device_list;
81
82 /* Variable for privilege, only for write API,
83   before we should reduce time to bt-service dbus calling
84   -1 : Don't have a permission to access API
85   0 : Initial value, not yet check
86   1 : Have a permission to access API
87 */
88 static int privilege_token_send_mouse = 0;
89 static int privilege_token_send_key = 0;
90 static int privilege_token_reply = 0;
91
92 static GVariant* __bt_hid_agent_dbus_send(const char *path,
93                                 const char *interface,  const char *method,
94                                 GError **err, GVariant *parameters)
95 {
96         GVariant *reply = NULL;
97         GDBusProxy *proxy = NULL;
98         GDBusConnection *conn = NULL;
99
100         conn = _bt_gdbus_get_system_gconn();
101         retv_if(conn == NULL, NULL);
102
103         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
104                 NULL, BT_HID_SERVICE_NAME, path, interface, NULL, err);
105         if (proxy == NULL) {
106                 BT_ERR("Unable to allocate new proxy");
107                 return NULL;
108         }
109
110         reply = g_dbus_proxy_call_sync(proxy, method, parameters,
111                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
112
113         g_object_unref(proxy);
114         return reply;
115 }
116
117 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
118 {
119         GSList *l;
120
121         for (l = device_list; l != NULL; l = l->next) {
122                 hid_connected_device_info_t *info = l->data;
123                 if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
124                         return info;
125         }
126         return NULL;
127 }
128
129 static void __hid_connected_cb(hid_connected_device_info_t *info,
130                         int result)
131 {
132         bluetooth_device_address_t bd_addr;
133         bt_event_info_t *event_info = NULL;
134
135         event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
136         if (event_info == NULL)
137                 return;
138
139         memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
140         _bt_convert_addr_string_to_type(bd_addr.addr, info->address);
141
142         if (result == BLUETOOTH_ERROR_NONE)
143                 BT_INFO_C("Connected [HID Device]");
144
145         _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
146                         result, &bd_addr,
147                         event_info->cb, event_info->user_data);
148 }
149
150 static void __hid_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
151                         gpointer user_data)
152
153 {
154         int result;
155         GError *error = NULL;
156         GVariant *ret = NULL;
157         hid_connected_device_info_t info;
158         const char *path;
159
160         BT_DBG("+");
161
162         ret = g_dbus_proxy_call_finish(proxy, res, &error);
163         if (ret == NULL) {
164                 g_dbus_error_strip_remote_error(error);
165                 BT_ERR("Error : %s \n", error->message);
166
167                 info.ctrl_fd = -1;
168                 info.intr_fd = -1;
169
170                 info.address = g_malloc0(BT_ADDRESS_STRING_SIZE);
171
172                 path = g_dbus_proxy_get_object_path(proxy);
173                 _bt_convert_device_path_to_address(path, info.address);
174
175                 if (g_strcmp0(error->message, "Already Connected") == 0) {
176                         bluetooth_device_address_t dev_address = { {0} };
177                         int ctrl = -1, intr = -1;
178
179                         _bt_convert_addr_string_to_type(dev_address.addr,
180                                                         info.address);
181                         _bt_hid_device_get_fd(info.address, &ctrl, &intr);
182                         if (ctrl != -1 && intr != -1)
183                                 _bt_hid_new_connection(&dev_address, ctrl, intr);
184                         else
185                                 BT_ERR("fd is invalid.(ctrl=%d, intr=%d)", ctrl, intr);
186                 } else {
187                         if (g_strcmp0(error->message, "In Progress") == 0)
188                                 result = BLUETOOTH_ERROR_IN_PROGRESS;
189                         else
190                                 result = BLUETOOTH_ERROR_INTERNAL;
191
192                         __hid_connected_cb(&info, result);
193                 }
194
195                 g_free(info.address);
196                 g_error_free(error);
197         } else {
198                 g_variant_unref(ret);
199         }
200
201         if (proxy)
202                 g_object_unref(proxy);
203
204         BT_DBG("-");
205 }
206
207 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
208 {
209         bluetooth_device_address_t bd_addr;
210         bt_event_info_t *event_info;
211
212         BT_INFO_C("Disconnected [HID Device]");
213         device_list = g_slist_remove(device_list, info);
214         if (info->ctrl_data_id > 0) {
215                 g_source_remove(info->ctrl_data_id);
216                 info->ctrl_data_id = 0;
217         }
218         if (info->intr_data_id > 0) {
219                 g_source_remove(info->intr_data_id);
220                 info->intr_data_id = 0;
221         }
222
223         if (info->ctrl_data_io) {
224                 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
225                 g_io_channel_unref(info->ctrl_data_io);
226                 info->ctrl_data_io = NULL;
227         }
228         if (info->intr_data_io) {
229                 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
230                 g_io_channel_unref(info->intr_data_io);
231                 info->intr_data_io = NULL;
232         }
233         if (info->intr_fd >= 0) {
234                 close(info->ctrl_fd);
235                 close(info->intr_fd);
236                 info->intr_fd = -1;
237                 info->ctrl_fd = -1;
238         }
239         info->disconnect_idle_id = 0;
240         event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
241         if (event_info == NULL)
242                 return FALSE;
243
244         memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
245         _bt_convert_addr_string_to_type(bd_addr.addr , info->address);
246         _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
247                         BLUETOOTH_ERROR_NONE, &bd_addr,
248                         event_info->cb, event_info->user_data);
249         if (info->address)
250                 g_free(info->address);
251         g_free(info);
252         info = NULL;
253         BT_DBG("-");
254         return FALSE;
255 }
256
257 static gboolean __is_error_by_disconnect(GError *err)
258 {
259         return !g_strcmp0(err->message, "Connection reset by peer") ||
260                         !g_strcmp0(err->message, "Connection timed out") ||
261                         !g_strcmp0(err->message, "Software caused connection abort");
262 }
263
264 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
265                                                                 gpointer data)
266 {
267         hid_connected_device_info_t *info = data;
268         GIOStatus status = G_IO_STATUS_NORMAL;
269         char buffer[BT_RFCOMM_BUFFER_LEN];
270         gsize len = 0;
271         GError *err = NULL;
272         guint8  header, type, param;
273         bt_event_info_t *event_info;
274         retv_if(info == NULL, FALSE);
275
276         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
277                 BT_ERR_C("HID  disconnected: %d", info->ctrl_fd);
278                         if (info->disconnect_idle_id > 0) {
279                                 BT_INFO("Disconnect idle still not process remove source");
280                                 g_source_remove(info->disconnect_idle_id);
281                                 info->disconnect_idle_id = 0;
282                         }
283                 __hid_disconnect(info);
284                 return FALSE;
285         }
286
287         status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
288                         &len, &err);
289         if (status == G_IO_STATUS_NORMAL) {
290                 BT_INFO("Parsing Data");
291                 bluetooth_hid_received_data_t data = {0};
292                 header = buffer[0];
293                 type = header & BT_HID_HEADER_TRANS_MASK;
294                 param = header & BT_HID_HEADER_PARAM_MASK;
295                 BT_INFO("type %d , param %d", type, param);
296                 BT_INFO("Data Reveived from %s" , info->address);
297
298                 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
299                 if (event_info == NULL)
300                         return FALSE;
301
302                 data.address = g_strdup(info->address);
303                 switch (type) {
304                 case BT_HID_TRANS_HANDSHAKE:
305                         BT_INFO("TRANS HANDSHAKE");
306                         data.type = HTYPE_TRANS_HANDSHAKE;
307                         data.buffer_size = len;
308                         data.buffer = (char *) malloc(sizeof(char) * len);
309                         if (data.buffer)
310                                 memcpy(data.buffer, buffer, len);
311                 break;
312
313                 case BT_HID_TRANS_HID_CONTROL:
314                         BT_INFO("HID CONTROL");
315                         data.type = HTYPE_TRANS_HID_CONTROL;
316                         data.buffer_size = len;
317                         data.buffer = (char *) malloc(sizeof(char) * len);
318                         if (data.buffer)
319                                 memcpy(data.buffer, buffer, len);
320                 break;
321
322                 case BT_HID_TRANS_DATA:
323                         BT_INFO("TRANS DATA");
324                         data.type = HTYPE_TRANS_DATA;
325                         if (param & BT_HID_DATA_RTYPE_INPUT) {
326                                 BT_INFO("Input Report");
327                                 data.param = PTYPE_DATA_RTYPE_INPUT;
328                                 data.buffer_size = len;
329                                 data.buffer = (char *) malloc(sizeof(char) * len);
330                                 if (data.buffer)
331                                         memcpy(data.buffer, buffer, len);
332                         } else {
333                                 BT_INFO("Out Report");
334                                 data.param = PTYPE_DATA_RTYPE_OUTPUT;
335                                 data.buffer_size = len;
336                                 data.buffer = (char *) malloc(sizeof(char) * len);
337                                 if (data.buffer)
338                                         memcpy(data.buffer, buffer, len);
339                         }
340                 break;
341
342                 case BT_HID_TRANS_GET_REPORT: {
343                         BT_INFO("Get Report");
344                         data.type = HTYPE_TRANS_GET_REPORT;
345                         if (param & BT_HID_DATA_RTYPE_INPUT) {
346                                 BT_INFO("Input Report");
347                                 data.param = PTYPE_DATA_RTYPE_INPUT;
348                         } else {
349                                 BT_INFO("Output Report");
350                                 data.param = PTYPE_DATA_RTYPE_OUTPUT;
351                         }
352                         data.buffer_size = len;
353                         data.buffer = (char *) malloc(sizeof(char) * len);
354                         if (data.buffer)
355                                 memcpy(data.buffer, buffer, len);
356                         break;
357                 }
358
359                 case BT_HID_TRANS_SET_REPORT: {
360                         BT_INFO("Set Report");
361                         data.type = HTYPE_TRANS_SET_REPORT;
362                         if (param & BT_HID_DATA_RTYPE_INPUT) {
363                                 BT_INFO("Input Report");
364                                 data.param = PTYPE_DATA_RTYPE_INPUT;
365                         } else {
366                                 BT_INFO("Output Report");
367                                 data.param = PTYPE_DATA_RTYPE_OUTPUT;
368                         }
369                         data.buffer_size = len;
370                         data.buffer = (char *) malloc(sizeof(char) * len);
371                         if (data.buffer)
372                                 memcpy(data.buffer, buffer, len);
373                         break;
374                 }
375
376                 case BT_HID_TRANS_GET_PROTOCOL:{
377                         BT_INFO("Get_PROTOCOL");
378                         data.type = HTYPE_TRANS_GET_PROTOCOL;
379                         data.param = PTYPE_DATA_RTYPE_INPUT;
380                         data.buffer_size = len;
381                         data.buffer = (char *) malloc(sizeof(char) * len);
382                         if (data.buffer)
383                                 memcpy(data.buffer, buffer, len);
384                         break;
385                 }
386
387                 case BT_HID_TRANS_SET_PROTOCOL:{
388                         BT_INFO("Set_PROTOCOL");
389                         data.type = HTYPE_TRANS_SET_PROTOCOL;
390                         data.param = PTYPE_DATA_RTYPE_INPUT;
391                         data.buffer_size = len;
392                         data.buffer = (char *) malloc(sizeof(char) * len);
393                         if (data.buffer)
394                                 memcpy(data.buffer, buffer, len);
395                         break;
396                 }
397
398                 case BT_HID_TRANS_GET_IDLE:{
399                         BT_INFO("Get_IDLE");
400                         data.type = HTYPE_TRANS_GET_IDLE;
401                         data.param = PTYPE_DATA_RTYPE_INPUT;
402                         data.buffer_size = len;
403                         data.buffer = (char *) malloc(sizeof(char) * len);
404                         if (data.buffer)
405                                 memcpy(data.buffer, buffer, len);
406                         break;
407                 }
408
409                 case BT_HID_TRANS_SET_IDLE:{
410                         BT_INFO("Set_IDLE");
411                         data.type = HTYPE_TRANS_SET_IDLE;
412                         data.param = PTYPE_DATA_RTYPE_INPUT;
413                         data.buffer_size = len;
414                         data.buffer = (char *) malloc(sizeof(char) * len);
415                         if (data.buffer)
416                                 memcpy(data.buffer, buffer, len);
417                         break;
418                 }
419
420                 default: {
421                         BT_INFO("unsupported HIDP control message");
422                         BT_ERR("Send Handshake Message");
423                         guint8 type = BT_HID_TRANS_HANDSHAKE |
424                                 BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
425                         data.type = HTYPE_TRANS_UNKNOWN;
426                         int fd = g_io_channel_unix_get_fd(chan);
427                         int bytes = write(fd,  &type, sizeof(type));
428                         BT_INFO("Bytes Written %d", bytes);
429                         break;
430                 }
431         }
432
433         _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
434                                 BLUETOOTH_ERROR_NONE, &data,
435                                 event_info->cb, event_info->user_data);
436         if (data.buffer)
437                 g_free(data.buffer);
438
439         if (data.address)
440                 g_free((char *)data.address);
441         } else {
442                 BT_ERR("Error while reading data %d [%s]", status, info->address);
443                 if (err) {
444                         BT_ERR("IO Channel read error [%s]", err->message);
445                         if (status == G_IO_STATUS_ERROR &&
446                                         __is_error_by_disconnect(err)) {
447                                 BT_DBG("cond : %d", cond);
448                                 g_error_free(err);
449                                 __hid_disconnect(info);
450                                 return FALSE;
451                         }
452                         g_error_free(err);
453                 } else if (status == G_IO_STATUS_EOF) {
454                         __hid_disconnect(info);
455                         return FALSE;
456                 }
457         }
458         return TRUE;
459 }
460
461 static void __free_hid_info(void *data)
462 {
463         BT_DBG("");
464
465         hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
466
467         if (dev_info->disconnect_idle_id > 0) {
468                 BT_INFO("Disconnect idle still not process remove source");
469                 g_source_remove(dev_info->disconnect_idle_id);
470                 dev_info->disconnect_idle_id = 0;
471         }
472         __hid_disconnect(dev_info);
473 }
474
475 int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
476 {
477
478         int ret = BLUETOOTH_ERROR_NONE;
479         char *adapter_path;
480         GVariant *result = NULL;
481         GError *err = NULL;
482         GDBusConnection *conn;
483         GDBusProxy *server_proxy;
484         int index1 = 0;
485         int index2 = 0;
486         GUnixFDList *out_fd_list = NULL;
487         conn = _bt_gdbus_get_system_gconn();
488         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
489
490         adapter_path = _bt_get_device_object_path((char *)address);
491         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
492         BT_INFO_C("Device : %s", adapter_path);
493         server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
494                         NULL, BT_BLUEZ_NAME,
495                         adapter_path, "org.bluez.Input1",  NULL, NULL);
496         g_free(adapter_path);
497
498         if (server_proxy == NULL) {
499                 BT_ERR("Failed to get the network server proxy\n");
500                 return BLUETOOTH_ERROR_INTERNAL;
501         }
502
503         result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
504                                  NULL,
505                                  G_DBUS_CALL_FLAGS_NONE,
506                                  -1,
507                                  NULL,
508                                  &out_fd_list,
509                                  NULL,
510                                  &err);
511         if (result == NULL) {
512                 if (err != NULL) {
513                         g_dbus_error_strip_remote_error(err);
514                         BT_ERR("INPUT server register Error: %s\n", err->message);
515                         if (g_strcmp0(err->message, "Already Exists") == 0)
516                                 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
517                         else
518                                 ret = BLUETOOTH_ERROR_INTERNAL;
519
520                         g_error_free(err);
521                 }
522         } else {
523                 g_variant_get(result, "(hh)", &index1, &index2);
524                 int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
525                 int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
526
527                 *ctrl = fd1;
528                 *intr = fd2;
529                 g_object_unref(out_fd_list);
530                 g_variant_unref(result);
531         }
532         g_object_unref(server_proxy);
533         return ret;
534 }
535
536 int _bt_hid_new_connection(bluetooth_device_address_t *addr,
537                                 int ctrl_fd, int intr_fd)
538 {
539         hid_connected_device_info_t *dev_info = NULL;
540         char address[18];
541         char secure_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
542
543         _bt_convert_addr_type_to_string((char *)address, addr->addr);
544         _bt_convert_addr_string_to_secure_string(secure_addr, address);
545         BT_INFO("Address [%s]", secure_addr);
546         dev_info = __find_hid_info_with_address(address);
547         if (dev_info != NULL)
548                 __free_hid_info(dev_info);
549
550         dev_info = (hid_connected_device_info_t *)
551                 g_malloc0(sizeof(hid_connected_device_info_t));
552
553         dev_info->ctrl_fd = ctrl_fd;
554         dev_info->intr_fd = intr_fd;
555         dev_info->address = g_strdup(address);
556         dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
557         dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
558         g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
559         g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
560         g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
561         g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
562         g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
563         g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
564         dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
565                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
566                         __received_cb, dev_info);
567         dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
568                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
569                         __received_cb, dev_info);
570         device_list = g_slist_append(device_list, dev_info);
571
572         __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
573
574         return 0;
575 }
576
577 void _bt_hid_free_hid_info(void)
578 {
579         g_slist_free_full(device_list, __free_hid_info);
580
581         device_list = NULL;
582 }
583
584 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
585 {
586         int ret;
587
588         /* Register HID Device events */
589         BT_INFO("BT_HID_DEVICE_EVENT");
590         ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
591
592         if (ret != BLUETOOTH_ERROR_NONE &&
593              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
594                 BT_ERR("Fail to init the event handler");
595                 return ret;
596         }
597
598         _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
599
600         return BLUETOOTH_ERROR_NONE;
601 }
602
603 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
604 {
605         int ret;
606
607         ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
608
609         if (ret != BLUETOOTH_ERROR_NONE) {
610                 BT_ERR("Fail to deinit the event handler");
611                 return ret;
612         }
613
614         _bt_set_user_data(BT_HID, NULL, NULL);
615
616         return BLUETOOTH_ERROR_NONE;
617 }
618
619 BT_EXPORT_API int bluetooth_hid_device_activate(void)
620 {
621         GVariant *reply;
622         GError *err = NULL;
623
624         BT_CHECK_ENABLED(return);
625
626         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
627                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
628                 BT_ERR("Don't have a privilege to use this API");
629                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
630         }
631
632         reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
633                         BT_HID_SERVICE_INTERFACE,
634                         "RegisterApplication", &err, NULL);
635
636         if (!reply) {
637                 int ret = BLUETOOTH_ERROR_INTERNAL;
638                 BT_ERR("Error returned in method call");
639                 if (err) {
640                         BT_ERR("Error = %s", err->message);
641                         if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
642                                 ret = BLUETOOTH_ERROR_IN_PROGRESS;
643                         else
644                                 ret = BLUETOOTH_ERROR_INTERNAL;
645                         g_clear_error(&err);
646                 }
647                 return ret;
648         }
649
650         g_variant_unref(reply);
651
652         return BLUETOOTH_ERROR_NONE;
653 }
654
655 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
656 {
657         GVariant *reply;
658         GError *err = NULL;
659
660         BT_CHECK_ENABLED(return);
661
662         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
663                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
664                 BT_ERR("Don't have a privilege to use this API");
665                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
666         }
667
668         reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
669                         BT_HID_SERVICE_INTERFACE,
670                         "UnregisterApplication", &err, NULL);
671
672         if (!reply) {
673                 int ret = BLUETOOTH_ERROR_INTERNAL;
674                 BT_ERR("Error returned in method call");
675                 if (err) {
676                         BT_ERR("Error = %s", err->message);
677                         if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
678                                 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
679                         else
680                                 ret = BLUETOOTH_ERROR_INTERNAL;
681                         g_clear_error(&err);
682                 }
683                 return ret;
684         }
685
686         g_variant_unref(reply);
687
688         _bt_hid_free_hid_info();
689
690         return BLUETOOTH_ERROR_NONE;
691 }
692
693 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
694 {
695         char device_address[BT_ADDRESS_STRING_SIZE] = {0};
696         hid_connected_device_info_t *info = NULL;
697         int ret;
698         BT_DBG("+");
699         BT_CHECK_PARAMETER(remote_addr, return);
700
701         BT_CHECK_ENABLED(return);
702
703         info = __find_hid_info_with_address(remote_addr);
704         if (info) {
705                 BT_ERR("Connection Already Exists");
706                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
707         }
708         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
709                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
710                 BT_ERR("Don't have a privilege to use this API");
711                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
712         }
713
714         memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
715         ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
716                                 __hid_connect_response_cb, NULL);
717
718         return ret;
719 }
720 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
721 {
722         BT_CHECK_PARAMETER(remote_addr, return);
723
724         BT_CHECK_ENABLED(return);
725
726         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
727                  == BLUETOOTH_ERROR_PERMISSION_DEINED) {
728                 BT_ERR("Don't have a privilege to use this API");
729                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
730         }
731
732         hid_connected_device_info_t *info = NULL;
733
734         info = __find_hid_info_with_address(remote_addr);
735         if (info == NULL)
736                 return BLUETOOTH_ERROR_INVALID_PARAM;
737
738         _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
739
740         info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
741
742         BT_DBG("-");
743         return BLUETOOTH_ERROR_NONE;
744 }
745 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
746                                         hid_send_mouse_event_t send_event)
747 {
748         int result;
749         int written = 0;
750         hid_connected_device_info_t *info = NULL;
751
752         BT_CHECK_PARAMETER(remote_addr, return);
753
754         switch (privilege_token_send_mouse) {
755         case 0:
756                 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
757
758                 if (result == BLUETOOTH_ERROR_NONE) {
759                         privilege_token_send_mouse = 1; /* Have a permission */
760                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
761                         BT_ERR("Don't have a privilege to use this API");
762                         privilege_token_send_mouse = -1; /* Don't have a permission */
763                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
764                 } else {
765                         /* Just break - It is not related with permission error */
766                 }
767                 break;
768         case 1:
769                 /* Already have a privilege */
770                 break;
771         case -1:
772                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
773         default:
774                 /* Invalid privilge token value */
775                 return BLUETOOTH_ERROR_INTERNAL;
776         }
777         info = __find_hid_info_with_address(remote_addr);
778         if (info == NULL) {
779                 BT_ERR("Connection Information not found");
780                 return BLUETOOTH_ERROR_INVALID_PARAM;
781         }
782
783         if (info->intr_fd >= 0) {
784                 written = write(info->intr_fd, &send_event, sizeof(send_event));
785         } else {
786                 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
787                 __free_hid_info(info);
788                 return BLUETOOTH_ERROR_INTERNAL;
789         }
790
791         return written;
792 }
793
794 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
795                                         hid_send_key_event_t send_event)
796 {
797         int result;
798         int written = 0;
799         hid_connected_device_info_t *info = NULL;
800
801         BT_CHECK_PARAMETER(remote_addr, return);
802
803         switch (privilege_token_send_key) {
804         case 0:
805                 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
806
807                 if (result == BLUETOOTH_ERROR_NONE) {
808                         privilege_token_send_key = 1; /* Have a permission */
809                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
810                         BT_ERR("Don't have a privilege to use this API");
811                         privilege_token_send_key = -1; /* Don't have a permission */
812                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
813                 } else {
814                         /* Just break - It is not related with permission error */
815                 }
816                 break;
817         case 1:
818                 /* Already have a privilege */
819                 break;
820         case -1:
821                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
822         default:
823                 /* Invalid privilge token value */
824                 return BLUETOOTH_ERROR_INTERNAL;
825         }
826
827         info = __find_hid_info_with_address(remote_addr);
828         if (info == NULL) {
829                 BT_ERR("Connection Information not found");
830                 return BLUETOOTH_ERROR_INVALID_PARAM;
831         }
832
833         if (info->intr_fd >= 0) {
834                 written = write(info->intr_fd, &send_event, sizeof(send_event));
835         } else {
836                 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
837                 __free_hid_info(info);
838                 return BLUETOOTH_ERROR_INTERNAL;
839         }
840
841         return written;
842 }
843
844 BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
845                         unsigned char btcode, unsigned char report_id,
846                         const char *data, unsigned int data_len)
847 {
848         int result;
849         int written = 0;
850         hid_connected_device_info_t *info = NULL;
851         char *send_event = NULL;
852
853         BT_CHECK_PARAMETER(remote_addr, return);
854         BT_CHECK_PARAMETER(data, return);
855
856         switch (privilege_token_send_key) {
857         case 0:
858                 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
859
860                 if (result == BLUETOOTH_ERROR_NONE) {
861                         privilege_token_send_key = 1; /* Have a permission */
862                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
863                         BT_ERR("Don't have a privilege to use this API");
864                         privilege_token_send_key = -1; /* Don't have a permission */
865                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
866                 } else {
867                         /* Just break - It is not related with permission error */
868                 }
869                 break;
870         case 1:
871                 /* Already have a privilege */
872                 break;
873         case -1:
874                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
875         default:
876                 /* Invalid privilge token value */
877                 return BLUETOOTH_ERROR_INTERNAL;
878         }
879
880         info = __find_hid_info_with_address(remote_addr);
881         if (info == NULL) {
882                 BT_ERR("Connection Information not found");
883                 return BLUETOOTH_ERROR_INVALID_PARAM;
884         }
885
886         if (info->intr_fd >= 0) {
887                 send_event = g_malloc0(data_len + 2);
888
889                 send_event[0] = (char)btcode;
890                 send_event[1] = (char)report_id;
891                 memcpy(send_event + 2, data, data_len);
892
893                 written = write(info->intr_fd, send_event, data_len + 2);
894                 g_free(send_event);
895         } else {
896                 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
897                 __free_hid_info(info);
898                 return BLUETOOTH_ERROR_INTERNAL;
899         }
900
901         return written;
902 }
903
904 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
905                                 bt_hid_header_type_t htype,
906                                 bt_hid_param_type_t ptype,
907                                 const char *data,
908                                 unsigned int data_len)
909 {
910         int result;
911         struct reports output_report = { 0 };
912         int bytes = -1;
913         hid_connected_device_info_t *info = NULL;
914
915         BT_CHECK_PARAMETER(remote_addr, return);
916
917         info = __find_hid_info_with_address(remote_addr);
918         if (info == NULL) {
919                 BT_ERR("Connection Information not found");
920                 return BLUETOOTH_ERROR_INVALID_PARAM;
921         }
922
923         if (info->ctrl_fd < 0) {
924                 BT_ERR("ctrl_fd(%d) is invalid.", info->ctrl_fd);
925                 __free_hid_info(info);
926                 return BLUETOOTH_ERROR_INTERNAL;
927         }
928
929         switch (privilege_token_reply) {
930         case 0:
931                 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
932
933                 if (result == BLUETOOTH_ERROR_NONE) {
934                         privilege_token_reply = 1; /* Have a permission */
935                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
936                         BT_ERR("Don't have a privilege to use this API");
937                         privilege_token_reply = -1; /* Don't have a permission */
938                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
939                 } else {
940                         /* Just break - It is not related with permission error */
941                 }
942                 break;
943         case 1:
944                 /* Already have a privilege */
945                 break;
946         case -1:
947                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
948         default:
949                 /* Invalid privilge token value */
950                 return BLUETOOTH_ERROR_INTERNAL;
951         }
952
953         BT_INFO("htype %d ptype %d", htype, ptype);
954         switch (htype) {
955         case HTYPE_TRANS_GET_REPORT: {
956                 switch (ptype) {
957                 case PTYPE_DATA_RTYPE_INPUT: {
958                         output_report.type = BT_HID_TRANS_DATA |
959                                         BT_HID_DATA_RTYPE_INPUT;
960                         memcpy(output_report.rep_data, data, data_len);
961                         bytes = write(info->ctrl_fd, &output_report,
962                                                 sizeof(output_report));
963                         BT_DBG("Bytes Written %d", bytes);
964                         break;
965                 }
966                 default:
967                         BT_INFO("Not Supported");
968                         break;
969         }
970         break;
971
972         case HTYPE_TRANS_GET_PROTOCOL: {
973                 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
974                 output_report.rep_data[0] = data[0];
975                 bytes = write(info->ctrl_fd, &output_report, 2);
976                 break;
977         }
978
979         case HTYPE_TRANS_SET_PROTOCOL: {
980                 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
981                 memcpy(output_report.rep_data, data, data_len);
982                 bytes = write(info->ctrl_fd, &output_report,
983                                 sizeof(output_report));
984                 break;
985         }
986
987         case HTYPE_TRANS_HANDSHAKE: {
988                 output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
989                 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
990                 bytes = write(info->ctrl_fd,  &output_report.type,
991                                 sizeof(output_report.type));
992                 break;
993         }
994
995         case HTYPE_TRANS_GET_IDLE: {
996                 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
997                 output_report.rep_data[0] = data[0];
998                 bytes = write(info->ctrl_fd, &output_report, 2);
999                 break;
1000         }
1001
1002         case HTYPE_TRANS_SET_IDLE: {
1003                 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
1004                 memcpy(output_report.rep_data, data, data_len);
1005                 bytes = write(info->ctrl_fd, &output_report,
1006                                 sizeof(output_report));
1007                 break;
1008         }
1009
1010         default:
1011                 break;
1012                 }
1013         }
1014
1015         BT_DBG("Bytes Written %d", bytes);
1016
1017         return bytes;
1018 }