4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
24 #include <gio/gunixfdlist.h>
25 #include <sys/socket.h>
27 #include "bluetooth-api.h"
28 #include "bt-internal-types.h"
29 #include "bluetooth-hid-api.h"
30 #include "bt-common.h"
31 #include "bt-request-sender.h"
32 #include "bt-event-handler.h"
34 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
35 #define REPORTID_MOUSE 1
36 #define BT_HID_BUFFER_LEN 100
38 /* HIDP header masks */
39 #define HIDP_HEADER_TRANS_MASK 0xf0
40 #define HIDP_HEADER_PARAM_MASK 0x0f
42 /* HIDP transaction types */
43 #define HIDP_TRANS_HANDSHAKE 0x00
44 #define HIDP_TRANS_HID_CONTROL 0x10
45 #define HIDP_TRANS_GET_REPORT 0x40
46 #define HIDP_TRANS_SET_REPORT 0x50
47 #define HIDP_TRANS_GET_PROTOCOL 0x60
48 #define HIDP_TRANS_SET_PROTOCOL 0x70
49 #define HIDP_TRANS_GET_IDLE 0x80
50 #define HIDP_TRANS_SET_IDLE 0x90
51 #define HIDP_TRANS_DATA 0xa0
52 #define HIDP_TRANS_DATC 0xb0
54 #define HIDP_DATA_RTYPE_INPUT 0x01
55 #define HIDP_DATA_RTYPE_OUTPUT 0x02
57 #define HIDP_HSHK_SUCCESSFUL 0x00
58 #define HIDP_HSHK_NOT_READY 0x01
59 #define HIDP_HSHK_ERR_INVALID_REPORT_ID 0x02
60 #define HIDP_HSHK_ERR_UNSUPPORTED_REQUEST 0x03
61 #define HIDP_HSHK_ERR_INVALID_PARAMETER 0x04
62 #define HIDP_HSHK_ERR_UNKNOWN 0x0E
63 #define HIDP_HSHK_ERR_FATAL 0x0F
76 GIOChannel *ctrl_data_io;
77 GIOChannel *intr_data_io;
81 guint disconnect_idle_id;
82 } hid_connected_device_info_t;
87 }__attribute__((__packed__));
89 static hid_info_t *hid_info = NULL;
91 /* Variable for privilege, only for write API,
92 before we should reduce time to bt-service dbus calling
93 -1 : Don't have a permission to access API
94 0 : Initial value, not yet check
95 1 : Have a permission to access API
97 static int privilege_token_send_mouse = 0;
98 static int privilege_token_send_key = 0;
99 static int privilege_token_reply = 0;
101 static gboolean __hid_disconnect(hid_connected_device_info_t *info);
103 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
107 for ( l = hid_info->device_list; l != NULL; l = l->next) {
108 hid_connected_device_info_t *info = l->data;
109 if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
115 static void __hid_connected_cb(hid_connected_device_info_t *info,
116 bt_event_info_t *event_info)
118 bluetooth_hid_request_t conn_info;
120 memset(&conn_info, 0x00, sizeof(bluetooth_hid_request_t));
121 if (info->intr_fd != -1 && info->ctrl_fd == -1)
122 conn_info.socket_fd = info->intr_fd;
124 conn_info.socket_fd = info->ctrl_fd;
125 _bt_convert_addr_string_to_type (conn_info.device_addr.addr , info->address);
127 BT_INFO_C("Connected [HID Device]");
128 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_CONNECTED,
129 BLUETOOTH_ERROR_NONE, &conn_info,
130 event_info->cb, event_info->user_data);
133 static gboolean __hid_disconnect(hid_connected_device_info_t *info)
135 bluetooth_hid_request_t disconn_info;
136 int fd = info->ctrl_fd;
137 bt_event_info_t *event_info;
139 BT_INFO_C("Disconnected [HID Device]");
140 hid_info->device_list = g_slist_remove(hid_info->device_list, info);
141 if (info->ctrl_data_id > 0) {
142 g_source_remove(info->ctrl_data_id);
143 info->ctrl_data_id = 0;
145 if (info->intr_data_id > 0) {
146 g_source_remove(info->intr_data_id);
147 info->intr_data_id = 0;
150 if (info->intr_fd >= 0) {
151 close(info->ctrl_fd);
152 close(info->intr_fd);
157 if (info->ctrl_data_io) {
158 g_io_channel_shutdown(info->ctrl_data_io, TRUE, NULL);
159 g_io_channel_unref(info->ctrl_data_io);
160 info->ctrl_data_io = NULL;
162 if (info->intr_data_io) {
163 g_io_channel_shutdown(info->intr_data_io, TRUE, NULL);
164 g_io_channel_unref(info->intr_data_io);
165 info->intr_data_io = NULL;
167 info->disconnect_idle_id = 0;
168 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
169 if (event_info == NULL)
172 memset(&disconn_info, 0x00, sizeof(bluetooth_hid_request_t));
173 disconn_info.socket_fd = fd;
174 _bt_convert_addr_string_to_type (disconn_info.device_addr.addr , info->address);
175 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DISCONNECTED,
176 BLUETOOTH_ERROR_NONE, &disconn_info,
177 event_info->cb, event_info->user_data);
179 g_free(info->address);
186 void __free_hid_info(hid_info_t *info)
190 _bt_unregister_gdbus(info->object_id);
192 while (info->device_list) {
193 hid_connected_device_info_t *dev_info = NULL;
194 dev_info = (hid_connected_device_info_t *)info->device_list->data;
196 if (dev_info->disconnect_idle_id > 0) {
197 BT_INFO("Disconnect idle still not process remove source");
198 g_source_remove(dev_info->disconnect_idle_id);
199 dev_info->disconnect_idle_id = 0;
201 __hid_disconnect(dev_info);
209 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
212 hid_connected_device_info_t *info = data;
213 GIOStatus status = G_IO_STATUS_NORMAL;
217 guint8 header, type, param;
218 bt_event_info_t *event_info;
219 retv_if(info == NULL, FALSE);
221 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
222 BT_ERR_C("HID disconnected: %d", info->ctrl_fd);
223 if (info->disconnect_idle_id > 0) {
224 BT_INFO("Disconnect idle still not process remove source");
225 g_source_remove(info->disconnect_idle_id);
226 info->disconnect_idle_id = 0;
228 __hid_disconnect(info);
231 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
233 if (status == G_IO_STATUS_NORMAL) {
234 BT_INFO("Parsing Data");
235 bluetooth_hid_received_data_t data = {0};
237 type = header & HIDP_HEADER_TRANS_MASK;
238 param = header & HIDP_HEADER_PARAM_MASK;
239 BT_INFO("type %d , param %d", type, param);
240 BT_INFO("Data Reveived from %s" , info->address);
241 data.address = g_strdup(info->address);
243 case HIDP_TRANS_HANDSHAKE:
244 BT_INFO("TRANS HANDSHAKE");
245 data.type = HTYPE_TRANS_HANDSHAKE;
246 data.buffer_size = len;
247 data.buffer = (char *) malloc(sizeof(char) * len);
248 memcpy(data.buffer, buffer, len);
250 case HIDP_TRANS_HID_CONTROL:
251 BT_INFO("HID CONTROL");
252 data.type = HTYPE_TRANS_HID_CONTROL;
253 data.buffer_size = len;
254 data.buffer = (char *) malloc(sizeof(char) * len);
255 memcpy(data.buffer, buffer, len);
257 case HIDP_TRANS_DATA:
258 BT_INFO("TRANS DATA");
259 data.type = HTYPE_TRANS_DATA;
260 if ( param & HIDP_DATA_RTYPE_INPUT) {
261 BT_INFO("Input Report");
262 data.param = PTYPE_DATA_RTYPE_INPUT;
263 data.buffer_size = len;
264 data.buffer = (char *) malloc(sizeof(char) * len);
265 memcpy(data.buffer, buffer, len);
268 BT_INFO("Out Report");
269 data.param = PTYPE_DATA_RTYPE_OUTPUT;
270 data.buffer_size = len;
271 data.buffer = (char *) malloc(sizeof(char) * len);
272 memcpy(data.buffer, buffer, len);
275 case HIDP_TRANS_GET_REPORT: {
276 BT_INFO("Get Report");
277 data.type = HTYPE_TRANS_GET_REPORT;
278 if (param & HIDP_DATA_RTYPE_INPUT) {
279 BT_INFO("Input Report");
280 data.param = PTYPE_DATA_RTYPE_INPUT;
282 BT_INFO("Output Report");
283 data.param = PTYPE_DATA_RTYPE_OUTPUT;
285 data.buffer_size = len;
286 data.buffer = (char *) malloc(sizeof(char) * len);
287 memcpy(data.buffer, buffer, len);
290 case HIDP_TRANS_SET_REPORT: {
291 BT_INFO("Set Report");
292 data.type = HTYPE_TRANS_SET_REPORT;
293 if (param & HIDP_DATA_RTYPE_INPUT) {
294 BT_INFO("Input Report");
295 data.param = PTYPE_DATA_RTYPE_INPUT;
297 BT_INFO("Output Report");
298 data.param = PTYPE_DATA_RTYPE_OUTPUT;
300 data.buffer_size = len;
301 data.buffer = (char *) malloc(sizeof(char) * len);
302 memcpy(data.buffer, buffer, len);
305 case HIDP_TRANS_GET_PROTOCOL:{
306 BT_INFO("Get_PROTOCOL");
307 data.type = HTYPE_TRANS_GET_PROTOCOL;
308 data.param = PTYPE_DATA_RTYPE_INPUT;
309 data.buffer_size = len;
310 data.buffer = (char *) malloc(sizeof(char) * len);
311 memcpy(data.buffer, buffer, len);
314 case HIDP_TRANS_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);
320 memcpy(data.buffer, buffer, len);
324 BT_INFO("unsupported HIDP control message");
325 BT_ERR("Send Handshake Message");
326 guint8 type = HIDP_TRANS_HANDSHAKE |
327 HIDP_HSHK_ERR_UNSUPPORTED_REQUEST;
328 data.type = HTYPE_TRANS_UNKNOWN;
329 int fd = g_io_channel_unix_get_fd(chan);
330 int bytes = write(fd, &type, sizeof(type));
331 BT_INFO("Bytes Written %d", bytes);
335 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
336 if (event_info == NULL)
339 _bt_common_event_cb(BLUETOOTH_HID_DEVICE_DATA_RECEIVED,
340 BLUETOOTH_ERROR_NONE, &data,
341 event_info->cb, event_info->user_data);
345 g_free((char *)data.address);
347 BT_INFO("Error while reading data");
352 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
354 hid_info_t *info = NULL;
355 hid_connected_device_info_t *dev_info = NULL;
356 bt_event_info_t *event_info = NULL;
362 _bt_convert_addr_type_to_string((char *)address, addr->addr);
363 BT_INFO("Address [%s]", address);
364 dev_info = __find_hid_info_with_address(address);
365 if (dev_info == NULL) {
366 dev_info = (hid_connected_device_info_t *)
367 g_malloc0(sizeof(hid_connected_device_info_t));
368 dev_info->intr_fd = -1;
369 dev_info->ctrl_fd = -1;
370 dev_info->intr_fd = fd;
371 dev_info->address = g_strdup(address);
372 dev_info->intr_data_io = g_io_channel_unix_new(dev_info->intr_fd);
373 g_io_channel_set_encoding(dev_info->intr_data_io, NULL, NULL);
374 g_io_channel_set_flags(dev_info->intr_data_io, G_IO_FLAG_NONBLOCK, NULL);
376 dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
377 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
378 __received_cb, dev_info);
379 hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
381 dev_info->ctrl_fd = fd;
382 dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
383 g_io_channel_set_encoding(dev_info->ctrl_data_io, NULL, NULL);
384 g_io_channel_set_flags(dev_info->ctrl_data_io, G_IO_FLAG_NONBLOCK, NULL);
386 dev_info->ctrl_data_id = g_io_add_watch(dev_info->ctrl_data_io,
387 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
388 __received_cb, dev_info);
390 if (dev_info->ctrl_fd != -1 && dev_info->intr_fd != -1) {
391 event_info = _bt_event_get_cb_data(BT_HID_DEVICE_EVENT);
393 __hid_connected_cb(dev_info, event_info);
398 static hid_info_t *__register_method()
401 hid_info_t *info = NULL;
403 path = g_strdup_printf("/org/socket/server/%d", getpid());
405 object_id = _bt_register_new_conn(path, new_hid_connection);
409 info = g_new(hid_info_t, 1);
410 info->object_id = (guint)object_id;
413 info->device_list = NULL;
418 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
422 /* Register HID Device events */
423 BT_INFO("BT_HID_DEVICE_EVENT");
424 ret = _bt_register_event(BT_HID_DEVICE_EVENT , (void *)callback_ptr, user_data);
426 if (ret != BLUETOOTH_ERROR_NONE &&
427 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
428 BT_ERR("Fail to init the event handler");
432 _bt_set_user_data(BT_HID, (void *)callback_ptr, user_data);
434 return BLUETOOTH_ERROR_NONE;
437 BT_EXPORT_API int bluetooth_hid_device_deinit(void)
441 ret = _bt_unregister_event(BT_HID_DEVICE_EVENT);
443 if (ret != BLUETOOTH_ERROR_NONE) {
444 BT_ERR("Fail to deinit the event handler");
448 _bt_set_user_data(BT_HID, NULL, NULL);
450 return BLUETOOTH_ERROR_NONE;
453 BT_EXPORT_API int bluetooth_hid_device_activate(void)
455 bt_register_profile_info_t profile_info;
456 int result = BLUETOOTH_ERROR_NONE;
458 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
459 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
460 BT_ERR("Don't have a privilege to use this API");
461 return BLUETOOTH_ERROR_PERMISSION_DEINED;
464 if (hid_info != NULL)
465 return BLUETOOTH_ERROR_IN_PROGRESS;
467 hid_info = __register_method();
468 if (hid_info == NULL)
469 return BLUETOOTH_ERROR_INTERNAL;
471 hid_info->uuid = g_strdup(HID_UUID);
473 profile_info.authentication = TRUE;
474 profile_info.authorization = TRUE;
475 profile_info.obj_path = hid_info->path;
476 profile_info.role = g_strdup("Hid");
477 profile_info.service = hid_info->uuid;
478 profile_info.uuid = hid_info->uuid;
480 BT_INFO("uuid %s", profile_info.uuid);
481 result = _bt_register_profile_platform(&profile_info, FALSE);
486 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
488 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
489 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
490 BT_ERR("Don't have a privilege to use this API");
491 return BLUETOOTH_ERROR_PERMISSION_DEINED;
494 if (hid_info == NULL)
495 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
497 _bt_unregister_profile(hid_info->path);
499 __free_hid_info(hid_info);
501 return BLUETOOTH_ERROR_NONE;
504 BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
506 char device_address[BT_ADDRESS_STRING_SIZE] = {0};
507 hid_connected_device_info_t *info = NULL;
509 BT_CHECK_PARAMETER(remote_addr, return);
511 info = __find_hid_info_with_address(remote_addr);
513 BT_ERR("Connection Already Exists");
514 return BLUETOOTH_ERROR_ALREADY_CONNECT;
516 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_CONNECT)
517 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
518 BT_ERR("Don't have a privilege to use this API");
519 return BLUETOOTH_ERROR_PERMISSION_DEINED;
522 memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
523 _bt_connect_profile(device_address, HID_UUID, NULL, NULL);
525 return BLUETOOTH_ERROR_NONE;
527 BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
529 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
530 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
531 BT_ERR("Don't have a privilege to use this API");
532 return BLUETOOTH_ERROR_PERMISSION_DEINED;
534 hid_connected_device_info_t *info = NULL;
536 info = __find_hid_info_with_address(remote_addr);
538 return BLUETOOTH_ERROR_INVALID_PARAM;
540 _bt_disconnect_profile((char *)remote_addr, HID_UUID, NULL, NULL);
542 info->disconnect_idle_id = g_idle_add((GSourceFunc)__hid_disconnect, info);
545 return BLUETOOTH_ERROR_NONE;
547 BT_EXPORT_API int bluetooth_hid_device_send_mouse_event(const char *remote_addr,
548 hid_send_mouse_event_t send_event)
552 hid_connected_device_info_t *info = NULL;
554 switch (privilege_token_send_mouse) {
556 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_MOUSE_EVENT);
558 if (result == BLUETOOTH_ERROR_NONE) {
559 privilege_token_send_mouse = 1; /* Have a permission */
560 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
561 BT_ERR("Don't have a privilege to use this API");
562 privilege_token_send_mouse = -1; /* Don't have a permission */
563 return BLUETOOTH_ERROR_PERMISSION_DEINED;
565 /* Just break - It is not related with permission error */
569 /* Already have a privilege */
572 return BLUETOOTH_ERROR_PERMISSION_DEINED;
574 /* Invalid privilge token value */
575 return BLUETOOTH_ERROR_INTERNAL;
577 info = __find_hid_info_with_address(remote_addr);
579 BT_ERR("Connection Information not found");
580 return BLUETOOTH_ERROR_INVALID_PARAM;
587 if (info->intr_fd != -1 && info->ctrl_fd == -1)
588 socket_fd = info->intr_fd;
590 socket_fd = info->ctrl_fd;
592 written = write(socket_fd, &send_event, sizeof(send_event));
597 BT_EXPORT_API int bluetooth_hid_device_send_key_event(const char *remote_addr,
598 hid_send_key_event_t send_event)
602 hid_connected_device_info_t *info = NULL;
604 switch (privilege_token_send_key) {
606 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_KEY_EVENT);
608 if (result == BLUETOOTH_ERROR_NONE) {
609 privilege_token_send_key = 1; /* Have a permission */
610 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
611 BT_ERR("Don't have a privilege to use this API");
612 privilege_token_send_key = -1; /* Don't have a permission */
613 return BLUETOOTH_ERROR_PERMISSION_DEINED;
615 /* Just break - It is not related with permission error */
619 /* Already have a privilege */
622 return BLUETOOTH_ERROR_PERMISSION_DEINED;
624 /* Invalid privilge token value */
625 return BLUETOOTH_ERROR_INTERNAL;
628 info = __find_hid_info_with_address(remote_addr);
630 BT_ERR("Connection Information not found");
631 return BLUETOOTH_ERROR_INVALID_PARAM;
639 if (info->intr_fd != -1 && info->ctrl_fd == -1)
640 socket_fd = info->intr_fd;
642 socket_fd = info->ctrl_fd;
644 written = write(socket_fd, &send_event, sizeof(send_event));
648 BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
649 bt_hid_header_type_t htype,
650 bt_hid_param_type_t ptype,
652 unsigned int data_len)
655 struct reports output_report = { 0 };
657 hid_connected_device_info_t *info = NULL;
658 info = __find_hid_info_with_address(remote_addr);
660 BT_ERR("Connection Information not found");
661 return BLUETOOTH_ERROR_INVALID_PARAM;
664 switch (privilege_token_reply) {
666 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HID_DEVICE_SEND_REPLY_TO_REPORT);
668 if (result == BLUETOOTH_ERROR_NONE) {
669 privilege_token_reply = 1; /* Have a permission */
670 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
671 BT_ERR("Don't have a privilege to use this API");
672 privilege_token_reply = -1; /* Don't have a permission */
673 return BLUETOOTH_ERROR_PERMISSION_DEINED;
675 /* Just break - It is not related with permission error */
679 /* Already have a privilege */
682 return BLUETOOTH_ERROR_PERMISSION_DEINED;
684 /* Invalid privilge token value */
685 return BLUETOOTH_ERROR_INTERNAL;
688 BT_INFO("htype %d ptype %d", htype, ptype);
690 case HTYPE_TRANS_GET_REPORT: {
692 case PTYPE_DATA_RTYPE_INPUT: {
693 output_report.type = HIDP_TRANS_DATA |
694 HIDP_DATA_RTYPE_INPUT;
695 memcpy(output_report.rep_data, data, data_len);
696 bytes = write(info->intr_fd, &output_report,
697 sizeof(output_report));
698 BT_DBG("Bytes Written %d", bytes);
702 BT_INFO("Not Supported");
706 case HTYPE_TRANS_GET_PROTOCOL: {
707 BT_DBG("Replying to Get_PROTOCOL");
708 output_report.type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUTPUT;
709 output_report.rep_data[0] = data[0];
710 bytes = write(info->intr_fd, &output_report, 2);
711 BT_DBG("Bytes Written %d", bytes);
714 case HTYPE_TRANS_SET_PROTOCOL: {
715 BT_DBG("Reply to Set_Protocol");
716 output_report.type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT;
717 memcpy(output_report.rep_data, data, data_len);
718 bytes = write(info->ctrl_fd, &output_report,
719 sizeof(output_report));
720 BT_DBG("Bytes Written %d", bytes);
723 case HTYPE_TRANS_HANDSHAKE: {
724 BT_DBG("Replying Handshake");
725 output_report.type = HIDP_TRANS_HANDSHAKE | data[0];
726 memset(output_report.rep_data, 0, sizeof(output_report.rep_data));
727 bytes = write(info->intr_fd, &output_report.type,
728 sizeof(output_report.type));
729 BT_DBG("Bytes Written %d", bytes);