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)
244 memset(&bd_addr, 0x00, sizeof(bluetooth_device_address_t));
245 _bt_convert_addr_string_to_type(bd_addr.addr , info->address);
246 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
247 BLUETOOTH_ERROR_NONE, &bd_addr,
248 event_info->cb, event_info->user_data);
250 g_free(info->address);
257 static gboolean __is_error_by_disconnect(GError *err)
259 return !g_strcmp0(err->message, "Connection reset by peer") ||
260 !g_strcmp0(err->message, "Connection timed out") ||
261 !g_strcmp0(err->message, "Software caused connection abort");
264 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
267 hid_connected_device_info_t *info = data;
268 GIOStatus status = G_IO_STATUS_NORMAL;
269 char buffer[BT_RFCOMM_BUFFER_LEN];
272 guint8 header, type, param;
273 bt_event_info_t *event_info;
274 retv_if(info == NULL, FALSE);
276 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
277 BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
278 if (info->disconnect_idle_id > 0) {
279 BT_INFO("Disconnect idle still not process remove source");
280 g_source_remove(info->disconnect_idle_id);
281 info->disconnect_idle_id = 0;
283 __hid_disconnect(info);
287 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
289 if (status == G_IO_STATUS_NORMAL) {
290 BT_INFO("Parsing Data");
291 bluetooth_hid_received_data_t data = {0};
293 type = header & BT_HID_HEADER_TRANS_MASK;
294 param = header & BT_HID_HEADER_PARAM_MASK;
295 BT_INFO("type %d , param %d", type, param);
296 BT_INFO("Data Reveived from %s" , info->address);
298 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
299 if (event_info == NULL)
302 data.address = g_strdup(info->address);
304 case BT_HID_TRANS_HANDSHAKE:
305 BT_INFO("TRANS HANDSHAKE");
306 data.type = HTYPE_TRANS_HANDSHAKE;
307 data.buffer_size = len;
308 data.buffer = (char *) malloc(sizeof(char) * len);
310 memcpy(data.buffer, buffer, len);
313 case BT_HID_TRANS_HID_CONTROL:
314 BT_INFO("HID CONTROL");
315 data.type = HTYPE_TRANS_HID_CONTROL;
316 data.buffer_size = len;
317 data.buffer = (char *) malloc(sizeof(char) * len);
319 memcpy(data.buffer, buffer, len);
322 case BT_HID_TRANS_DATA:
323 BT_INFO("TRANS DATA");
324 data.type = HTYPE_TRANS_DATA;
325 if (param & BT_HID_DATA_RTYPE_INPUT) {
326 BT_INFO("Input Report");
327 data.param = PTYPE_DATA_RTYPE_INPUT;
328 data.buffer_size = len;
329 data.buffer = (char *) malloc(sizeof(char) * len);
331 memcpy(data.buffer, buffer, len);
333 BT_INFO("Out Report");
334 data.param = PTYPE_DATA_RTYPE_OUTPUT;
335 data.buffer_size = len;
336 data.buffer = (char *) malloc(sizeof(char) * len);
338 memcpy(data.buffer, buffer, len);
342 case BT_HID_TRANS_GET_REPORT: {
343 BT_INFO("Get Report");
344 data.type = HTYPE_TRANS_GET_REPORT;
345 if (param & BT_HID_DATA_RTYPE_INPUT) {
346 BT_INFO("Input Report");
347 data.param = PTYPE_DATA_RTYPE_INPUT;
349 BT_INFO("Output Report");
350 data.param = PTYPE_DATA_RTYPE_OUTPUT;
352 data.buffer_size = len;
353 data.buffer = (char *) malloc(sizeof(char) * len);
355 memcpy(data.buffer, buffer, len);
359 case BT_HID_TRANS_SET_REPORT: {
360 BT_INFO("Set Report");
361 data.type = HTYPE_TRANS_SET_REPORT;
362 if (param & BT_HID_DATA_RTYPE_INPUT) {
363 BT_INFO("Input Report");
364 data.param = PTYPE_DATA_RTYPE_INPUT;
366 BT_INFO("Output Report");
367 data.param = PTYPE_DATA_RTYPE_OUTPUT;
369 data.buffer_size = len;
370 data.buffer = (char *) malloc(sizeof(char) * len);
372 memcpy(data.buffer, buffer, len);
376 case BT_HID_TRANS_GET_PROTOCOL:{
377 BT_INFO("Get_PROTOCOL");
378 data.type = HTYPE_TRANS_GET_PROTOCOL;
379 data.param = PTYPE_DATA_RTYPE_INPUT;
380 data.buffer_size = len;
381 data.buffer = (char *) malloc(sizeof(char) * len);
383 memcpy(data.buffer, buffer, len);
387 case BT_HID_TRANS_SET_PROTOCOL:{
388 BT_INFO("Set_PROTOCOL");
389 data.type = HTYPE_TRANS_SET_PROTOCOL;
390 data.param = PTYPE_DATA_RTYPE_INPUT;
391 data.buffer_size = len;
392 data.buffer = (char *) malloc(sizeof(char) * len);
394 memcpy(data.buffer, buffer, len);
398 case BT_HID_TRANS_GET_IDLE:{
400 data.type = HTYPE_TRANS_GET_IDLE;
401 data.param = PTYPE_DATA_RTYPE_INPUT;
402 data.buffer_size = len;
403 data.buffer = (char *) malloc(sizeof(char) * len);
405 memcpy(data.buffer, buffer, len);
409 case BT_HID_TRANS_SET_IDLE:{
411 data.type = HTYPE_TRANS_SET_IDLE;
412 data.param = PTYPE_DATA_RTYPE_INPUT;
413 data.buffer_size = len;
414 data.buffer = (char *) malloc(sizeof(char) * len);
416 memcpy(data.buffer, buffer, len);
421 BT_INFO("unsupported HIDP control message");
422 BT_ERR("Send Handshake Message");
423 guint8 type = BT_HID_TRANS_HANDSHAKE |
424 BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
425 data.type = HTYPE_TRANS_UNKNOWN;
426 int fd = g_io_channel_unix_get_fd(chan);
427 int bytes = write(fd, &type, sizeof(type));
428 BT_INFO("Bytes Written %d", bytes);
433 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
434 BLUETOOTH_ERROR_NONE, &data,
435 event_info->cb, event_info->user_data);
440 g_free((char *)data.address);
442 BT_ERR("Error while reading data %d [%s]", status, info->address);
444 BT_ERR("IO Channel read error [%s]", err->message);
445 if (status == G_IO_STATUS_ERROR &&
446 __is_error_by_disconnect(err)) {
447 BT_DBG("cond : %d", cond);
449 __hid_disconnect(info);
453 } else if (status == G_IO_STATUS_EOF) {
454 __hid_disconnect(info);
461 static void __free_hid_info(void *data)
465 hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
467 if (dev_info->disconnect_idle_id > 0) {
468 BT_INFO("Disconnect idle still not process remove source");
469 g_source_remove(dev_info->disconnect_idle_id);
470 dev_info->disconnect_idle_id = 0;
472 __hid_disconnect(dev_info);
475 int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
478 int ret = BLUETOOTH_ERROR_NONE;
480 GVariant *result = NULL;
482 GDBusConnection *conn;
483 GDBusProxy *server_proxy;
486 GUnixFDList *out_fd_list = NULL;
487 conn = _bt_gdbus_get_system_gconn();
488 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
490 adapter_path = _bt_get_device_object_path((char *)address);
491 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
492 BT_INFO_C("Device : %s", adapter_path);
493 server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
495 adapter_path, "org.bluez.Input1", NULL, NULL);
496 g_free(adapter_path);
498 if (server_proxy == NULL) {
499 BT_ERR("Failed to get the network server proxy\n");
500 return BLUETOOTH_ERROR_INTERNAL;
503 result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
505 G_DBUS_CALL_FLAGS_NONE,
511 if (result == NULL) {
513 g_dbus_error_strip_remote_error(err);
514 BT_ERR("INPUT server register Error: %s\n", err->message);
515 if (g_strcmp0(err->message, "Already Exists") == 0)
516 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
518 ret = BLUETOOTH_ERROR_INTERNAL;
523 g_variant_get(result, "(hh)", &index1, &index2);
524 int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
525 int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
529 g_object_unref(out_fd_list);
530 g_variant_unref(result);
532 g_object_unref(server_proxy);
536 int _bt_hid_new_connection(bluetooth_device_address_t *addr,
537 int ctrl_fd, int intr_fd)
539 hid_connected_device_info_t *dev_info = NULL;
541 char secure_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
543 _bt_convert_addr_type_to_string((char *)address, addr->addr);
544 _bt_convert_addr_string_to_secure_string(secure_addr, address);
545 BT_INFO("Address [%s]", secure_addr);
546 dev_info = __find_hid_info_with_address(address);
547 if (dev_info != NULL)
548 __free_hid_info(dev_info);
550 dev_info = (hid_connected_device_info_t *)
551 g_malloc0(sizeof(hid_connected_device_info_t));
553 dev_info->ctrl_fd = ctrl_fd;
554 dev_info->intr_fd = intr_fd;
555 dev_info->address = g_strdup(address);
556 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
557 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
558 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
559 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
560 g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
561 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
562 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
563 g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
564 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
565 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
566 __received_cb, dev_info);
567 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
568 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
569 __received_cb, dev_info);
570 device_list = g_slist_append(device_list, dev_info);
572 __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
577 void _bt_hid_free_hid_info(void)
579 g_slist_free_full(device_list, __free_hid_info);
584 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
588 /* Register HID Device events */
589 BT_INFO("BT_HID_DEVICE_EVENT");
590 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
592 if (ret != BLUETOOTH_ERROR_NONE &&
593 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
594 BT_ERR("Fail to init the event handler");
598 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
600 return BLUETOOTH_ERROR_NONE;
603 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
607 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
609 if (ret != BLUETOOTH_ERROR_NONE) {
610 BT_ERR("Fail to deinit the event handler");
614 _bt_set_user_data(BT_HID, NULL, NULL);
616 return BLUETOOTH_ERROR_NONE;
619 BT_EXPORT_API int bluetooth_hid_device_activate(void)
624 BT_CHECK_ENABLED(return);
626 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
627 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
628 BT_ERR("Don't have a privilege to use this API");
629 return BLUETOOTH_ERROR_PERMISSION_DEINED;
632 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
633 BT_HID_SERVICE_INTERFACE,
634 "RegisterApplication", &err, NULL);
637 int ret = BLUETOOTH_ERROR_INTERNAL;
638 BT_ERR("Error returned in method call");
640 BT_ERR("Error = %s", err->message);
641 if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
642 ret = BLUETOOTH_ERROR_IN_PROGRESS;
644 ret = BLUETOOTH_ERROR_INTERNAL;
650 g_variant_unref(reply);
652 return BLUETOOTH_ERROR_NONE;
655 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
660 BT_CHECK_ENABLED(return);
662 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
663 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
664 BT_ERR("Don't have a privilege to use this API");
665 return BLUETOOTH_ERROR_PERMISSION_DEINED;
668 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
669 BT_HID_SERVICE_INTERFACE,
670 "UnregisterApplication", &err, NULL);
673 int ret = BLUETOOTH_ERROR_INTERNAL;
674 BT_ERR("Error returned in method call");
676 BT_ERR("Error = %s", err->message);
677 if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
678 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
680 ret = BLUETOOTH_ERROR_INTERNAL;
686 g_variant_unref(reply);
688 _bt_hid_free_hid_info();
690 return BLUETOOTH_ERROR_NONE;
693 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
695 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
696 hid_connected_device_info_t *info = NULL;
699 BT_CHECK_PARAMETER(remote_addr, return);
701 BT_CHECK_ENABLED(return);
703 info = __find_hid_info_with_address(remote_addr);
705 BT_ERR("Connection Already Exists");
706 return BLUETOOTH_ERROR_ALREADY_CONNECT;
708 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
709 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
710 BT_ERR("Don't have a privilege to use this API");
711 return BLUETOOTH_ERROR_PERMISSION_DEINED;
714 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
715 ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
716 __hid_connect_response_cb, NULL);
720 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
722 BT_CHECK_PARAMETER(remote_addr, return);
724 BT_CHECK_ENABLED(return);
726 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
727 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
728 BT_ERR("Don't have a privilege to use this API");
729 return BLUETOOTH_ERROR_PERMISSION_DEINED;
732 hid_connected_device_info_t *info = NULL;
734 info = __find_hid_info_with_address(remote_addr);
736 return BLUETOOTH_ERROR_INVALID_PARAM;
738 _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
740 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
743 return BLUETOOTH_ERROR_NONE;
745 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
746 hid_send_mouse_event_t send_event)
750 hid_connected_device_info_t *info = NULL;
752 BT_CHECK_PARAMETER(remote_addr, return);
754 switch (privilege_token_send_mouse) {
756 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
758 if (result == BLUETOOTH_ERROR_NONE) {
759 privilege_token_send_mouse = 1; /* Have a permission */
760 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
761 BT_ERR("Don't have a privilege to use this API");
762 privilege_token_send_mouse = -1; /* Don't have a permission */
763 return BLUETOOTH_ERROR_PERMISSION_DEINED;
765 /* Just break - It is not related with permission error */
769 /* Already have a privilege */
772 return BLUETOOTH_ERROR_PERMISSION_DEINED;
774 /* Invalid privilge token value */
775 return BLUETOOTH_ERROR_INTERNAL;
777 info = __find_hid_info_with_address(remote_addr);
779 BT_ERR("Connection Information not found");
780 return BLUETOOTH_ERROR_INVALID_PARAM;
783 if (info->intr_fd >= 0) {
784 written = write(info->intr_fd, &send_event, sizeof(send_event));
786 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
787 __free_hid_info(info);
788 return BLUETOOTH_ERROR_INTERNAL;
794 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
795 hid_send_key_event_t send_event)
799 hid_connected_device_info_t *info = NULL;
801 BT_CHECK_PARAMETER(remote_addr, return);
803 switch (privilege_token_send_key) {
805 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
807 if (result == BLUETOOTH_ERROR_NONE) {
808 privilege_token_send_key = 1; /* Have a permission */
809 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
810 BT_ERR("Don't have a privilege to use this API");
811 privilege_token_send_key = -1; /* Don't have a permission */
812 return BLUETOOTH_ERROR_PERMISSION_DEINED;
814 /* Just break - It is not related with permission error */
818 /* Already have a privilege */
821 return BLUETOOTH_ERROR_PERMISSION_DEINED;
823 /* Invalid privilge token value */
824 return BLUETOOTH_ERROR_INTERNAL;
827 info = __find_hid_info_with_address(remote_addr);
829 BT_ERR("Connection Information not found");
830 return BLUETOOTH_ERROR_INVALID_PARAM;
833 if (info->intr_fd >= 0) {
834 written = write(info->intr_fd, &send_event, sizeof(send_event));
836 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
837 __free_hid_info(info);
838 return BLUETOOTH_ERROR_INTERNAL;
844 BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
845 unsigned char btcode, unsigned char report_id,
846 const char *data, unsigned int data_len)
850 hid_connected_device_info_t *info = NULL;
851 char *send_event = NULL;
853 BT_CHECK_PARAMETER(remote_addr, return);
854 BT_CHECK_PARAMETER(data, return);
856 switch (privilege_token_send_key) {
858 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
860 if (result == BLUETOOTH_ERROR_NONE) {
861 privilege_token_send_key = 1; /* Have a permission */
862 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
863 BT_ERR("Don't have a privilege to use this API");
864 privilege_token_send_key = -1; /* Don't have a permission */
865 return BLUETOOTH_ERROR_PERMISSION_DEINED;
867 /* Just break - It is not related with permission error */
871 /* Already have a privilege */
874 return BLUETOOTH_ERROR_PERMISSION_DEINED;
876 /* Invalid privilge token value */
877 return BLUETOOTH_ERROR_INTERNAL;
880 info = __find_hid_info_with_address(remote_addr);
882 BT_ERR("Connection Information not found");
883 return BLUETOOTH_ERROR_INVALID_PARAM;
886 if (info->intr_fd >= 0) {
887 send_event = g_malloc0(data_len + 2);
889 send_event[0] = (char)btcode;
890 send_event[1] = (char)report_id;
891 memcpy(send_event + 2, data, data_len);
893 written = write(info->intr_fd, send_event, data_len + 2);
896 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
897 __free_hid_info(info);
898 return BLUETOOTH_ERROR_INTERNAL;
904 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
905 bt_hid_header_type_t htype,
906 bt_hid_param_type_t ptype,
908 unsigned int data_len)
911 struct reports output_report = { 0 };
913 hid_connected_device_info_t *info = NULL;
915 BT_CHECK_PARAMETER(remote_addr, return);
917 info = __find_hid_info_with_address(remote_addr);
919 BT_ERR("Connection Information not found");
920 return BLUETOOTH_ERROR_INVALID_PARAM;
923 if (info->ctrl_fd < 0) {
924 BT_ERR("ctrl_fd(%d) is invalid.", info->ctrl_fd);
925 __free_hid_info(info);
926 return BLUETOOTH_ERROR_INTERNAL;
929 switch (privilege_token_reply) {
931 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
933 if (result == BLUETOOTH_ERROR_NONE) {
934 privilege_token_reply = 1; /* Have a permission */
935 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
936 BT_ERR("Don't have a privilege to use this API");
937 privilege_token_reply = -1; /* Don't have a permission */
938 return BLUETOOTH_ERROR_PERMISSION_DEINED;
940 /* Just break - It is not related with permission error */
944 /* Already have a privilege */
947 return BLUETOOTH_ERROR_PERMISSION_DEINED;
949 /* Invalid privilge token value */
950 return BLUETOOTH_ERROR_INTERNAL;
953 BT_INFO("htype %d ptype %d", htype, ptype);
955 case HTYPE_TRANS_GET_REPORT: {
957 case PTYPE_DATA_RTYPE_INPUT: {
958 output_report.type = BT_HID_TRANS_DATA |
959 BT_HID_DATA_RTYPE_INPUT;
960 memcpy(output_report.rep_data, data, data_len);
961 bytes = write(info->ctrl_fd, &output_report,
962 sizeof(output_report));
963 BT_DBG("Bytes Written %d", bytes);
967 BT_INFO("Not Supported");
972 case HTYPE_TRANS_GET_PROTOCOL: {
973 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
974 output_report.rep_data[0] = data[0];
975 bytes = write(info->ctrl_fd, &output_report, 2);
979 case HTYPE_TRANS_SET_PROTOCOL: {
980 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
981 memcpy(output_report.rep_data, data, data_len);
982 bytes = write(info->ctrl_fd, &output_report,
983 sizeof(output_report));
987 case HTYPE_TRANS_HANDSHAKE: {
988 output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
989 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
990 bytes = write(info->ctrl_fd, &output_report.type,
991 sizeof(output_report.type));
995 case HTYPE_TRANS_GET_IDLE: {
996 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
997 output_report.rep_data[0] = data[0];
998 bytes = write(info->ctrl_fd, &output_report, 2);
1002 case HTYPE_TRANS_SET_IDLE: {
1003 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
1004 memcpy(output_report.rep_data, data, data_len);
1005 bytes = write(info->ctrl_fd, &output_report,
1006 sizeof(output_report));
1015 BT_DBG("Bytes Written %d", bytes);