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