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