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 REPORTID_MOUSE 1
30 #define BT_HID_BUFFER_LEN 100
32 /* The types of HIDP transaction */
33 #define BT_HIDP_TRANSACTION_SET_PROTOCOL 0x70
34 #define BT_HIDP_TRANSACTION_GET_IDLE 0x80
35 #define BT_HIDP_TRANSACTION_SET_IDLE 0x90
36 #define BT_HIDP_TRANSACTION_DATA 0xa0
37 #define BT_HIDP_TRANSACTION_DATC 0xb0
38 #define BT_HIDP_TRANSACTION_HANDSHAKE 0x00
39 #define BT_HIDP_TRANSACTION_HID_CONTROL 0x10
40 #define BT_HIDP_TRANSACTION_GET_REPORT 0x40
41 #define BT_HIDP_TRANSACTION_SET_REPORT 0x50
42 #define BT_HIDP_TRANSACTION_GET_PROTOCOL 0x60
44 #define BT_HIDP_DATA_OUT_RTYPE 0x02
45 #define BT_HIDP_DATA_IN_RTYPE 0x01
47 #define BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST 0x03
48 #define BT_HIDP_HSHK_ERROR_INVALID_PARAM 0x04
49 #define BT_HIDP_HSHK_ERROR_UNKNOWN 0x0E
50 #define BT_HIDP_HSHK_ERROR_FATAL 0x0F
51 #define BT_HIDP_HSHK_OK_SUCCESSFUL 0x00
52 #define BT_HIDP_HSHK_NOT_AVAILABLE 0x01
53 #define BT_HIDP_HSHK_ERROR_INVALID_REPORT_ID 0x02
55 /* The masks of BT_HIDP header */
56 #define BT_HIDP_HEADER_PARAMETER_MASK 0x0f
57 #define BT_HIDP_HEADER_TRANSACTION_MASK 0xf0
70 GIOChannel *ctrl_data_io;
71 GIOChannel *intr_data_io;
75 guint disconnect_idle_id;
76 } hid_connected_device_info_t;
81 } __attribute__((__packed__));
83 static hid_info_t *hid_info = NULL;
85 /* Variable for privilege, only for write API,
86 before we should reduce time to bt-service dbus calling
87 -1 : Don't have a permission to access API
88 0 : Initial value, not yet check
89 1 : Have a permission to access API
91 static int privilege_token_send_mouse = 0;
92 static int privilege_token_send_key = 0;
93 static int privilege_token_reply = 0;
95 static gboolean __hid_disconnect(hid_connected_device_info_t *info);
97 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
101 for (l = hid_info->device_list; l != NULL; l = l->next) {
102 hid_connected_device_info_t *info = l->data;
103 if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
109 static void __hid_connected_cb(hid_connected_device_info_t *info,
110 bt_event_info_t *event_info)
112 bluetooth_hid_request_t conn_info;
114 memset(&conn_info, 0x00, sizeof(bluetooth_hid_request_t));
115 if (info->intr_fd != -1 && info->ctrl_fd == -1)
116 conn_info.socket_fd = info->intr_fd;
118 conn_info.socket_fd = info->ctrl_fd;
119 _bt_convert_addr_string_to_type(conn_info.device_addr.addr, info->address);
121 BT_INFO_C("Connected [HID Device]");
122 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
123 BLUETOOTH_ERROR_NONE, &conn_info,
124 event_info->cb, event_info->user_data);
127 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
129 bluetooth_hid_request_t disconn_info;
130 int fd = info->ctrl_fd;
131 bt_event_info_t *event_info;
133 BT_INFO_C("Disconnected [HID Device]");
134 hid_info->device_list = g_slist_remove(hid_info->device_list, info);
135 if (info->ctrl_data_id > 0) {
136 g_source_remove(info->ctrl_data_id);
137 info->ctrl_data_id = 0;
139 if (info->intr_data_id > 0) {
140 g_source_remove(info->intr_data_id);
141 info->intr_data_id = 0;
144 if (info->intr_fd >= 0) {
145 close(info->ctrl_fd);
146 close(info->intr_fd);
151 if (info->ctrl_data_io) {
152 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
153 g_io_channel_unref(info->ctrl_data_io);
154 info->ctrl_data_io = NULL;
156 if (info->intr_data_io) {
157 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
158 g_io_channel_unref(info->intr_data_io);
159 info->intr_data_io = NULL;
161 info->disconnect_idle_id = 0;
162 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
163 if (event_info == NULL)
166 memset(&disconn_info, 0x00, sizeof(bluetooth_hid_request_t));
167 disconn_info.socket_fd = fd;
168 _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, info->address);
169 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
170 BLUETOOTH_ERROR_NONE, &disconn_info,
171 event_info->cb, event_info->user_data);
173 g_free(info->address);
180 void __free_hid_info(hid_info_t *info)
184 _bt_unregister_gdbus(info->object_id);
186 while (info->device_list) {
187 hid_connected_device_info_t *dev_info = NULL;
188 dev_info = (hid_connected_device_info_t *)info->device_list->data;
190 if (dev_info->disconnect_idle_id > 0) {
191 BT_INFO("Disconnect idle still not process remove source");
192 g_source_remove(dev_info->disconnect_idle_id);
193 dev_info->disconnect_idle_id = 0;
195 __hid_disconnect(dev_info);
203 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
206 hid_connected_device_info_t *info = data;
207 GIOStatus status = G_IO_STATUS_NORMAL;
211 guint8 header, type, param;
212 bt_event_info_t *event_info;
213 retv_if(info == NULL, FALSE);
215 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
216 BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
217 if (info->disconnect_idle_id > 0) {
218 BT_INFO("Disconnect idle still not process remove source");
219 g_source_remove(info->disconnect_idle_id);
220 info->disconnect_idle_id = 0;
222 __hid_disconnect(info);
225 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
227 if (status == G_IO_STATUS_NORMAL) {
228 BT_INFO("Parsing Data");
229 bluetooth_hid_received_data_t data = {0};
231 type = header & BT_HIDP_HEADER_TRANSACTION_MASK;
232 param = header & BT_HIDP_HEADER_PARAMETER_MASK;
233 BT_INFO("type %d , param %d", type, param);
234 BT_INFO("Data Reveived from %s" , info->address);
235 data.address = g_strdup(info->address);
237 case BT_HIDP_TRANSACTION_HANDSHAKE:
238 BT_INFO("TRANS HANDSHAKE");
239 data.type = HTYPE_TRANS_HANDSHAKE;
240 data.buffer_size = len;
241 data.buffer = (char *) malloc(sizeof(char) * len);
243 memcpy(data.buffer, buffer, len);
245 case BT_HIDP_TRANSACTION_HID_CONTROL:
246 BT_INFO("HID CONTROL");
247 data.type = HTYPE_TRANS_HID_CONTROL;
248 data.buffer_size = len;
249 data.buffer = (char *) malloc(sizeof(char) * len);
251 memcpy(data.buffer, buffer, len);
253 case BT_HIDP_TRANSACTION_DATA:
254 BT_INFO("TRANS DATA");
255 data.type = HTYPE_TRANS_DATA;
256 if (param & BT_HIDP_DATA_IN_RTYPE) {
257 BT_INFO("Input Report");
258 data.param = PTYPE_DATA_RTYPE_INPUT;
259 data.buffer_size = len;
260 data.buffer = (char *) malloc(sizeof(char) * len);
262 memcpy(data.buffer, buffer, len);
264 BT_INFO("Out Report");
265 data.param = PTYPE_DATA_RTYPE_OUTPUT;
266 data.buffer_size = len;
267 data.buffer = (char *) malloc(sizeof(char) * len);
269 memcpy(data.buffer, buffer, len);
272 case BT_HIDP_TRANSACTION_GET_REPORT: {
273 BT_INFO("Get Report");
274 data.type = HTYPE_TRANS_GET_REPORT;
275 if (param & BT_HIDP_DATA_IN_RTYPE) {
276 BT_INFO("Input Report");
277 data.param = PTYPE_DATA_RTYPE_INPUT;
279 BT_INFO("Output Report");
280 data.param = PTYPE_DATA_RTYPE_OUTPUT;
282 data.buffer_size = len;
283 data.buffer = (char *) malloc(sizeof(char) * len);
285 memcpy(data.buffer, buffer, len);
288 case BT_HIDP_TRANSACTION_SET_REPORT: {
289 BT_INFO("Set Report");
290 data.type = HTYPE_TRANS_SET_REPORT;
291 if (param & BT_HIDP_DATA_IN_RTYPE) {
292 BT_INFO("Input Report");
293 data.param = PTYPE_DATA_RTYPE_INPUT;
295 BT_INFO("Output Report");
296 data.param = PTYPE_DATA_RTYPE_OUTPUT;
298 data.buffer_size = len;
299 data.buffer = (char *) malloc(sizeof(char) * len);
301 memcpy(data.buffer, buffer, len);
304 case BT_HIDP_TRANSACTION_GET_PROTOCOL:{
305 BT_INFO("Get_PROTOCOL");
306 data.type = HTYPE_TRANS_GET_PROTOCOL;
307 data.param = PTYPE_DATA_RTYPE_INPUT;
308 data.buffer_size = len;
309 data.buffer = (char *) malloc(sizeof(char) * len);
311 memcpy(data.buffer, buffer, len);
314 case BT_HIDP_TRANSACTION_SET_PROTOCOL:{
315 BT_INFO("Set_PROTOCOL");
316 data.type = HTYPE_TRANS_SET_PROTOCOL;
317 data.param = PTYPE_DATA_RTYPE_INPUT;
318 data.buffer_size = len;
319 data.buffer = (char *) malloc(sizeof(char) * len);
321 memcpy(data.buffer, buffer, len);
325 BT_INFO("unsupported HIDP control message");
326 BT_ERR("Send Handshake Message");
327 guint8 type = BT_HIDP_TRANSACTION_HANDSHAKE |
328 BT_HIDP_HSHK_ERROR_UNSUPPORTED_REQUEST;
329 data.type = HTYPE_TRANS_UNKNOWN;
330 int fd = g_io_channel_unix_get_fd(chan);
331 int bytes = write(fd, &type, sizeof(type));
332 BT_INFO("Bytes Written %d", bytes);
336 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
337 if (event_info == NULL) {
339 g_free((char *)data.address);
343 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
344 BLUETOOTH_ERROR_NONE, &data,
345 event_info->cb, event_info->user_data);
348 g_free((char *)data.address);
350 BT_INFO("Error while reading data");
355 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
357 hid_info_t *info = NULL;
358 hid_connected_device_info_t *dev_info = NULL;
359 bt_event_info_t *event_info = NULL;
365 _bt_convert_addr_type_to_string((char *)address, addr->addr);
366 BT_INFO("Address [%s]", address);
367 dev_info = __find_hid_info_with_address(address);
368 if (dev_info == NULL) {
369 dev_info = (hid_connected_device_info_t *)
370 g_malloc0(sizeof(hid_connected_device_info_t));
371 if (dev_info == NULL) {
372 BT_ERR("Fail to allocation memory");
376 dev_info->intr_fd = -1;
377 dev_info->ctrl_fd = -1;
378 dev_info->intr_fd = fd;
379 dev_info->address = g_strdup(address);
380 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
381 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
382 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
384 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
385 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
386 __received_cb, dev_info);
387 hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
389 dev_info->ctrl_fd = fd;
390 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
391 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
392 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
394 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
395 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
396 __received_cb, dev_info);
398 if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1) {
399 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
401 __hid_connected_cb(dev_info, event_info);
406 static hid_info_t *__register_method()
409 hid_info_t *info = NULL;
411 path = g_strdup_printf("/org/socket/server/%d", getpid());
413 object_id = _bt_register_new_conn(path, new_hid_connection);
417 info = g_new(hid_info_t, 1);
418 info->object_id = (guint)object_id;
421 info->device_list = NULL;
426 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
430 /* Register HID Device events */
431 BT_INFO("BT_HID_DEVICE_EVENT");
432 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
434 if (ret != BLUETOOTH_ERROR_NONE &&
435 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
436 BT_ERR("Fail to init the event handler");
440 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
442 return BLUETOOTH_ERROR_NONE;
445 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
449 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
451 if (ret != BLUETOOTH_ERROR_NONE) {
452 BT_ERR("Fail to deinit the event handler");
456 _bt_set_user_data(BT_HID, NULL, NULL);
458 return BLUETOOTH_ERROR_NONE;
461 BT_EXPORT_API int bluetooth_hid_device_activate(void)
463 bt_register_profile_info_t profile_info;
464 int result = BLUETOOTH_ERROR_NONE;
466 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
467 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
468 BT_ERR("Don't have a privilege to use this API");
469 return BLUETOOTH_ERROR_PERMISSION_DEINED;
472 if (hid_info != NULL)
473 return BLUETOOTH_ERROR_IN_PROGRESS;
475 hid_info = __register_method();
476 if (hid_info == NULL)
477 return BLUETOOTH_ERROR_INTERNAL;
479 hid_info->uuid = g_strdup(HID_UUID);
481 profile_info.authentication = TRUE;
482 profile_info.authorization = TRUE;
483 profile_info.obj_path = hid_info->path;
484 profile_info.role = g_strdup("Hid");
485 profile_info.service = hid_info->uuid;
486 profile_info.uuid = hid_info->uuid;
488 BT_INFO("uuid %s", profile_info.uuid);
489 result = _bt_register_profile_platform(&profile_info, FALSE);
494 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
496 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
497 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
498 BT_ERR("Don't have a privilege to use this API");
499 return BLUETOOTH_ERROR_PERMISSION_DEINED;
502 if (hid_info == NULL)
503 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
505 _bt_unregister_profile(hid_info->path);
507 __free_hid_info(hid_info);
509 return BLUETOOTH_ERROR_NONE;
512 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
514 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
515 hid_connected_device_info_t *info = NULL;
518 BT_CHECK_PARAMETER(remote_addr, return);
520 info = __find_hid_info_with_address(remote_addr);
522 BT_ERR("Connection Already Exists");
523 return BLUETOOTH_ERROR_ALREADY_CONNECT;
525 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
526 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
527 BT_ERR("Don't have a privilege to use this API");
528 return BLUETOOTH_ERROR_PERMISSION_DEINED;
531 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
532 ret = _bt_connect_profile(device_address, HID_UUID, NULL, NULL);
536 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
538 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
539 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
540 BT_ERR("Don't have a privilege to use this API");
541 return BLUETOOTH_ERROR_PERMISSION_DEINED;
543 hid_connected_device_info_t *info = NULL;
545 info = __find_hid_info_with_address(remote_addr);
547 return BLUETOOTH_ERROR_INVALID_PARAM;
549 _bt_disconnect_profile((char *)remote_addr, HID_UUID, NULL, NULL);
551 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
554 return BLUETOOTH_ERROR_NONE;
556 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
557 hid_send_mouse_event_t send_event)
562 hid_connected_device_info_t *info = NULL;
564 switch (privilege_token_send_mouse) {
566 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
568 if (result == BLUETOOTH_ERROR_NONE) {
569 privilege_token_send_mouse = 1; /* Have a permission */
570 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
571 BT_ERR("Don't have a privilege to use this API");
572 privilege_token_send_mouse = -1; /* Don't have a permission */
573 return BLUETOOTH_ERROR_PERMISSION_DEINED;
575 /* Just break - It is not related with permission error */
579 /* Already have a privilege */
582 return BLUETOOTH_ERROR_PERMISSION_DEINED;
584 /* Invalid privilge token value */
585 return BLUETOOTH_ERROR_INTERNAL;
587 info = __find_hid_info_with_address(remote_addr);
589 BT_ERR("Connection Information not found");
590 return BLUETOOTH_ERROR_INVALID_PARAM;
593 if (info->intr_fd != -1 && info->ctrl_fd == -1)
594 socket_fd = info->intr_fd;
596 socket_fd = info->ctrl_fd;
598 written = write(socket_fd, &send_event, sizeof(send_event));
603 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
604 hid_send_key_event_t send_event)
609 hid_connected_device_info_t *info = NULL;
611 switch (privilege_token_send_key) {
613 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_KEY_EVENT);
615 if (result == BLUETOOTH_ERROR_NONE) {
616 privilege_token_send_key = 1; /* Have a permission */
617 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
618 BT_ERR("Don't have a privilege to use this API");
619 privilege_token_send_key = -1; /* Don't have a permission */
620 return BLUETOOTH_ERROR_PERMISSION_DEINED;
622 /* Just break - It is not related with permission error */
626 /* Already have a privilege */
629 return BLUETOOTH_ERROR_PERMISSION_DEINED;
631 /* Invalid privilge token value */
632 return BLUETOOTH_ERROR_INTERNAL;
635 info = __find_hid_info_with_address(remote_addr);
637 BT_ERR("Connection Information not found");
638 return BLUETOOTH_ERROR_INVALID_PARAM;
641 if (info->intr_fd != -1 && info->ctrl_fd == -1)
642 socket_fd = info->intr_fd;
644 socket_fd = info->ctrl_fd;
646 written = write(socket_fd, &send_event, sizeof(send_event));
650 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
651 bt_hid_header_type_t htype,
652 bt_hid_param_type_t ptype,
654 unsigned int data_len)
657 struct reports output_report = { 0 };
659 hid_connected_device_info_t *info = NULL;
660 info = __find_hid_info_with_address(remote_addr);
662 BT_ERR("Connection Information not found");
663 return BLUETOOTH_ERROR_INVALID_PARAM;
666 switch (privilege_token_reply) {
668 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
670 if (result == BLUETOOTH_ERROR_NONE) {
671 privilege_token_reply = 1; /* Have a permission */
672 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
673 BT_ERR("Don't have a privilege to use this API");
674 privilege_token_reply = -1; /* Don't have a permission */
675 return BLUETOOTH_ERROR_PERMISSION_DEINED;
677 /* Just break - It is not related with permission error */
681 /* Already have a privilege */
684 return BLUETOOTH_ERROR_PERMISSION_DEINED;
686 /* Invalid privilge token value */
687 return BLUETOOTH_ERROR_INTERNAL;
690 BT_INFO("htype %d ptype %d", htype, ptype);
692 case HTYPE_TRANS_GET_REPORT: {
694 case PTYPE_DATA_RTYPE_INPUT: {
695 output_report.type = BT_HIDP_TRANSACTION_DATA |
696 BT_HIDP_DATA_IN_RTYPE;
697 memcpy(output_report.rep_data, data, data_len);
698 bytes = write(info->intr_fd, &output_report,
699 sizeof(output_report));
700 BT_DBG("Bytes Written %d", bytes);
704 BT_INFO("Not Supported");
708 case HTYPE_TRANS_GET_PROTOCOL: {
709 BT_DBG("Replying to Get_PROTOCOL");
710 output_report.type = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_OUT_RTYPE;
711 output_report.rep_data[0] = data[0];
712 bytes = write(info->intr_fd, &output_report, 2);
713 BT_DBG("Bytes Written %d", bytes);
716 case HTYPE_TRANS_SET_PROTOCOL: {
717 BT_DBG("Reply to Set_Protocol");
718 output_report.type = BT_HIDP_TRANSACTION_DATA | BT_HIDP_DATA_IN_RTYPE;
719 memcpy(output_report.rep_data, data, data_len);
720 bytes = write(info->ctrl_fd, &output_report,
721 sizeof(output_report));
722 BT_DBG("Bytes Written %d", bytes);
725 case HTYPE_TRANS_HANDSHAKE: {
726 BT_DBG("Replying Handshake");
727 output_report.type = BT_HIDP_TRANSACTION_HANDSHAKE | data[0];
728 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
729 bytes = write(info->intr_fd, &output_report.type,
730 sizeof(output_report.type));
731 BT_DBG("Bytes Written %d", bytes);