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_get_system_private_conn();
101 retv_if(conn == NULL, NULL);
103 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
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 (strcasecmp((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 recv_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 recv_data.address = g_strdup(info->address);
302 case BT_HID_TRANS_HANDSHAKE:
303 BT_INFO("TRANS HANDSHAKE");
304 recv_data.type = HTYPE_TRANS_HANDSHAKE;
305 recv_data.buffer_size = len;
306 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
307 memcpy(recv_data.buffer, buffer, len);
310 case BT_HID_TRANS_HID_CONTROL:
311 BT_INFO("HID CONTROL");
312 recv_data.type = HTYPE_TRANS_HID_CONTROL;
313 recv_data.buffer_size = len;
314 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
315 memcpy(recv_data.buffer, buffer, len);
318 case BT_HID_TRANS_DATA:
319 BT_INFO("TRANS DATA");
320 recv_data.type = HTYPE_TRANS_DATA;
321 if (param & BT_HID_DATA_RTYPE_INPUT) {
322 BT_INFO("Input Report");
323 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
324 recv_data.buffer_size = len;
325 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
326 memcpy(recv_data.buffer, buffer, len);
328 BT_INFO("Out Report");
329 recv_data.param = PTYPE_DATA_RTYPE_OUTPUT;
330 recv_data.buffer_size = len;
331 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
332 memcpy(recv_data.buffer, buffer, len);
336 case BT_HID_TRANS_GET_REPORT: {
337 BT_INFO("Get Report");
338 recv_data.type = HTYPE_TRANS_GET_REPORT;
339 if (param & BT_HID_DATA_RTYPE_INPUT) {
340 BT_INFO("Input Report");
341 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
343 BT_INFO("Output Report");
344 recv_data.param = PTYPE_DATA_RTYPE_OUTPUT;
346 recv_data.buffer_size = len;
347 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
348 memcpy(recv_data.buffer, buffer, len);
352 case BT_HID_TRANS_SET_REPORT: {
353 BT_INFO("Set Report");
354 recv_data.type = HTYPE_TRANS_SET_REPORT;
355 if (param & BT_HID_DATA_RTYPE_INPUT) {
356 BT_INFO("Input Report");
357 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
359 BT_INFO("Output Report");
360 recv_data.param = PTYPE_DATA_RTYPE_OUTPUT;
362 recv_data.buffer_size = len;
363 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
364 memcpy(recv_data.buffer, buffer, len);
368 case BT_HID_TRANS_GET_PROTOCOL:{
369 BT_INFO("Get_PROTOCOL");
370 recv_data.type = HTYPE_TRANS_GET_PROTOCOL;
371 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
372 recv_data.buffer_size = len;
373 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
374 memcpy(recv_data.buffer, buffer, len);
378 case BT_HID_TRANS_SET_PROTOCOL:{
379 BT_INFO("Set_PROTOCOL");
380 recv_data.type = HTYPE_TRANS_SET_PROTOCOL;
381 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
382 recv_data.buffer_size = len;
383 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
384 memcpy(recv_data.buffer, buffer, len);
388 case BT_HID_TRANS_GET_IDLE:{
390 recv_data.type = HTYPE_TRANS_GET_IDLE;
391 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
392 recv_data.buffer_size = len;
393 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
394 memcpy(recv_data.buffer, buffer, len);
398 case BT_HID_TRANS_SET_IDLE:{
400 recv_data.type = HTYPE_TRANS_SET_IDLE;
401 recv_data.param = PTYPE_DATA_RTYPE_INPUT;
402 recv_data.buffer_size = len;
403 recv_data.buffer = (char *)g_malloc0(sizeof(char) * len);
404 memcpy(recv_data.buffer, buffer, len);
409 BT_INFO("unsupported HIDP control message");
410 BT_ERR("Send Handshake Message");
411 guint8 type = BT_HID_TRANS_HANDSHAKE |
412 BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
413 recv_data.type = HTYPE_TRANS_UNKNOWN;
414 int fd = g_io_channel_unix_get_fd(chan);
415 int bytes = write(fd, &type, sizeof(type));
416 BT_INFO("Bytes Written %d", bytes);
421 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
422 BLUETOOTH_ERROR_NONE, &recv_data,
423 event_info->cb, event_info->user_data);
424 if (recv_data.buffer)
425 g_free(recv_data.buffer);
427 if (recv_data.address)
428 g_free((char *)recv_data.address);
430 BT_ERR("Error while reading data %d [%s]", status, info->address);
432 BT_ERR("IO Channel read error [%s]", err->message);
433 if (status == G_IO_STATUS_ERROR &&
434 __is_error_by_disconnect(err)) {
435 BT_DBG("cond : %d", cond);
437 __hid_disconnect(info);
441 } else if (status == G_IO_STATUS_EOF) {
442 __hid_disconnect(info);
449 static void __free_hid_info(void *data)
453 hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
455 if (dev_info->disconnect_idle_id > 0) {
456 BT_INFO("Disconnect idle still not process remove source");
457 g_source_remove(dev_info->disconnect_idle_id);
458 dev_info->disconnect_idle_id = 0;
460 __hid_disconnect(dev_info);
463 int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
466 int ret = BLUETOOTH_ERROR_NONE;
468 GVariant *result = NULL;
470 GDBusConnection *conn;
471 GDBusProxy *server_proxy;
474 GUnixFDList *out_fd_list = NULL;
475 conn = _bt_get_system_private_conn();
476 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
478 adapter_path = _bt_get_device_object_path((char *)address);
479 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
480 BT_INFO_C("Device : %s", adapter_path);
481 server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
483 adapter_path, "org.bluez.Input1", NULL, NULL);
484 g_free(adapter_path);
486 if (server_proxy == NULL) {
487 BT_ERR("Failed to get the network server proxy\n");
488 return BLUETOOTH_ERROR_INTERNAL;
491 result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
493 G_DBUS_CALL_FLAGS_NONE,
499 if (result == NULL) {
501 g_dbus_error_strip_remote_error(err);
502 BT_ERR("INPUT server register Error: %s\n", err->message);
503 if (g_strcmp0(err->message, "Already Exists") == 0)
504 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
506 ret = BLUETOOTH_ERROR_INTERNAL;
511 g_variant_get(result, "(hh)", &index1, &index2);
512 int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
513 int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
517 g_object_unref(out_fd_list);
518 g_variant_unref(result);
520 g_object_unref(server_proxy);
524 int _bt_hid_new_connection(bluetooth_device_address_t *addr,
525 int ctrl_fd, int intr_fd)
527 hid_connected_device_info_t *dev_info = NULL;
529 char secure_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
531 _bt_convert_addr_type_to_string((char *)address, addr->addr);
532 _bt_convert_addr_string_to_secure_string(secure_addr, address);
533 BT_INFO("Address [%s]", secure_addr);
534 dev_info = __find_hid_info_with_address(address);
535 if (dev_info != NULL)
536 __free_hid_info(dev_info);
538 dev_info = (hid_connected_device_info_t *)
539 g_malloc0(sizeof(hid_connected_device_info_t));
541 dev_info->ctrl_fd = ctrl_fd;
542 dev_info->intr_fd = intr_fd;
543 dev_info->address = g_strdup(address);
544 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
545 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
546 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
547 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
548 g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
549 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
550 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
551 g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
552 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
553 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
554 __received_cb, dev_info);
555 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
556 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
557 __received_cb, dev_info);
558 device_list = g_slist_append(device_list, dev_info);
560 __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
565 void _bt_hid_free_hid_info(void)
567 g_slist_free_full(device_list, __free_hid_info);
572 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
576 /* Register HID Device events */
577 BT_INFO("BT_HID_DEVICE_EVENT");
578 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
580 if (ret != BLUETOOTH_ERROR_NONE &&
581 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
582 BT_ERR("Fail to init the event handler");
586 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
588 return BLUETOOTH_ERROR_NONE;
591 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
595 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
597 if (ret != BLUETOOTH_ERROR_NONE) {
598 BT_ERR("Fail to deinit the event handler");
602 _bt_set_user_data(BT_HID, NULL, NULL);
604 return BLUETOOTH_ERROR_NONE;
607 BT_EXPORT_API int bluetooth_hid_device_activate(void)
612 BT_CHECK_ENABLED(return);
614 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
615 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
616 BT_ERR("Don't have a privilege to use this API");
617 return BLUETOOTH_ERROR_PERMISSION_DEINED;
620 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
621 BT_HID_SERVICE_INTERFACE,
622 "RegisterApplication", &err, NULL);
625 int ret = BLUETOOTH_ERROR_INTERNAL;
626 BT_ERR("Error returned in method call");
628 BT_ERR("Error = %s", err->message);
629 if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
630 ret = BLUETOOTH_ERROR_IN_PROGRESS;
632 ret = BLUETOOTH_ERROR_INTERNAL;
638 g_variant_unref(reply);
640 return BLUETOOTH_ERROR_NONE;
643 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
648 BT_CHECK_ENABLED(return);
650 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
651 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
652 BT_ERR("Don't have a privilege to use this API");
653 return BLUETOOTH_ERROR_PERMISSION_DEINED;
656 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
657 BT_HID_SERVICE_INTERFACE,
658 "UnregisterApplication", &err, NULL);
661 int ret = BLUETOOTH_ERROR_INTERNAL;
662 BT_ERR("Error returned in method call");
664 BT_ERR("Error = %s", err->message);
665 if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
666 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
668 ret = BLUETOOTH_ERROR_INTERNAL;
674 g_variant_unref(reply);
676 _bt_hid_free_hid_info();
678 return BLUETOOTH_ERROR_NONE;
681 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
683 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
684 hid_connected_device_info_t *info = NULL;
687 BT_CHECK_PARAMETER(remote_addr, return);
689 BT_CHECK_ENABLED(return);
691 info = __find_hid_info_with_address(remote_addr);
693 BT_ERR("Connection Already Exists");
694 return BLUETOOTH_ERROR_ALREADY_CONNECT;
696 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
697 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
698 BT_ERR("Don't have a privilege to use this API");
699 return BLUETOOTH_ERROR_PERMISSION_DEINED;
702 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
703 ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
704 __hid_connect_response_cb, NULL);
708 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
710 BT_CHECK_PARAMETER(remote_addr, return);
712 BT_CHECK_ENABLED(return);
714 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
715 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
716 BT_ERR("Don't have a privilege to use this API");
717 return BLUETOOTH_ERROR_PERMISSION_DEINED;
720 hid_connected_device_info_t *info = NULL;
722 info = __find_hid_info_with_address(remote_addr);
724 return BLUETOOTH_ERROR_INVALID_PARAM;
726 _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
728 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
731 return BLUETOOTH_ERROR_NONE;
733 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
734 hid_send_mouse_event_t send_event)
738 hid_connected_device_info_t *info = NULL;
740 BT_CHECK_PARAMETER(remote_addr, return);
742 switch (privilege_token_send_mouse) {
744 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
746 if (result == BLUETOOTH_ERROR_NONE) {
747 privilege_token_send_mouse = 1; /* Have a permission */
748 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
749 BT_ERR("Don't have a privilege to use this API");
750 privilege_token_send_mouse = -1; /* Don't have a permission */
751 return BLUETOOTH_ERROR_PERMISSION_DEINED;
753 /* Just break - It is not related with permission error */
757 /* Already have a privilege */
760 return BLUETOOTH_ERROR_PERMISSION_DEINED;
762 /* Invalid privilge token value */
763 return BLUETOOTH_ERROR_INTERNAL;
765 info = __find_hid_info_with_address(remote_addr);
767 BT_ERR("Connection Information not found");
768 return BLUETOOTH_ERROR_INVALID_PARAM;
771 if (info->intr_fd >= 0) {
772 written = write(info->intr_fd, &send_event, sizeof(send_event));
774 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
775 __free_hid_info(info);
776 return BLUETOOTH_ERROR_INTERNAL;
782 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
783 hid_send_key_event_t send_event)
787 hid_connected_device_info_t *info = NULL;
789 BT_CHECK_PARAMETER(remote_addr, return);
791 switch (privilege_token_send_key) {
793 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
795 if (result == BLUETOOTH_ERROR_NONE) {
796 privilege_token_send_key = 1; /* Have a permission */
797 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
798 BT_ERR("Don't have a privilege to use this API");
799 privilege_token_send_key = -1; /* Don't have a permission */
800 return BLUETOOTH_ERROR_PERMISSION_DEINED;
802 /* Just break - It is not related with permission error */
806 /* Already have a privilege */
809 return BLUETOOTH_ERROR_PERMISSION_DEINED;
811 /* Invalid privilge token value */
812 return BLUETOOTH_ERROR_INTERNAL;
815 info = __find_hid_info_with_address(remote_addr);
817 BT_ERR("Connection Information not found");
818 return BLUETOOTH_ERROR_INVALID_PARAM;
821 if (info->intr_fd >= 0) {
822 written = write(info->intr_fd, &send_event, sizeof(send_event));
824 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
825 __free_hid_info(info);
826 return BLUETOOTH_ERROR_INTERNAL;
832 BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
833 unsigned char btcode, unsigned char report_id,
834 const char *data, unsigned int data_len)
838 hid_connected_device_info_t *info = NULL;
839 char *send_event = NULL;
841 BT_CHECK_PARAMETER(remote_addr, return);
842 BT_CHECK_PARAMETER(data, return);
844 switch (privilege_token_send_key) {
846 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
848 if (result == BLUETOOTH_ERROR_NONE) {
849 privilege_token_send_key = 1; /* Have a permission */
850 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
851 BT_ERR("Don't have a privilege to use this API");
852 privilege_token_send_key = -1; /* Don't have a permission */
853 return BLUETOOTH_ERROR_PERMISSION_DEINED;
855 /* Just break - It is not related with permission error */
859 /* Already have a privilege */
862 return BLUETOOTH_ERROR_PERMISSION_DEINED;
864 /* Invalid privilge token value */
865 return BLUETOOTH_ERROR_INTERNAL;
868 info = __find_hid_info_with_address(remote_addr);
870 BT_ERR("Connection Information not found");
871 return BLUETOOTH_ERROR_INVALID_PARAM;
874 if (info->intr_fd >= 0) {
875 send_event = g_malloc0(data_len + 2);
877 send_event[0] = (char)btcode;
878 send_event[1] = (char)report_id;
879 memcpy(send_event + 2, data, data_len);
881 written = write(info->intr_fd, send_event, data_len + 2);
884 BT_ERR("intr_fd(%d) is invalid.", info->intr_fd);
885 __free_hid_info(info);
886 return BLUETOOTH_ERROR_INTERNAL;
892 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
893 bt_hid_header_type_t htype,
894 bt_hid_param_type_t ptype,
896 unsigned int data_len)
899 struct reports output_report = { 0 };
901 hid_connected_device_info_t *info = NULL;
903 BT_CHECK_PARAMETER(remote_addr, return);
905 info = __find_hid_info_with_address(remote_addr);
907 BT_ERR("Connection Information not found");
908 return BLUETOOTH_ERROR_INVALID_PARAM;
911 if (info->ctrl_fd < 0) {
912 BT_ERR("ctrl_fd(%d) is invalid.", info->ctrl_fd);
913 __free_hid_info(info);
914 return BLUETOOTH_ERROR_INTERNAL;
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->ctrl_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 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
962 output_report.rep_data[0] = data[0];
963 bytes = write(info->ctrl_fd, &output_report, 2);
967 case HTYPE_TRANS_SET_PROTOCOL: {
968 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
969 memcpy(output_report.rep_data, data, data_len);
970 bytes = write(info->ctrl_fd, &output_report,
971 sizeof(output_report));
975 case HTYPE_TRANS_HANDSHAKE: {
976 output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
977 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
978 bytes = write(info->ctrl_fd, &output_report.type,
979 sizeof(output_report.type));
983 case HTYPE_TRANS_GET_IDLE: {
984 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
985 output_report.rep_data[0] = data[0];
986 bytes = write(info->ctrl_fd, &output_report, 2);
990 case HTYPE_TRANS_SET_IDLE: {
991 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
992 memcpy(output_report.rep_data, data, data_len);
993 bytes = write(info->ctrl_fd, &output_report,
994 sizeof(output_report));
1003 BT_DBG("Bytes Written %d", bytes);