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