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
71 GIOChannel *ctrl_data_io;
72 GIOChannel *intr_data_io;
76 guint disconnect_idle_id;
77 } hid_connected_device_info_t;
82 } __attribute__((__packed__));
84 static hid_info_t *hid_info = NULL;
86 /* Variable for privilege, only for write API,
87 before we should reduce time to bt-service dbus calling
88 -1 : Don't have a permission to access API
89 0 : Initial value, not yet check
90 1 : Have a permission to access API
92 static int privilege_token_send_mouse = 0;
93 static int privilege_token_send_key = 0;
94 static int privilege_token_reply = 0;
96 static gboolean __hid_disconnect(hid_connected_device_info_t *info);
98 int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
101 int ret = BLUETOOTH_ERROR_NONE;
103 GVariant *result = NULL;
105 GDBusConnection *conn;
106 GDBusProxy *server_proxy;
109 GUnixFDList *out_fd_list = NULL;
110 conn = _bt_gdbus_get_system_gconn();
111 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
113 adapter_path = _bt_get_device_object_path((char *)address);
114 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
115 BT_INFO_C("Device : %s", adapter_path);
116 server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
118 adapter_path, "org.bluez.Input1", NULL, NULL);
119 g_free(adapter_path);
121 if (server_proxy == NULL) {
122 BT_ERR("Failed to get the network server proxy\n");
123 return BLUETOOTH_ERROR_INTERNAL;
126 result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
128 G_DBUS_CALL_FLAGS_NONE,
134 if (result == NULL) {
136 g_dbus_error_strip_remote_error(err);
137 BT_ERR("INPUT server register Error: %s\n", err->message);
138 if (g_strcmp0(err->message, "Already Exists") == 0)
139 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
141 ret = BLUETOOTH_ERROR_INTERNAL;
146 g_variant_get(result, "(hh)", &index1, &index2);
147 int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
148 int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
152 g_object_unref(out_fd_list);
153 g_variant_unref(result);
155 g_object_unref(server_proxy);
159 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
163 for (l = hid_info->device_list; l != NULL; l = l->next) {
164 hid_connected_device_info_t *info = l->data;
165 if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
171 static void __hid_connected_cb(hid_connected_device_info_t *info,
174 bluetooth_hid_request_t conn_info;
175 bt_event_info_t *event_info = NULL;
177 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
178 if (event_info == NULL)
181 memset(&conn_info, 0x00, sizeof(bluetooth_hid_request_t));
182 if (info->intr_fd != -1 && info->ctrl_fd == -1)
183 conn_info.socket_fd = info->intr_fd;
185 conn_info.socket_fd = info->ctrl_fd;
186 _bt_convert_addr_string_to_type(conn_info.device_addr.addr, info->address);
188 if (result == BLUETOOTH_ERROR_NONE)
189 BT_INFO_C("Connected [HID Device]");
191 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
193 event_info->cb, event_info->user_data);
196 static void __hid_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
201 GError *error = NULL;
202 GVariant *ret = NULL;
203 hid_connected_device_info_t info;
208 ret = g_dbus_proxy_call_finish(proxy, res, &error);
210 g_dbus_error_strip_remote_error(error);
211 BT_ERR("Error : %s \n", error->message);
213 if (g_strcmp0(error->message, "In Progress") == 0)
214 result = BLUETOOTH_ERROR_DEVICE_BUSY;
216 result = BLUETOOTH_ERROR_INTERNAL;
221 info.address = g_malloc0(BT_ADDRESS_STRING_SIZE);
223 path = g_dbus_proxy_get_object_path(proxy);
224 _bt_convert_device_path_to_address(path, info.address);
226 __hid_connected_cb(&info, result);
228 g_free(info.address);
232 g_variant_unref(ret);
236 g_object_unref(proxy);
241 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
243 bluetooth_hid_request_t disconn_info;
244 int fd = info->ctrl_fd;
245 bt_event_info_t *event_info;
247 BT_INFO_C("Disconnected [HID Device]");
248 hid_info->device_list = g_slist_remove(hid_info->device_list, info);
249 if (info->ctrl_data_id > 0) {
250 g_source_remove(info->ctrl_data_id);
251 info->ctrl_data_id = 0;
253 if (info->intr_data_id > 0) {
254 g_source_remove(info->intr_data_id);
255 info->intr_data_id = 0;
258 if (info->ctrl_data_io) {
259 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
260 g_io_channel_unref(info->ctrl_data_io);
261 info->ctrl_data_io = NULL;
263 if (info->intr_data_io) {
264 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
265 g_io_channel_unref(info->intr_data_io);
266 info->intr_data_io = NULL;
268 if (info->intr_fd >= 0) {
269 close(info->ctrl_fd);
270 close(info->intr_fd);
274 info->disconnect_idle_id = 0;
275 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
276 if (event_info == NULL)
279 memset(&disconn_info, 0x00, sizeof(bluetooth_hid_request_t));
280 disconn_info.socket_fd = fd;
281 _bt_convert_addr_string_to_type(disconn_info.device_addr.addr , info->address);
282 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
283 BLUETOOTH_ERROR_NONE, &disconn_info,
284 event_info->cb, event_info->user_data);
286 g_free(info->address);
293 void __free_hid_info(hid_info_t *info)
297 _bt_unregister_gdbus(info->object_id);
299 while (info->device_list) {
300 hid_connected_device_info_t *dev_info = NULL;
301 dev_info = (hid_connected_device_info_t *)info->device_list->data;
303 if (dev_info->disconnect_idle_id > 0) {
304 BT_INFO("Disconnect idle still not process remove source");
305 g_source_remove(dev_info->disconnect_idle_id);
306 dev_info->disconnect_idle_id = 0;
308 __hid_disconnect(dev_info);
316 static gboolean __is_error_by_disconnect(GError *err)
318 return !g_strcmp0(err->message, "Connection reset by peer") ||
319 !g_strcmp0(err->message, "Connection timed out") ||
320 !g_strcmp0(err->message, "Software caused connection abort");
323 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
326 hid_connected_device_info_t *info = data;
327 GIOStatus status = G_IO_STATUS_NORMAL;
328 char buffer[BT_RFCOMM_BUFFER_LEN];
331 guint8 header, type, param;
332 bt_event_info_t *event_info;
333 retv_if(info == NULL, FALSE);
335 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
336 BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
337 if (info->disconnect_idle_id > 0) {
338 BT_INFO("Disconnect idle still not process remove source");
339 g_source_remove(info->disconnect_idle_id);
340 info->disconnect_idle_id = 0;
342 __hid_disconnect(info);
346 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
348 if (status == G_IO_STATUS_NORMAL) {
349 BT_INFO("Parsing Data");
350 bluetooth_hid_received_data_t data = {0};
352 type = header & BT_HID_HEADER_TRANS_MASK;
353 param = header & BT_HID_HEADER_PARAM_MASK;
354 BT_INFO("type %d , param %d", type, param);
355 BT_INFO("Data Reveived from %s" , info->address);
357 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
358 if (event_info == NULL)
361 data.address = g_strdup(info->address);
363 case BT_HID_TRANS_HANDSHAKE:
364 BT_INFO("TRANS HANDSHAKE");
365 data.type = HTYPE_TRANS_HANDSHAKE;
366 data.buffer_size = len;
367 data.buffer = (char *) malloc(sizeof(char) * len);
369 memcpy(data.buffer, buffer, len);
372 case BT_HID_TRANS_HID_CONTROL:
373 BT_INFO("HID CONTROL");
374 data.type = HTYPE_TRANS_HID_CONTROL;
375 data.buffer_size = len;
376 data.buffer = (char *) malloc(sizeof(char) * len);
378 memcpy(data.buffer, buffer, len);
381 case BT_HID_TRANS_DATA:
382 BT_INFO("TRANS DATA");
383 data.type = HTYPE_TRANS_DATA;
384 if (param & BT_HID_DATA_RTYPE_INPUT) {
385 BT_INFO("Input Report");
386 data.param = PTYPE_DATA_RTYPE_INPUT;
387 data.buffer_size = len;
388 data.buffer = (char *) malloc(sizeof(char) * len);
390 memcpy(data.buffer, buffer, len);
392 BT_INFO("Out Report");
393 data.param = PTYPE_DATA_RTYPE_OUTPUT;
394 data.buffer_size = len;
395 data.buffer = (char *) malloc(sizeof(char) * len);
397 memcpy(data.buffer, buffer, len);
401 case BT_HID_TRANS_GET_REPORT: {
402 BT_INFO("Get Report");
403 data.type = HTYPE_TRANS_GET_REPORT;
404 if (param & BT_HID_DATA_RTYPE_INPUT) {
405 BT_INFO("Input Report");
406 data.param = PTYPE_DATA_RTYPE_INPUT;
408 BT_INFO("Output Report");
409 data.param = PTYPE_DATA_RTYPE_OUTPUT;
411 data.buffer_size = len;
412 data.buffer = (char *) malloc(sizeof(char) * len);
414 memcpy(data.buffer, buffer, len);
418 case BT_HID_TRANS_SET_REPORT: {
419 BT_INFO("Set Report");
420 data.type = HTYPE_TRANS_SET_REPORT;
421 if (param & BT_HID_DATA_RTYPE_INPUT) {
422 BT_INFO("Input Report");
423 data.param = PTYPE_DATA_RTYPE_INPUT;
425 BT_INFO("Output Report");
426 data.param = PTYPE_DATA_RTYPE_OUTPUT;
428 data.buffer_size = len;
429 data.buffer = (char *) malloc(sizeof(char) * len);
431 memcpy(data.buffer, buffer, len);
435 case BT_HID_TRANS_GET_PROTOCOL:{
436 BT_INFO("Get_PROTOCOL");
437 data.type = HTYPE_TRANS_GET_PROTOCOL;
438 data.param = PTYPE_DATA_RTYPE_INPUT;
439 data.buffer_size = len;
440 data.buffer = (char *) malloc(sizeof(char) * len);
442 memcpy(data.buffer, buffer, len);
446 case BT_HID_TRANS_SET_PROTOCOL:{
447 BT_INFO("Set_PROTOCOL");
448 data.type = HTYPE_TRANS_SET_PROTOCOL;
449 data.param = PTYPE_DATA_RTYPE_INPUT;
450 data.buffer_size = len;
451 data.buffer = (char *) malloc(sizeof(char) * len);
453 memcpy(data.buffer, buffer, len);
457 case BT_HID_TRANS_GET_IDLE:{
459 data.type = HTYPE_TRANS_GET_IDLE;
460 data.param = PTYPE_DATA_RTYPE_INPUT;
461 data.buffer_size = len;
462 data.buffer = (char *) malloc(sizeof(char) * len);
464 memcpy(data.buffer, buffer, len);
468 case BT_HID_TRANS_SET_IDLE:{
470 data.type = HTYPE_TRANS_SET_IDLE;
471 data.param = PTYPE_DATA_RTYPE_INPUT;
472 data.buffer_size = len;
473 data.buffer = (char *) malloc(sizeof(char) * len);
475 memcpy(data.buffer, buffer, len);
480 BT_INFO("unsupported HIDP control message");
481 BT_ERR("Send Handshake Message");
482 guint8 type = BT_HID_TRANS_HANDSHAKE |
483 BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
484 data.type = HTYPE_TRANS_UNKNOWN;
485 int fd = g_io_channel_unix_get_fd(chan);
486 int bytes = write(fd, &type, sizeof(type));
487 BT_INFO("Bytes Written %d", bytes);
492 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
493 BLUETOOTH_ERROR_NONE, &data,
494 event_info->cb, event_info->user_data);
499 g_free((char *)data.address);
501 BT_ERR("Error while reading data %d [%s]", status, info->address);
503 BT_ERR("IO Channel read error [%s]", err->message);
504 if (status == G_IO_STATUS_ERROR &&
505 __is_error_by_disconnect(err)) {
506 BT_DBG("cond : %d", cond);
508 __hid_disconnect(info);
512 } else if (status == G_IO_STATUS_EOF) {
513 __hid_disconnect(info);
520 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
522 hid_info_t *info = NULL;
523 hid_connected_device_info_t *dev_info = NULL;
529 _bt_convert_addr_type_to_string((char *)address, addr->addr);
530 BT_INFO("Address [%s]", address);
531 dev_info = __find_hid_info_with_address(address);
532 if (dev_info == NULL) {
533 dev_info = (hid_connected_device_info_t *)
534 g_malloc0(sizeof(hid_connected_device_info_t));
536 dev_info->intr_fd = -1;
537 dev_info->ctrl_fd = -1;
538 dev_info->intr_fd = fd;
539 dev_info->address = g_strdup(address);
540 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
541 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
542 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
543 g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
544 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
545 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
546 __received_cb, dev_info);
547 hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
549 dev_info->ctrl_fd = fd;
550 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
551 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
552 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
553 g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
554 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
555 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
556 __received_cb, dev_info);
559 if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1)
560 __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
564 static hid_info_t *__register_method()
567 hid_info_t *info = NULL;
569 path = g_strdup_printf("/org/socket/server/%d", getpid());
571 object_id = _bt_register_new_conn(path, new_hid_connection);
575 info = g_new(hid_info_t, 1);
576 info->object_id = (guint)object_id;
579 info->device_list = NULL;
584 void _bluetooth_hid_free_hid_info(void)
586 if (hid_info == NULL) {
587 BT_DBG("hid_info is already NULL");
591 __free_hid_info(hid_info);
595 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
599 /* Register HID Device events */
600 BT_INFO("BT_HID_DEVICE_EVENT");
601 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
603 if (ret != BLUETOOTH_ERROR_NONE &&
604 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
605 BT_ERR("Fail to init the event handler");
609 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
611 return BLUETOOTH_ERROR_NONE;
614 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
618 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
620 if (ret != BLUETOOTH_ERROR_NONE) {
621 BT_ERR("Fail to deinit the event handler");
625 _bt_set_user_data(BT_HID, NULL, NULL);
627 return BLUETOOTH_ERROR_NONE;
630 BT_EXPORT_API int bluetooth_hid_device_activate(void)
632 bt_register_profile_info_t profile_info;
633 int result = BLUETOOTH_ERROR_NONE;
635 BT_CHECK_ENABLED(return);
637 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
638 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
639 BT_ERR("Don't have a privilege to use this API");
640 return BLUETOOTH_ERROR_PERMISSION_DEINED;
643 if (hid_info != NULL)
644 return BLUETOOTH_ERROR_IN_PROGRESS;
646 hid_info = __register_method();
647 if (hid_info == NULL)
648 return BLUETOOTH_ERROR_INTERNAL;
650 hid_info->uuid = g_strdup(HID_DEVICE_UUID);
652 profile_info.authentication = TRUE;
653 profile_info.authorization = TRUE;
654 profile_info.obj_path = hid_info->path;
655 profile_info.role = g_strdup("Hid");
656 profile_info.service = hid_info->uuid;
657 profile_info.uuid = hid_info->uuid;
659 BT_INFO("uuid %s", profile_info.uuid);
660 result = _bt_register_profile(&profile_info, FALSE);
662 g_free(profile_info.role);
667 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
669 BT_CHECK_ENABLED(return);
671 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
672 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
673 BT_ERR("Don't have a privilege to use this API");
674 return BLUETOOTH_ERROR_PERMISSION_DEINED;
677 if (hid_info == NULL)
678 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
680 _bt_unregister_profile(hid_info->path);
682 _bluetooth_hid_free_hid_info();
684 return BLUETOOTH_ERROR_NONE;
687 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
689 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
690 hid_connected_device_info_t *info = NULL;
693 BT_CHECK_PARAMETER(remote_addr, return);
695 BT_CHECK_ENABLED(return);
697 info = __find_hid_info_with_address(remote_addr);
699 BT_ERR("Connection Already Exists");
700 return BLUETOOTH_ERROR_ALREADY_CONNECT;
702 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
703 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
704 BT_ERR("Don't have a privilege to use this API");
705 return BLUETOOTH_ERROR_PERMISSION_DEINED;
708 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
709 ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
710 __hid_connect_response_cb, NULL);
714 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
716 BT_CHECK_PARAMETER(remote_addr, return);
718 BT_CHECK_ENABLED(return);
720 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
721 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
722 BT_ERR("Don't have a privilege to use this API");
723 return BLUETOOTH_ERROR_PERMISSION_DEINED;
726 hid_connected_device_info_t *info = NULL;
728 info = __find_hid_info_with_address(remote_addr);
730 return BLUETOOTH_ERROR_INVALID_PARAM;
732 _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
734 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
737 return BLUETOOTH_ERROR_NONE;
739 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
740 hid_send_mouse_event_t send_event)
744 hid_connected_device_info_t *info = NULL;
746 BT_CHECK_PARAMETER(remote_addr, return);
748 switch (privilege_token_send_mouse) {
750 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
752 if (result == BLUETOOTH_ERROR_NONE) {
753 privilege_token_send_mouse = 1; /* Have a permission */
754 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
755 BT_ERR("Don't have a privilege to use this API");
756 privilege_token_send_mouse = -1; /* Don't have a permission */
757 return BLUETOOTH_ERROR_PERMISSION_DEINED;
759 /* Just break - It is not related with permission error */
763 /* Already have a privilege */
766 return BLUETOOTH_ERROR_PERMISSION_DEINED;
768 /* Invalid privilge token value */
769 return BLUETOOTH_ERROR_INTERNAL;
771 info = __find_hid_info_with_address(remote_addr);
773 BT_ERR("Connection Information not found");
774 return BLUETOOTH_ERROR_INVALID_PARAM;
778 if (info->intr_fd != -1 && info->ctrl_fd == -1)
779 socket_fd = info->intr_fd;
781 socket_fd = info->ctrl_fd;
783 written = write(socket_fd, &send_event, sizeof(send_event));
788 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
789 hid_send_key_event_t send_event)
793 hid_connected_device_info_t *info = NULL;
795 BT_CHECK_PARAMETER(remote_addr, return);
797 switch (privilege_token_send_key) {
799 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
801 if (result == BLUETOOTH_ERROR_NONE) {
802 privilege_token_send_key = 1; /* Have a permission */
803 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
804 BT_ERR("Don't have a privilege to use this API");
805 privilege_token_send_key = -1; /* Don't have a permission */
806 return BLUETOOTH_ERROR_PERMISSION_DEINED;
808 /* Just break - It is not related with permission error */
812 /* Already have a privilege */
815 return BLUETOOTH_ERROR_PERMISSION_DEINED;
817 /* Invalid privilge token value */
818 return BLUETOOTH_ERROR_INTERNAL;
821 info = __find_hid_info_with_address(remote_addr);
823 BT_ERR("Connection Information not found");
824 return BLUETOOTH_ERROR_INVALID_PARAM;
829 if (info->intr_fd != -1 && info->ctrl_fd == -1)
830 socket_fd = info->intr_fd;
832 socket_fd = info->ctrl_fd;
834 written = write(socket_fd, &send_event, sizeof(send_event));
838 BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
839 unsigned char btcode, unsigned char report_id,
840 const char *data, unsigned int data_len)
845 hid_connected_device_info_t *info = NULL;
846 char *send_event = NULL;
848 BT_CHECK_PARAMETER(remote_addr, return);
849 BT_CHECK_PARAMETER(data, return);
851 switch (privilege_token_send_key) {
853 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
855 if (result == BLUETOOTH_ERROR_NONE) {
856 privilege_token_send_key = 1; /* Have a permission */
857 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
858 BT_ERR("Don't have a privilege to use this API");
859 privilege_token_send_key = -1; /* Don't have a permission */
860 return BLUETOOTH_ERROR_PERMISSION_DEINED;
862 /* Just break - It is not related with permission error */
866 /* Already have a privilege */
869 return BLUETOOTH_ERROR_PERMISSION_DEINED;
871 /* Invalid privilge token value */
872 return BLUETOOTH_ERROR_INTERNAL;
875 info = __find_hid_info_with_address(remote_addr);
877 BT_ERR("Connection Information not found");
878 return BLUETOOTH_ERROR_INVALID_PARAM;
881 if (info->intr_fd != -1 && info->ctrl_fd == -1)
882 socket_fd = info->intr_fd;
884 socket_fd = info->ctrl_fd;
886 send_event = g_malloc0(data_len + 2);
888 send_event[0] = (char)btcode;
889 send_event[1] = (char)report_id;
890 memcpy(send_event + 2, data, data_len);
892 written = write(socket_fd, send_event, data_len + 2);
899 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
900 bt_hid_header_type_t htype,
901 bt_hid_param_type_t ptype,
903 unsigned int data_len)
906 struct reports output_report = { 0 };
907 int bytes = BLUETOOTH_ERROR_INTERNAL;
908 hid_connected_device_info_t *info = NULL;
909 info = __find_hid_info_with_address(remote_addr);
911 BT_ERR("Connection Information not found");
912 return BLUETOOTH_ERROR_INVALID_PARAM;
915 BT_CHECK_PARAMETER(remote_addr, return);
917 switch (privilege_token_reply) {
919 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
921 if (result == BLUETOOTH_ERROR_NONE) {
922 privilege_token_reply = 1; /* Have a permission */
923 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
924 BT_ERR("Don't have a privilege to use this API");
925 privilege_token_reply = -1; /* Don't have a permission */
926 return BLUETOOTH_ERROR_PERMISSION_DEINED;
928 /* Just break - It is not related with permission error */
932 /* Already have a privilege */
935 return BLUETOOTH_ERROR_PERMISSION_DEINED;
937 /* Invalid privilge token value */
938 return BLUETOOTH_ERROR_INTERNAL;
941 BT_INFO("htype %d ptype %d", htype, ptype);
943 case HTYPE_TRANS_GET_REPORT: {
945 case PTYPE_DATA_RTYPE_INPUT: {
946 output_report.type = BT_HID_TRANS_DATA |
947 BT_HID_DATA_RTYPE_INPUT;
948 memcpy(output_report.rep_data, data, data_len);
949 bytes = write(info->intr_fd, &output_report,
950 sizeof(output_report));
951 BT_DBG("Bytes Written %d", bytes);
955 BT_INFO("Not Supported");
960 case HTYPE_TRANS_GET_PROTOCOL: {
961 BT_DBG("Replying to Get_PROTOCOL");
962 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
963 output_report.rep_data[0] = data[0];
964 bytes = write(info->intr_fd, &output_report, 2);
965 BT_DBG("Bytes Written %d", bytes);
969 case HTYPE_TRANS_SET_PROTOCOL: {
970 BT_DBG("Reply to Set_Protocol");
971 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
972 memcpy(output_report.rep_data, data, data_len);
973 bytes = write(info->ctrl_fd, &output_report,
974 sizeof(output_report));
975 BT_DBG("Bytes Written %d", bytes);
979 case HTYPE_TRANS_HANDSHAKE: {
980 BT_DBG("Replying Handshake");
981 output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
982 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
983 bytes = write(info->intr_fd, &output_report.type,
984 sizeof(output_report.type));
985 BT_DBG("Bytes Written %d", bytes);
989 case HTYPE_TRANS_GET_IDLE: {
990 BT_DBG("Replying to Get_IDLE");
991 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
992 output_report.rep_data[0] = data[0];
993 bytes = write(info->intr_fd, &output_report, 2);
994 BT_DBG("Bytes Written %d", bytes);
998 case HTYPE_TRANS_SET_IDLE: {
999 BT_DBG("Reply to Set_IDLE");
1000 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
1001 memcpy(output_report.rep_data, data, data_len);
1002 bytes = write(info->ctrl_fd, &output_report,
1003 sizeof(output_report));
1004 BT_DBG("Bytes Written %d", bytes);