2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <gio/gunixfdlist.h>
19 #include <sys/socket.h>
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"
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
33 /* HIDP header masks */
34 #define BT_HID_HEADER_TRANS_MASK 0xf0
35 #define BT_HID_HEADER_PARAM_MASK 0x0f
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
49 #define BT_HID_DATA_RTYPE_INPUT 0x01
50 #define BT_HID_DATA_RTYPE_OUTPUT 0x02
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
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"
67 GIOChannel *ctrl_data_io;
68 GIOChannel *intr_data_io;
72 guint disconnect_idle_id;
73 } hid_connected_device_info_t;
78 } __attribute__((__packed__));
80 static GSList *device_list;
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
88 static int privilege_token_send_mouse = 0;
89 static int privilege_token_send_key = 0;
90 static int privilege_token_reply = 0;
92 static GVariant* __bt_hid_agent_dbus_send(const char *path,
93 const char *interface, const char *method,
94 GError **err, GVariant *parameters)
96 GVariant *reply = NULL;
97 GDBusProxy *proxy = NULL;
98 GDBusConnection *conn = NULL;
100 conn = _bt_gdbus_get_system_gconn();
101 retv_if(conn == NULL, NULL);
103 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
104 NULL, BT_HID_SERVICE_NAME, path, interface, NULL, err);
106 BT_ERR("Unable to allocate new proxy");
110 reply = g_dbus_proxy_call_sync(proxy, method, parameters,
111 G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
113 g_object_unref(proxy);
117 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
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)
129 static void __hid_connected_cb(hid_connected_device_info_t *info,
132 bluetooth_device_address_t bd_addr;
133 bt_event_info_t *event_info = NULL;
135 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
136 if (event_info == NULL)
139 memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
140 _bt_convert_addr_string_to_type(bd_addr.addr, info->address);
142 if (result == BLUETOOTH_ERROR_NONE)
143 BT_INFO_C("Connected [HID Device]");
145 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
147 event_info->cb, event_info->user_data);
150 static void __hid_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
155 GError *error = NULL;
156 GVariant *ret = NULL;
157 hid_connected_device_info_t info;
162 ret = g_dbus_proxy_call_finish(proxy, res, &error);
164 g_dbus_error_strip_remote_error(error);
165 BT_ERR("Error : %s \n", error->message);
170 info.address = g_malloc0(BT_ADDRESS_STRING_SIZE);
172 path = g_dbus_proxy_get_object_path(proxy);
173 _bt_convert_device_path_to_address(path, info.address);
175 if (g_strcmp0(error->message, "Already Connected") == 0) {
176 bluetooth_device_address_t dev_address = { {0} };
177 int ctrl = -1, intr = -1;
179 _bt_convert_addr_string_to_type(dev_address.addr,
181 _bt_hid_device_get_fd(info.address, &ctrl, &intr);
182 if (ctrl != -1 && intr != -1)
183 _bt_hid_new_connection(&dev_address, ctrl, intr);
185 BT_ERR("fd is invalid.(ctrl=%d, intr=%d)", ctrl, intr);
187 if (g_strcmp0(error->message, "In Progress") == 0)
188 result = BLUETOOTH_ERROR_IN_PROGRESS;
190 result = BLUETOOTH_ERROR_INTERNAL;
192 __hid_connected_cb(&info, result);
195 g_free(info.address);
198 g_variant_unref(ret);
202 g_object_unref(proxy);
207 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
209 bluetooth_device_address_t bd_addr;
210 bt_event_info_t *event_info;
212 BT_INFO_C("Disconnected [HID Device]");
213 device_list = g_slist_remove(device_list, info);
214 if (info->ctrl_data_id > 0) {
215 g_source_remove(info->ctrl_data_id);
216 info->ctrl_data_id = 0;
218 if (info->intr_data_id > 0) {
219 g_source_remove(info->intr_data_id);
220 info->intr_data_id = 0;
223 if (info->ctrl_data_io) {
224 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
225 g_io_channel_unref(info->ctrl_data_io);
226 info->ctrl_data_io = NULL;
228 if (info->intr_data_io) {
229 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
230 g_io_channel_unref(info->intr_data_io);
231 info->intr_data_io = NULL;
233 if (info->intr_fd >= 0) {
234 close(info->ctrl_fd);
235 close(info->intr_fd);
239 info->disconnect_idle_id = 0;
240 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
241 if (event_info != NULL) {
242 memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
243 _bt_convert_addr_string_to_type(bd_addr.addr , info->address);
244 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
245 BLUETOOTH_ERROR_NONE, &bd_addr,
246 event_info->cb, event_info->user_data);
249 g_free(info->address);
255 static gboolean __is_error_by_disconnect(GError *err)
257 return !g_strcmp0(err->message, "Connection reset by peer") ||
258 !g_strcmp0(err->message, "Connection timed out") ||
259 !g_strcmp0(err->message, "Software caused connection abort");
262 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
265 hid_connected_device_info_t *info = data;
266 GIOStatus status = G_IO_STATUS_NORMAL;
267 char buffer[BT_RFCOMM_BUFFER_LEN];
270 guint8 header, type, param;
271 bt_event_info_t *event_info;
272 retv_if(info == NULL, FALSE);
274 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
275 BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
276 if (info->disconnect_idle_id > 0) {
277 BT_INFO("Disconnect idle still not process remove source");
278 g_source_remove(info->disconnect_idle_id);
279 info->disconnect_idle_id = 0;
281 __hid_disconnect(info);
285 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
287 if (status == G_IO_STATUS_NORMAL) {
288 BT_INFO("Parsing Data");
289 bluetooth_hid_received_data_t data = {0};
291 type = header & BT_HID_HEADER_TRANS_MASK;
292 param = header & BT_HID_HEADER_PARAM_MASK;
293 BT_INFO("type %d , param %d", type, param);
294 BT_INFO("Data Reveived from %s" , info->address);
296 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
297 if (event_info == NULL)
300 data.address = g_strdup(info->address);
302 case BT_HID_TRANS_HANDSHAKE:
303 BT_INFO("TRANS HANDSHAKE");
304 data.type = HTYPE_TRANS_HANDSHAKE;
305 data.buffer_size = len;
306 data.buffer = (char *) malloc(sizeof(char) * len);
308 memcpy(data.buffer, buffer, len);
311 case BT_HID_TRANS_HID_CONTROL:
312 BT_INFO("HID CONTROL");
313 data.type = HTYPE_TRANS_HID_CONTROL;
314 data.buffer_size = len;
315 data.buffer = (char *) malloc(sizeof(char) * len);
317 memcpy(data.buffer, buffer, len);
320 case BT_HID_TRANS_DATA:
321 BT_INFO("TRANS DATA");
322 data.type = HTYPE_TRANS_DATA;
323 if (param & BT_HID_DATA_RTYPE_INPUT) {
324 BT_INFO("Input Report");
325 data.param = PTYPE_DATA_RTYPE_INPUT;
326 data.buffer_size = len;
327 data.buffer = (char *) malloc(sizeof(char) * len);
329 memcpy(data.buffer, buffer, len);
331 BT_INFO("Out Report");
332 data.param = PTYPE_DATA_RTYPE_OUTPUT;
333 data.buffer_size = len;
334 data.buffer = (char *) malloc(sizeof(char) * len);
336 memcpy(data.buffer, buffer, len);
340 case BT_HID_TRANS_GET_REPORT: {
341 BT_INFO("Get Report");
342 data.type = HTYPE_TRANS_GET_REPORT;
343 if (param & BT_HID_DATA_RTYPE_INPUT) {
344 BT_INFO("Input Report");
345 data.param = PTYPE_DATA_RTYPE_INPUT;
347 BT_INFO("Output Report");
348 data.param = PTYPE_DATA_RTYPE_OUTPUT;
350 data.buffer_size = len;
351 data.buffer = (char *) malloc(sizeof(char) * len);
353 memcpy(data.buffer, buffer, len);
357 case BT_HID_TRANS_SET_REPORT: {
358 BT_INFO("Set Report");
359 data.type = HTYPE_TRANS_SET_REPORT;
360 if (param & BT_HID_DATA_RTYPE_INPUT) {
361 BT_INFO("Input Report");
362 data.param = PTYPE_DATA_RTYPE_INPUT;
364 BT_INFO("Output Report");
365 data.param = PTYPE_DATA_RTYPE_OUTPUT;
367 data.buffer_size = len;
368 data.buffer = (char *) malloc(sizeof(char) * len);
370 memcpy(data.buffer, buffer, len);
374 case BT_HID_TRANS_GET_PROTOCOL:{
375 BT_INFO("Get_PROTOCOL");
376 data.type = HTYPE_TRANS_GET_PROTOCOL;
377 data.param = PTYPE_DATA_RTYPE_INPUT;
378 data.buffer_size = len;
379 data.buffer = (char *) malloc(sizeof(char) * len);
381 memcpy(data.buffer, buffer, len);
385 case BT_HID_TRANS_SET_PROTOCOL:{
386 BT_INFO("Set_PROTOCOL");
387 data.type = HTYPE_TRANS_SET_PROTOCOL;
388 data.param = PTYPE_DATA_RTYPE_INPUT;
389 data.buffer_size = len;
390 data.buffer = (char *) malloc(sizeof(char) * len);
392 memcpy(data.buffer, buffer, len);
396 case BT_HID_TRANS_GET_IDLE:{
398 data.type = HTYPE_TRANS_GET_IDLE;
399 data.param = PTYPE_DATA_RTYPE_INPUT;
400 data.buffer_size = len;
401 data.buffer = (char *) malloc(sizeof(char) * len);
403 memcpy(data.buffer, buffer, len);
407 case BT_HID_TRANS_SET_IDLE:{
409 data.type = HTYPE_TRANS_SET_IDLE;
410 data.param = PTYPE_DATA_RTYPE_INPUT;
411 data.buffer_size = len;
412 data.buffer = (char *) malloc(sizeof(char) * len);
414 memcpy(data.buffer, buffer, len);
419 BT_INFO("unsupported HIDP control message");
420 BT_ERR("Send Handshake Message");
421 guint8 type = BT_HID_TRANS_HANDSHAKE |
422 BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
423 data.type = HTYPE_TRANS_UNKNOWN;
424 int fd = g_io_channel_unix_get_fd(chan);
425 int bytes = write(fd, &type, sizeof(type));
426 BT_INFO("Bytes Written %d", bytes);
431 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
432 BLUETOOTH_ERROR_NONE, &data,
433 event_info->cb, event_info->user_data);
438 g_free((char *)data.address);
440 BT_ERR("Error while reading data %d [%s]", status, info->address);
442 BT_ERR("IO Channel read error [%s]", err->message);
443 if (status == G_IO_STATUS_ERROR &&
444 __is_error_by_disconnect(err)) {
445 BT_DBG("cond : %d", cond);
447 __hid_disconnect(info);
451 } else if (status == G_IO_STATUS_EOF) {
452 __hid_disconnect(info);
459 static void __free_hid_info(void *data)
463 hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
465 if (dev_info->disconnect_idle_id > 0) {
466 BT_INFO("Disconnect idle still not process remove source");
467 g_source_remove(dev_info->disconnect_idle_id);
468 dev_info->disconnect_idle_id = 0;
470 __hid_disconnect(dev_info);
473 int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
476 int ret = BLUETOOTH_ERROR_NONE;
478 GVariant *result = NULL;
480 GDBusConnection *conn;
481 GDBusProxy *server_proxy;
484 GUnixFDList *out_fd_list = NULL;
485 conn = _bt_gdbus_get_system_gconn();
486 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
488 adapter_path = _bt_get_device_object_path((char *)address);
489 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
490 BT_INFO_C("Device : %s", adapter_path);
491 server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
493 adapter_path, "org.bluez.Input1", NULL, NULL);
494 g_free(adapter_path);
496 if (server_proxy == NULL) {
497 BT_ERR("Failed to get the network server proxy\n");
498 return BLUETOOTH_ERROR_INTERNAL;
501 result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
503 G_DBUS_CALL_FLAGS_NONE,
509 if (result == NULL) {
511 g_dbus_error_strip_remote_error(err);
512 BT_ERR("INPUT server register Error: %s\n", err->message);
513 if (g_strcmp0(err->message, "Already Exists") == 0)
514 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
516 ret = BLUETOOTH_ERROR_INTERNAL;
521 g_variant_get(result, "(hh)", &index1, &index2);
522 int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
523 int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
527 g_object_unref(out_fd_list);
528 g_variant_unref(result);
530 g_object_unref(server_proxy);
534 int _bt_hid_new_connection(bluetooth_device_address_t *addr,
535 int ctrl_fd, int intr_fd)
537 hid_connected_device_info_t *dev_info = NULL;
539 char secure_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
541 _bt_convert_addr_type_to_string((char *)address, addr->addr);
542 _bt_convert_addr_string_to_secure_string(secure_addr, address);
543 BT_INFO("Address [%s]", secure_addr);
544 dev_info = __find_hid_info_with_address(address);
545 if (dev_info != NULL)
546 __free_hid_info(dev_info);
548 dev_info = (hid_connected_device_info_t *)
549 g_malloc0(sizeof(hid_connected_device_info_t));
551 dev_info->ctrl_fd = ctrl_fd;
552 dev_info->intr_fd = intr_fd;
553 dev_info->address = g_strdup(address);
554 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
555 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
556 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
557 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
558 g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
559 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
560 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
561 g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
562 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
563 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
564 __received_cb, dev_info);
565 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
566 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
567 __received_cb, dev_info);
568 device_list = g_slist_append(device_list, dev_info);
570 __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
575 void _bt_hid_free_hid_info(void)
577 g_slist_free_full(device_list, __free_hid_info);
582 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
586 /* Register HID Device events */
587 BT_INFO("BT_HID_DEVICE_EVENT");
588 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
590 if (ret != BLUETOOTH_ERROR_NONE &&
591 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
592 BT_ERR("Fail to init the event handler");
596 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
598 return BLUETOOTH_ERROR_NONE;
601 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
605 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
607 if (ret != BLUETOOTH_ERROR_NONE) {
608 BT_ERR("Fail to deinit the event handler");
612 _bt_set_user_data(BT_HID, NULL, NULL);
614 return BLUETOOTH_ERROR_NONE;
617 BT_EXPORT_API int bluetooth_hid_device_activate(void)
622 BT_CHECK_ENABLED(return);
624 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
625 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
626 BT_ERR("Don't have a privilege to use this API");
627 return BLUETOOTH_ERROR_PERMISSION_DEINED;
630 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
631 BT_HID_SERVICE_INTERFACE,
632 "RegisterApplication", &err, NULL);
635 int ret = BLUETOOTH_ERROR_INTERNAL;
636 BT_ERR("Error returned in method call");
638 BT_ERR("Error = %s", err->message);
639 if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
640 ret = BLUETOOTH_ERROR_IN_PROGRESS;
642 ret = BLUETOOTH_ERROR_INTERNAL;
648 g_variant_unref(reply);
650 return BLUETOOTH_ERROR_NONE;
653 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
658 BT_CHECK_ENABLED(return);
660 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
661 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
662 BT_ERR("Don't have a privilege to use this API");
663 return BLUETOOTH_ERROR_PERMISSION_DEINED;
666 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
667 BT_HID_SERVICE_INTERFACE,
668 "UnregisterApplication", &err, NULL);
671 int ret = BLUETOOTH_ERROR_INTERNAL;
672 BT_ERR("Error returned in method call");
674 BT_ERR("Error = %s", err->message);
675 if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
676 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
678 ret = BLUETOOTH_ERROR_INTERNAL;
684 g_variant_unref(reply);
686 _bt_hid_free_hid_info();
688 return BLUETOOTH_ERROR_NONE;
691 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
693 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
694 hid_connected_device_info_t *info = NULL;
697 BT_CHECK_PARAMETER(remote_addr, return);
699 BT_CHECK_ENABLED(return);
701 info = __find_hid_info_with_address(remote_addr);
703 BT_ERR("Connection Already Exists");
704 return BLUETOOTH_ERROR_ALREADY_CONNECT;
706 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
707 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
708 BT_ERR("Don't have a privilege to use this API");
709 return BLUETOOTH_ERROR_PERMISSION_DEINED;
712 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
713 ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
714 __hid_connect_response_cb, NULL);
718 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
720 BT_CHECK_PARAMETER(remote_addr, return);
722 BT_CHECK_ENABLED(return);
724 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
725 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
726 BT_ERR("Don't have a privilege to use this API");
727 return BLUETOOTH_ERROR_PERMISSION_DEINED;
730 hid_connected_device_info_t *info = NULL;
732 info = __find_hid_info_with_address(remote_addr);
734 return BLUETOOTH_ERROR_INVALID_PARAM;
736 _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
738 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
741 return BLUETOOTH_ERROR_NONE;
743 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
744 hid_send_mouse_event_t send_event)
748 hid_connected_device_info_t *info = NULL;
750 BT_CHECK_PARAMETER(remote_addr, return);
752 switch (privilege_token_send_mouse) {
754 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
756 if (result == BLUETOOTH_ERROR_NONE) {
757 privilege_token_send_mouse = 1; /* Have a permission */
758 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
759 BT_ERR("Don't have a privilege to use this API");
760 privilege_token_send_mouse = -1; /* Don't have a permission */
761 return BLUETOOTH_ERROR_PERMISSION_DEINED;
763 /* Just break - It is not related with permission error */
767 /* Already have a privilege */
770 return BLUETOOTH_ERROR_PERMISSION_DEINED;
772 /* Invalid privilge token value */
773 return BLUETOOTH_ERROR_INTERNAL;
775 info = __find_hid_info_with_address(remote_addr);
777 BT_ERR("Connection Information not found");
778 return BLUETOOTH_ERROR_INVALID_PARAM;
781 if (info->intr_fd >= 0) {
782 written = write(info->intr_fd, &send_event, sizeof(send_event));
784 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
785 __free_hid_info(info);
786 return BLUETOOTH_ERROR_INTERNAL;
792 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
793 hid_send_key_event_t send_event)
797 hid_connected_device_info_t *info = NULL;
799 BT_CHECK_PARAMETER(remote_addr, return);
801 switch (privilege_token_send_key) {
803 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
805 if (result == BLUETOOTH_ERROR_NONE) {
806 privilege_token_send_key = 1; /* Have a permission */
807 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
808 BT_ERR("Don't have a privilege to use this API");
809 privilege_token_send_key = -1; /* Don't have a permission */
810 return BLUETOOTH_ERROR_PERMISSION_DEINED;
812 /* Just break - It is not related with permission error */
816 /* Already have a privilege */
819 return BLUETOOTH_ERROR_PERMISSION_DEINED;
821 /* Invalid privilge token value */
822 return BLUETOOTH_ERROR_INTERNAL;
825 info = __find_hid_info_with_address(remote_addr);
827 BT_ERR("Connection Information not found");
828 return BLUETOOTH_ERROR_INVALID_PARAM;
831 if (info->intr_fd >= 0) {
832 written = write(info->intr_fd, &send_event, sizeof(send_event));
834 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
835 __free_hid_info(info);
836 return BLUETOOTH_ERROR_INTERNAL;
842 BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
843 unsigned char btcode, unsigned char report_id,
844 const char *data, unsigned int data_len)
848 hid_connected_device_info_t *info = NULL;
849 char *send_event = NULL;
851 BT_CHECK_PARAMETER(remote_addr, return);
852 BT_CHECK_PARAMETER(data, return);
854 switch (privilege_token_send_key) {
856 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
858 if (result == BLUETOOTH_ERROR_NONE) {
859 privilege_token_send_key = 1; /* Have a permission */
860 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
861 BT_ERR("Don't have a privilege to use this API");
862 privilege_token_send_key = -1; /* Don't have a permission */
863 return BLUETOOTH_ERROR_PERMISSION_DEINED;
865 /* Just break - It is not related with permission error */
869 /* Already have a privilege */
872 return BLUETOOTH_ERROR_PERMISSION_DEINED;
874 /* Invalid privilge token value */
875 return BLUETOOTH_ERROR_INTERNAL;
878 info = __find_hid_info_with_address(remote_addr);
880 BT_ERR("Connection Information not found");
881 return BLUETOOTH_ERROR_INVALID_PARAM;
884 if (info->intr_fd >= 0) {
885 send_event = g_malloc0(data_len + 2);
887 send_event[0] = (char)btcode;
888 send_event[1] = (char)report_id;
889 memcpy(send_event + 2, data, data_len);
891 written = write(info->intr_fd, send_event, data_len + 2);
894 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
895 __free_hid_info(info);
896 return BLUETOOTH_ERROR_INTERNAL;
902 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
903 bt_hid_header_type_t htype,
904 bt_hid_param_type_t ptype,
906 unsigned int data_len)
909 struct reports output_report = { 0 };
911 hid_connected_device_info_t *info = NULL;
913 BT_CHECK_PARAMETER(remote_addr, return);
915 info = __find_hid_info_with_address(remote_addr);
917 BT_ERR("Connection Information not found");
918 return BLUETOOTH_ERROR_INVALID_PARAM;
921 if (info->ctrl_fd < 0) {
922 BT_ERR("ctrl_fd(%d) is invalid.", info->ctrl_fd);
923 __free_hid_info(info);
924 return BLUETOOTH_ERROR_INTERNAL;
927 switch (privilege_token_reply) {
929 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
931 if (result == BLUETOOTH_ERROR_NONE) {
932 privilege_token_reply = 1; /* Have a permission */
933 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
934 BT_ERR("Don't have a privilege to use this API");
935 privilege_token_reply = -1; /* Don't have a permission */
936 return BLUETOOTH_ERROR_PERMISSION_DEINED;
938 /* Just break - It is not related with permission error */
942 /* Already have a privilege */
945 return BLUETOOTH_ERROR_PERMISSION_DEINED;
947 /* Invalid privilge token value */
948 return BLUETOOTH_ERROR_INTERNAL;
951 BT_INFO("htype %d ptype %d", htype, ptype);
953 case HTYPE_TRANS_GET_REPORT: {
955 case PTYPE_DATA_RTYPE_INPUT: {
956 output_report.type = BT_HID_TRANS_DATA |
957 BT_HID_DATA_RTYPE_INPUT;
958 memcpy(output_report.rep_data, data, data_len);
959 bytes = write(info->ctrl_fd, &output_report,
960 sizeof(output_report));
961 BT_DBG("Bytes Written %d", bytes);
965 BT_INFO("Not Supported");
970 case HTYPE_TRANS_GET_PROTOCOL: {
971 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
972 output_report.rep_data[0] = data[0];
973 bytes = write(info->ctrl_fd, &output_report, 2);
977 case HTYPE_TRANS_SET_PROTOCOL: {
978 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
979 memcpy(output_report.rep_data, data, data_len);
980 bytes = write(info->ctrl_fd, &output_report,
981 sizeof(output_report));
985 case HTYPE_TRANS_HANDSHAKE: {
986 output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
987 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
988 bytes = write(info->ctrl_fd, &output_report.type,
989 sizeof(output_report.type));
993 case HTYPE_TRANS_GET_IDLE: {
994 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
995 output_report.rep_data[0] = data[0];
996 bytes = write(info->ctrl_fd, &output_report, 2);
1000 case HTYPE_TRANS_SET_IDLE: {
1001 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
1002 memcpy(output_report.rep_data, data, data_len);
1003 bytes = write(info->ctrl_fd, &output_report,
1004 sizeof(output_report));
1013 BT_DBG("Bytes Written %d", bytes);