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 gboolean __hid_disconnect(hid_connected_device_info_t *info);
94 int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
97 int ret = BLUETOOTH_ERROR_NONE;
99 GVariant *result = NULL;
101 GDBusConnection *conn;
102 GDBusProxy *server_proxy;
105 GUnixFDList *out_fd_list = NULL;
106 conn = _bt_gdbus_get_system_gconn();
107 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
109 adapter_path = _bt_get_device_object_path((char *)address);
110 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
111 BT_INFO_C("Device : %s", adapter_path);
112 server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
114 adapter_path, "org.bluez.Input1", NULL, NULL);
115 g_free(adapter_path);
117 if (server_proxy == NULL) {
118 BT_ERR("Failed to get the network server proxy\n");
119 return BLUETOOTH_ERROR_INTERNAL;
122 result = g_dbus_proxy_call_with_unix_fd_list_sync(server_proxy, "GetFD",
124 G_DBUS_CALL_FLAGS_NONE,
130 if (result == NULL) {
132 g_dbus_error_strip_remote_error(err);
133 BT_ERR("INPUT server register Error: %s\n", err->message);
134 if (g_strcmp0(err->message, "Already Exists") == 0)
135 ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
137 ret = BLUETOOTH_ERROR_INTERNAL;
142 g_variant_get(result, "(hh)", &index1, &index2);
143 int fd1 = g_unix_fd_list_get(out_fd_list, index1, NULL);
144 int fd2 = g_unix_fd_list_get(out_fd_list, index2, NULL);
148 g_object_unref(out_fd_list);
149 g_variant_unref(result);
151 g_object_unref(server_proxy);
155 static GVariant* __bt_hid_agent_dbus_send(const char *path,
156 const char *interface, const char *method,
157 GError **err, GVariant *parameters)
159 GVariant *reply = NULL;
160 GDBusProxy *proxy = NULL;
161 GDBusConnection *conn = NULL;
163 conn = _bt_gdbus_get_system_gconn();
164 retv_if(conn == NULL, NULL);
166 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
167 NULL, BT_HID_SERVICE_NAME, path, interface, NULL, err);
169 BT_ERR("Unable to allocate new proxy");
173 reply = g_dbus_proxy_call_sync(proxy, method, parameters,
174 G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
176 g_object_unref(proxy);
180 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
184 for (l = device_list; l != NULL; l = l->next) {
185 hid_connected_device_info_t *info = l->data;
186 if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
192 static void __hid_connected_cb(hid_connected_device_info_t *info,
195 bluetooth_hid_request_t conn_info;
196 bt_event_info_t *event_info = NULL;
198 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
199 if (event_info == NULL)
202 memset(&conn_info, 0x00, sizeof(bluetooth_hid_request_t));
203 if (info->intr_fd != -1 && info->ctrl_fd == -1)
204 conn_info.socket_fd = info->intr_fd;
206 conn_info.socket_fd = info->ctrl_fd;
207 _bt_convert_addr_string_to_type(conn_info.device_addr.addr, info->address);
209 if (result == BLUETOOTH_ERROR_NONE)
210 BT_INFO_C("Connected [HID Device]");
212 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
214 event_info->cb, event_info->user_data);
217 static void __hid_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
222 GError *error = NULL;
223 GVariant *ret = NULL;
224 hid_connected_device_info_t info;
229 ret = g_dbus_proxy_call_finish(proxy, res, &error);
231 g_dbus_error_strip_remote_error(error);
232 BT_ERR("Error : %s \n", error->message);
234 if (g_strcmp0(error->message, "In Progress") == 0)
235 result = BLUETOOTH_ERROR_DEVICE_BUSY;
237 result = BLUETOOTH_ERROR_INTERNAL;
242 info.address = g_malloc0(BT_ADDRESS_STRING_SIZE);
244 path = g_dbus_proxy_get_object_path(proxy);
245 _bt_convert_device_path_to_address(path, info.address);
247 __hid_connected_cb(&info, result);
249 g_free(info.address);
253 g_variant_unref(ret);
257 g_object_unref(proxy);
262 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
264 bluetooth_hid_request_t disconn_info;
265 int fd = info->ctrl_fd;
266 bt_event_info_t *event_info;
268 BT_INFO_C("Disconnected [HID Device]");
269 device_list = g_slist_remove(device_list, info);
270 if (info->ctrl_data_id > 0) {
271 g_source_remove(info->ctrl_data_id);
272 info->ctrl_data_id = 0;
274 if (info->intr_data_id > 0) {
275 g_source_remove(info->intr_data_id);
276 info->intr_data_id = 0;
279 if (info->ctrl_data_io) {
280 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
281 g_io_channel_unref(info->ctrl_data_io);
282 info->ctrl_data_io = NULL;
284 if (info->intr_data_io) {
285 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
286 g_io_channel_unref(info->intr_data_io);
287 info->intr_data_io = NULL;
289 if (info->intr_fd >= 0) {
290 close(info->ctrl_fd);
291 close(info->intr_fd);
295 info->disconnect_idle_id = 0;
296 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
297 if (event_info == NULL)
300 memset(&disconn_info, 0x00, sizeof(bluetooth_hid_request_t));
301 disconn_info.socket_fd = fd;
302 _bt_convert_addr_string_to_type(disconn_info.device_addr.addr , info->address);
303 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
304 BLUETOOTH_ERROR_NONE, &disconn_info,
305 event_info->cb, event_info->user_data);
307 g_free(info->address);
314 static gboolean __is_error_by_disconnect(GError *err)
316 return !g_strcmp0(err->message, "Connection reset by peer") ||
317 !g_strcmp0(err->message, "Connection timed out") ||
318 !g_strcmp0(err->message, "Software caused connection abort");
321 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
324 hid_connected_device_info_t *info = data;
325 GIOStatus status = G_IO_STATUS_NORMAL;
326 char buffer[BT_RFCOMM_BUFFER_LEN];
329 guint8 header, type, param;
330 bt_event_info_t *event_info;
331 retv_if(info == NULL, FALSE);
333 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
334 BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
335 if (info->disconnect_idle_id > 0) {
336 BT_INFO("Disconnect idle still not process remove source");
337 g_source_remove(info->disconnect_idle_id);
338 info->disconnect_idle_id = 0;
340 __hid_disconnect(info);
344 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
346 if (status == G_IO_STATUS_NORMAL) {
347 BT_INFO("Parsing Data");
348 bluetooth_hid_received_data_t data = {0};
350 type = header & BT_HID_HEADER_TRANS_MASK;
351 param = header & BT_HID_HEADER_PARAM_MASK;
352 BT_INFO("type %d , param %d", type, param);
353 BT_INFO("Data Reveived from %s" , info->address);
355 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
356 if (event_info == NULL)
359 data.address = g_strdup(info->address);
361 case BT_HID_TRANS_HANDSHAKE:
362 BT_INFO("TRANS HANDSHAKE");
363 data.type = HTYPE_TRANS_HANDSHAKE;
364 data.buffer_size = len;
365 data.buffer = (char *) malloc(sizeof(char) * len);
367 memcpy(data.buffer, buffer, len);
370 case BT_HID_TRANS_HID_CONTROL:
371 BT_INFO("HID CONTROL");
372 data.type = HTYPE_TRANS_HID_CONTROL;
373 data.buffer_size = len;
374 data.buffer = (char *) malloc(sizeof(char) * len);
376 memcpy(data.buffer, buffer, len);
379 case BT_HID_TRANS_DATA:
380 BT_INFO("TRANS DATA");
381 data.type = HTYPE_TRANS_DATA;
382 if (param & BT_HID_DATA_RTYPE_INPUT) {
383 BT_INFO("Input Report");
384 data.param = PTYPE_DATA_RTYPE_INPUT;
385 data.buffer_size = len;
386 data.buffer = (char *) malloc(sizeof(char) * len);
388 memcpy(data.buffer, buffer, len);
390 BT_INFO("Out Report");
391 data.param = PTYPE_DATA_RTYPE_OUTPUT;
392 data.buffer_size = len;
393 data.buffer = (char *) malloc(sizeof(char) * len);
395 memcpy(data.buffer, buffer, len);
399 case BT_HID_TRANS_GET_REPORT: {
400 BT_INFO("Get Report");
401 data.type = HTYPE_TRANS_GET_REPORT;
402 if (param & BT_HID_DATA_RTYPE_INPUT) {
403 BT_INFO("Input Report");
404 data.param = PTYPE_DATA_RTYPE_INPUT;
406 BT_INFO("Output Report");
407 data.param = PTYPE_DATA_RTYPE_OUTPUT;
409 data.buffer_size = len;
410 data.buffer = (char *) malloc(sizeof(char) * len);
412 memcpy(data.buffer, buffer, len);
416 case BT_HID_TRANS_SET_REPORT: {
417 BT_INFO("Set Report");
418 data.type = HTYPE_TRANS_SET_REPORT;
419 if (param & BT_HID_DATA_RTYPE_INPUT) {
420 BT_INFO("Input Report");
421 data.param = PTYPE_DATA_RTYPE_INPUT;
423 BT_INFO("Output Report");
424 data.param = PTYPE_DATA_RTYPE_OUTPUT;
426 data.buffer_size = len;
427 data.buffer = (char *) malloc(sizeof(char) * len);
429 memcpy(data.buffer, buffer, len);
433 case BT_HID_TRANS_GET_PROTOCOL:{
434 BT_INFO("Get_PROTOCOL");
435 data.type = HTYPE_TRANS_GET_PROTOCOL;
436 data.param = PTYPE_DATA_RTYPE_INPUT;
437 data.buffer_size = len;
438 data.buffer = (char *) malloc(sizeof(char) * len);
440 memcpy(data.buffer, buffer, len);
444 case BT_HID_TRANS_SET_PROTOCOL:{
445 BT_INFO("Set_PROTOCOL");
446 data.type = HTYPE_TRANS_SET_PROTOCOL;
447 data.param = PTYPE_DATA_RTYPE_INPUT;
448 data.buffer_size = len;
449 data.buffer = (char *) malloc(sizeof(char) * len);
451 memcpy(data.buffer, buffer, len);
455 case BT_HID_TRANS_GET_IDLE:{
457 data.type = HTYPE_TRANS_GET_IDLE;
458 data.param = PTYPE_DATA_RTYPE_INPUT;
459 data.buffer_size = len;
460 data.buffer = (char *) malloc(sizeof(char) * len);
462 memcpy(data.buffer, buffer, len);
466 case BT_HID_TRANS_SET_IDLE:{
468 data.type = HTYPE_TRANS_SET_IDLE;
469 data.param = PTYPE_DATA_RTYPE_INPUT;
470 data.buffer_size = len;
471 data.buffer = (char *) malloc(sizeof(char) * len);
473 memcpy(data.buffer, buffer, len);
478 BT_INFO("unsupported HIDP control message");
479 BT_ERR("Send Handshake Message");
480 guint8 type = BT_HID_TRANS_HANDSHAKE |
481 BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
482 data.type = HTYPE_TRANS_UNKNOWN;
483 int fd = g_io_channel_unix_get_fd(chan);
484 int bytes = write(fd, &type, sizeof(type));
485 BT_INFO("Bytes Written %d", bytes);
490 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
491 BLUETOOTH_ERROR_NONE, &data,
492 event_info->cb, event_info->user_data);
497 g_free((char *)data.address);
499 BT_ERR("Error while reading data %d [%s]", status, info->address);
501 BT_ERR("IO Channel read error [%s]", err->message);
502 if (status == G_IO_STATUS_ERROR &&
503 __is_error_by_disconnect(err)) {
504 BT_DBG("cond : %d", cond);
506 __hid_disconnect(info);
510 } else if (status == G_IO_STATUS_EOF) {
511 __hid_disconnect(info);
518 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
520 hid_connected_device_info_t *dev_info = NULL;
523 _bt_convert_addr_type_to_string((char *)address, addr->addr);
524 BT_INFO("Address [%s]", address);
525 dev_info = __find_hid_info_with_address(address);
526 if (dev_info == NULL) {
527 dev_info = (hid_connected_device_info_t *)
528 g_malloc0(sizeof(hid_connected_device_info_t));
530 dev_info->intr_fd = -1;
531 dev_info->ctrl_fd = -1;
532 dev_info->intr_fd = fd;
533 dev_info->address = g_strdup(address);
534 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
535 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
536 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
537 g_io_channel_set_close_on_unref(dev_info->intr_data_io, TRUE);
538 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
539 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
540 __received_cb, dev_info);
541 device_list = g_slist_append(device_list, dev_info);
543 dev_info->ctrl_fd = fd;
544 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
545 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
546 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
547 g_io_channel_set_close_on_unref(dev_info->ctrl_data_io, TRUE);
548 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
549 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
550 __received_cb, dev_info);
553 if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1)
554 __hid_connected_cb(dev_info, BLUETOOTH_ERROR_NONE);
559 static void __free_hid_info(void *data)
563 hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
565 if (dev_info->disconnect_idle_id > 0) {
566 BT_INFO("Disconnect idle still not process remove source");
567 g_source_remove(dev_info->disconnect_idle_id);
568 dev_info->disconnect_idle_id = 0;
570 __hid_disconnect(dev_info);
573 void _bluetooth_hid_free_hid_info(void)
575 g_slist_free_full(device_list, __free_hid_info);
580 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
584 /* Register HID Device events */
585 BT_INFO("BT_HID_DEVICE_EVENT");
586 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
588 if (ret != BLUETOOTH_ERROR_NONE &&
589 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
590 BT_ERR("Fail to init the event handler");
594 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
596 return BLUETOOTH_ERROR_NONE;
599 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
603 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
605 if (ret != BLUETOOTH_ERROR_NONE) {
606 BT_ERR("Fail to deinit the event handler");
610 _bt_set_user_data(BT_HID, NULL, NULL);
612 return BLUETOOTH_ERROR_NONE;
615 BT_EXPORT_API int bluetooth_hid_device_activate(void)
620 BT_CHECK_ENABLED(return);
622 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
623 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
624 BT_ERR("Don't have a privilege to use this API");
625 return BLUETOOTH_ERROR_PERMISSION_DEINED;
628 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
629 BT_HID_SERVICE_INTERFACE,
630 "RegisterApplication", &err, NULL);
633 int ret = BLUETOOTH_ERROR_INTERNAL;
634 BT_ERR("Error returned in method call");
636 BT_ERR("Error = %s", err->message);
637 if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
638 ret = BLUETOOTH_ERROR_IN_PROGRESS;
640 ret = BLUETOOTH_ERROR_INTERNAL;
646 g_variant_unref(reply);
648 return BLUETOOTH_ERROR_NONE;
651 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
656 BT_CHECK_ENABLED(return);
658 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
659 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
660 BT_ERR("Don't have a privilege to use this API");
661 return BLUETOOTH_ERROR_PERMISSION_DEINED;
664 reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
665 BT_HID_SERVICE_INTERFACE,
666 "UnregisterApplication", &err, NULL);
669 int ret = BLUETOOTH_ERROR_INTERNAL;
670 BT_ERR("Error returned in method call");
672 BT_ERR("Error = %s", err->message);
673 if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
674 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
676 ret = BLUETOOTH_ERROR_INTERNAL;
682 g_variant_unref(reply);
684 _bluetooth_hid_free_hid_info();
686 return BLUETOOTH_ERROR_NONE;
689 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
691 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
692 hid_connected_device_info_t *info = NULL;
695 BT_CHECK_PARAMETER(remote_addr, return);
697 BT_CHECK_ENABLED(return);
699 info = __find_hid_info_with_address(remote_addr);
701 BT_ERR("Connection Already Exists");
702 return BLUETOOTH_ERROR_ALREADY_CONNECT;
704 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
705 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
706 BT_ERR("Don't have a privilege to use this API");
707 return BLUETOOTH_ERROR_PERMISSION_DEINED;
710 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
711 ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
712 __hid_connect_response_cb, NULL);
716 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
718 BT_CHECK_PARAMETER(remote_addr, return);
720 BT_CHECK_ENABLED(return);
722 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
723 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
724 BT_ERR("Don't have a privilege to use this API");
725 return BLUETOOTH_ERROR_PERMISSION_DEINED;
728 hid_connected_device_info_t *info = NULL;
730 info = __find_hid_info_with_address(remote_addr);
732 return BLUETOOTH_ERROR_INVALID_PARAM;
734 _bt_disconnect_profile((char *)remote_addr, HID_DEVICE_UUID, NULL, NULL);
736 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
739 return BLUETOOTH_ERROR_NONE;
741 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
742 hid_send_mouse_event_t send_event)
746 hid_connected_device_info_t *info = NULL;
748 BT_CHECK_PARAMETER(remote_addr, return);
750 switch (privilege_token_send_mouse) {
752 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
754 if (result == BLUETOOTH_ERROR_NONE) {
755 privilege_token_send_mouse = 1; /* Have a permission */
756 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
757 BT_ERR("Don't have a privilege to use this API");
758 privilege_token_send_mouse = -1; /* Don't have a permission */
759 return BLUETOOTH_ERROR_PERMISSION_DEINED;
761 /* Just break - It is not related with permission error */
765 /* Already have a privilege */
768 return BLUETOOTH_ERROR_PERMISSION_DEINED;
770 /* Invalid privilge token value */
771 return BLUETOOTH_ERROR_INTERNAL;
773 info = __find_hid_info_with_address(remote_addr);
775 BT_ERR("Connection Information not found");
776 return BLUETOOTH_ERROR_INVALID_PARAM;
780 if (info->intr_fd != -1 && info->ctrl_fd == -1)
781 socket_fd = info->intr_fd;
783 socket_fd = info->ctrl_fd;
785 written = write(socket_fd, &send_event, sizeof(send_event));
790 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
791 hid_send_key_event_t send_event)
795 hid_connected_device_info_t *info = NULL;
797 BT_CHECK_PARAMETER(remote_addr, return);
799 switch (privilege_token_send_key) {
801 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_KEY_EVENT);
803 if (result == BLUETOOTH_ERROR_NONE) {
804 privilege_token_send_key = 1; /* Have a permission */
805 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
806 BT_ERR("Don't have a privilege to use this API");
807 privilege_token_send_key = -1; /* Don't have a permission */
808 return BLUETOOTH_ERROR_PERMISSION_DEINED;
810 /* Just break - It is not related with permission error */
814 /* Already have a privilege */
817 return BLUETOOTH_ERROR_PERMISSION_DEINED;
819 /* Invalid privilge token value */
820 return BLUETOOTH_ERROR_INTERNAL;
823 info = __find_hid_info_with_address(remote_addr);
825 BT_ERR("Connection Information not found");
826 return BLUETOOTH_ERROR_INVALID_PARAM;
831 if (info->intr_fd != -1 && info->ctrl_fd == -1)
832 socket_fd = info->intr_fd;
834 socket_fd = info->ctrl_fd;
836 written = write(socket_fd, &send_event, sizeof(send_event));
840 BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr,
841 unsigned char btcode, unsigned char report_id,
842 const char *data, unsigned int data_len)
847 hid_connected_device_info_t *info = NULL;
848 char *send_event = NULL;
850 BT_CHECK_PARAMETER(remote_addr, return);
851 BT_CHECK_PARAMETER(data, return);
853 switch (privilege_token_send_key) {
855 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_CUSTOM_EVENT);
857 if (result == BLUETOOTH_ERROR_NONE) {
858 privilege_token_send_key = 1; /* Have a permission */
859 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
860 BT_ERR("Don't have a privilege to use this API");
861 privilege_token_send_key = -1; /* Don't have a permission */
862 return BLUETOOTH_ERROR_PERMISSION_DEINED;
864 /* Just break - It is not related with permission error */
868 /* Already have a privilege */
871 return BLUETOOTH_ERROR_PERMISSION_DEINED;
873 /* Invalid privilge token value */
874 return BLUETOOTH_ERROR_INTERNAL;
877 info = __find_hid_info_with_address(remote_addr);
879 BT_ERR("Connection Information not found");
880 return BLUETOOTH_ERROR_INVALID_PARAM;
883 if (info->intr_fd != -1 && info->ctrl_fd == -1)
884 socket_fd = info->intr_fd;
886 socket_fd = info->ctrl_fd;
888 send_event = g_malloc0(data_len + 2);
890 send_event[0] = (char)btcode;
891 send_event[1] = (char)report_id;
892 memcpy(send_event + 2, data, data_len);
894 written = write(socket_fd, send_event, data_len + 2);
901 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
902 bt_hid_header_type_t htype,
903 bt_hid_param_type_t ptype,
905 unsigned int data_len)
908 struct reports output_report = { 0 };
909 int bytes = BLUETOOTH_ERROR_INTERNAL;
910 hid_connected_device_info_t *info = NULL;
911 info = __find_hid_info_with_address(remote_addr);
913 BT_ERR("Connection Information not found");
914 return BLUETOOTH_ERROR_INVALID_PARAM;
917 BT_CHECK_PARAMETER(remote_addr, return);
919 switch (privilege_token_reply) {
921 result = _bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
923 if (result == BLUETOOTH_ERROR_NONE) {
924 privilege_token_reply = 1; /* Have a permission */
925 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
926 BT_ERR("Don't have a privilege to use this API");
927 privilege_token_reply = -1; /* Don't have a permission */
928 return BLUETOOTH_ERROR_PERMISSION_DEINED;
930 /* Just break - It is not related with permission error */
934 /* Already have a privilege */
937 return BLUETOOTH_ERROR_PERMISSION_DEINED;
939 /* Invalid privilge token value */
940 return BLUETOOTH_ERROR_INTERNAL;
943 BT_INFO("htype %d ptype %d", htype, ptype);
945 case HTYPE_TRANS_GET_REPORT: {
947 case PTYPE_DATA_RTYPE_INPUT: {
948 output_report.type = BT_HID_TRANS_DATA |
949 BT_HID_DATA_RTYPE_INPUT;
950 memcpy(output_report.rep_data, data, data_len);
951 bytes = write(info->intr_fd, &output_report,
952 sizeof(output_report));
953 BT_DBG("Bytes Written %d", bytes);
957 BT_INFO("Not Supported");
962 case HTYPE_TRANS_GET_PROTOCOL: {
963 BT_DBG("Replying to Get_PROTOCOL");
964 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
965 output_report.rep_data[0] = data[0];
966 bytes = write(info->intr_fd, &output_report, 2);
967 BT_DBG("Bytes Written %d", bytes);
971 case HTYPE_TRANS_SET_PROTOCOL: {
972 BT_DBG("Reply to Set_Protocol");
973 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
974 memcpy(output_report.rep_data, data, data_len);
975 bytes = write(info->ctrl_fd, &output_report,
976 sizeof(output_report));
977 BT_DBG("Bytes Written %d", bytes);
981 case HTYPE_TRANS_HANDSHAKE: {
982 BT_DBG("Replying Handshake");
983 output_report.type = BT_HID_TRANS_HANDSHAKE | data[0];
984 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
985 bytes = write(info->intr_fd, &output_report.type,
986 sizeof(output_report.type));
987 BT_DBG("Bytes Written %d", bytes);
991 case HTYPE_TRANS_GET_IDLE: {
992 BT_DBG("Replying to Get_IDLE");
993 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
994 output_report.rep_data[0] = data[0];
995 bytes = write(info->intr_fd, &output_report, 2);
996 BT_DBG("Bytes Written %d", bytes);
1000 case HTYPE_TRANS_SET_IDLE: {
1001 BT_DBG("Reply to Set_IDLE");
1002 output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
1003 memcpy(output_report.rep_data, data, data_len);
1004 bytes = write(info->ctrl_fd, &output_report,
1005 sizeof(output_report));
1006 BT_DBG("Bytes Written %d", bytes);