1 /******************************************************************************
2 *
3 * Copyright (C) 2016 The Android Open Source Project
4 * Copyright (C) 2009-2012 Broadcom Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 /************************************************************************************
21 *
22 * Filename: btif_hd.c
23 *
24 * Description: HID Device Profile Bluetooth Interface
25 *
26 *
27 ***********************************************************************************/
28 #include <errno.h>
29 #include <hardware/bluetooth.h>
30 #include <hardware/bt_hd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #define LOG_TAG "BTIF_HD"
36
37 #include "bta_api.h"
38 #include "bta_hd_api.h"
39 #include "bta_hh_api.h"
40
41 #include "btif_common.h"
42 #include "btif_hd.h"
43 #include "btif_storage.h"
44 #include "btif_util.h"
45
46 #define BTIF_HD_APP_NAME_LEN 50
47 #define BTIF_HD_APP_DESCRIPTION_LEN 50
48 #define BTIF_HD_APP_PROVIDER_LEN 50
49 #define BTIF_HD_APP_DESCRIPTOR_LEN 2048
50
51 #define COD_HID_KEYBOARD 0x0540
52 #define COD_HID_POINTING 0x0580
53 #define COD_HID_COMBO 0x05C0
54 #define COD_HID_MAJOR 0x0500
55
56 extern bool bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr);
57 extern bool check_cod_hid(const bt_bdaddr_t* remote_bdaddr);
58 extern void btif_hh_service_registration(bool enable);
59
60 /* HD request events */
61 typedef enum { BTIF_HD_DUMMY_REQ_EVT = 0 } btif_hd_req_evt_t;
62
63 btif_hd_cb_t btif_hd_cb;
64
65 static bthd_callbacks_t* bt_hd_callbacks = NULL;
66 static tBTA_HD_APP_INFO app_info;
67 static tBTA_HD_QOS_INFO in_qos;
68 static tBTA_HD_QOS_INFO out_qos;
69
intr_data_copy_cb(uint16_t event,char * p_dst,char * p_src)70 static void intr_data_copy_cb(uint16_t event, char* p_dst, char* p_src) {
71 tBTA_HD_INTR_DATA* p_dst_data = (tBTA_HD_INTR_DATA*)p_dst;
72 tBTA_HD_INTR_DATA* p_src_data = (tBTA_HD_INTR_DATA*)p_src;
73 uint8_t* p_data;
74
75 if (!p_src) return;
76
77 if (event != BTA_HD_INTR_DATA_EVT) return;
78
79 memcpy(p_dst, p_src, sizeof(tBTA_HD_INTR_DATA));
80
81 p_data = ((uint8_t*)p_dst_data) + sizeof(tBTA_HD_INTR_DATA);
82
83 memcpy(p_data, p_src_data->p_data, p_src_data->len);
84
85 p_dst_data->p_data = p_data;
86 }
87
set_report_copy_cb(uint16_t event,char * p_dst,char * p_src)88 static void set_report_copy_cb(uint16_t event, char* p_dst, char* p_src) {
89 tBTA_HD_SET_REPORT* p_dst_data = (tBTA_HD_SET_REPORT*)p_dst;
90 tBTA_HD_SET_REPORT* p_src_data = (tBTA_HD_SET_REPORT*)p_src;
91 uint8_t* p_data;
92
93 if (!p_src) return;
94
95 if (event != BTA_HD_SET_REPORT_EVT) return;
96
97 memcpy(p_dst, p_src, sizeof(tBTA_HD_SET_REPORT));
98
99 p_data = ((uint8_t*)p_dst_data) + sizeof(tBTA_HD_SET_REPORT);
100
101 memcpy(p_data, p_src_data->p_data, p_src_data->len);
102
103 p_dst_data->p_data = p_data;
104 }
105
btif_hd_free_buf()106 static void btif_hd_free_buf() {
107 if (app_info.descriptor.dsc_list) osi_free(app_info.descriptor.dsc_list);
108 if (app_info.p_description) osi_free(app_info.p_description);
109 if (app_info.p_name) osi_free(app_info.p_name);
110 if (app_info.p_provider) osi_free(app_info.p_provider);
111 app_info.descriptor.dsc_list = NULL;
112 app_info.p_description = NULL;
113 app_info.p_name = NULL;
114 app_info.p_provider = NULL;
115 }
116
117 /*******************************************************************************
118 *
119 * Function btif_hd_remove_device
120 *
121 * Description Removes plugged device
122 *
123 * Returns void
124 *
125 ******************************************************************************/
btif_hd_remove_device(bt_bdaddr_t bd_addr)126 void btif_hd_remove_device(bt_bdaddr_t bd_addr) {
127 BTA_HdRemoveDevice((uint8_t*)&bd_addr);
128 btif_storage_remove_hidd(&bd_addr);
129 }
130
131 /*******************************************************************************
132 *
133 * Function btif_hd_upstreams_evt
134 *
135 * Description Executes events in btif context
136 *
137 * Returns void
138 *
139 ******************************************************************************/
btif_hd_upstreams_evt(uint16_t event,char * p_param)140 static void btif_hd_upstreams_evt(uint16_t event, char* p_param) {
141 tBTA_HD* p_data = (tBTA_HD*)p_param;
142
143 BTIF_TRACE_API("%s: event=%s", __func__, dump_hd_event(event));
144
145 switch (event) {
146 case BTA_HD_ENABLE_EVT:
147 BTIF_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
148 if (p_data->status == BTA_HD_OK) {
149 btif_storage_load_hidd();
150 btif_hd_cb.status = BTIF_HD_ENABLED;
151 /* Register the app if not yet registered */
152 if (!btif_hd_cb.app_registered) {
153 BTA_HdRegisterApp(&app_info, &in_qos, &out_qos);
154 btif_hd_free_buf();
155 }
156 } else {
157 btif_hd_cb.status = BTIF_HD_DISABLED;
158 BTIF_TRACE_WARNING("Failed to enable BT-HD, status=%d", p_data->status);
159 }
160 break;
161
162 case BTA_HD_DISABLE_EVT:
163 BTIF_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
164 btif_hd_cb.status = BTIF_HD_DISABLED;
165 if (btif_hd_cb.service_dereg_active) {
166 BTIF_TRACE_WARNING("registering hid host now");
167 btif_hh_service_registration(TRUE);
168 btif_hd_cb.service_dereg_active = FALSE;
169 }
170 btif_hd_free_buf();
171 if (p_data->status == BTA_HD_OK)
172 memset(&btif_hd_cb, 0, sizeof(btif_hd_cb));
173 else
174 BTIF_TRACE_WARNING("Failed to disable BT-HD, status=%d",
175 p_data->status);
176 break;
177
178 case BTA_HD_REGISTER_APP_EVT: {
179 bt_bdaddr_t* addr = (bt_bdaddr_t*)&p_data->reg_status.bda;
180
181 if (!p_data->reg_status.in_use) {
182 addr = NULL;
183 }
184
185 btif_hd_cb.app_registered = TRUE;
186 HAL_CBACK(bt_hd_callbacks, application_state_cb, addr,
187 BTHD_APP_STATE_REGISTERED);
188 } break;
189
190 case BTA_HD_UNREGISTER_APP_EVT:
191 btif_hd_cb.app_registered = FALSE;
192 HAL_CBACK(bt_hd_callbacks, application_state_cb, NULL,
193 BTHD_APP_STATE_NOT_REGISTERED);
194 if (btif_hd_cb.service_dereg_active) {
195 BTIF_TRACE_WARNING("disabling hid device service now");
196 btif_hd_free_buf();
197 BTA_HdDisable();
198 }
199 break;
200
201 case BTA_HD_OPEN_EVT: {
202 bt_bdaddr_t* addr = (bt_bdaddr_t*)&p_data->conn.bda;
203 BTIF_TRACE_WARNING(
204 "BTA_HD_OPEN_EVT, address (%02x:%02x:%02x:%02x:%02x:%02x)",
205 addr->address[0], addr->address[1], addr->address[2],
206 addr->address[3], addr->address[4], addr->address[5]);
207 /* Check if the connection is from hid host and not hid device */
208 if (check_cod_hid(addr)) {
209 /* Incoming connection from hid device, reject it */
210 BTIF_TRACE_WARNING("remote device is not hid host, disconnecting");
211 btif_hd_cb.forced_disc = TRUE;
212 BTA_HdDisconnect();
213 break;
214 }
215 btif_storage_set_hidd((bt_bdaddr_t*)&p_data->conn.bda);
216
217 HAL_CBACK(bt_hd_callbacks, connection_state_cb,
218 (bt_bdaddr_t*)&p_data->conn.bda, BTHD_CONN_STATE_CONNECTED);
219 } break;
220
221 case BTA_HD_CLOSE_EVT:
222 if (btif_hd_cb.forced_disc) {
223 bt_bdaddr_t* addr = (bt_bdaddr_t*)&p_data->conn.bda;
224 BTIF_TRACE_WARNING("remote device was forcefully disconnected");
225 btif_hd_remove_device(*addr);
226 btif_hd_cb.forced_disc = FALSE;
227 break;
228 }
229 HAL_CBACK(bt_hd_callbacks, connection_state_cb,
230 (bt_bdaddr_t*)&p_data->conn.bda, BTHD_CONN_STATE_DISCONNECTED);
231 break;
232
233 case BTA_HD_GET_REPORT_EVT:
234 HAL_CBACK(bt_hd_callbacks, get_report_cb, p_data->get_report.report_type,
235 p_data->get_report.report_id, p_data->get_report.buffer_size);
236 break;
237
238 case BTA_HD_SET_REPORT_EVT:
239 HAL_CBACK(bt_hd_callbacks, set_report_cb, p_data->set_report.report_type,
240 p_data->set_report.report_id, p_data->set_report.len,
241 p_data->set_report.p_data);
242 break;
243
244 case BTA_HD_SET_PROTOCOL_EVT:
245 HAL_CBACK(bt_hd_callbacks, set_protocol_cb, p_data->set_protocol);
246 break;
247
248 case BTA_HD_INTR_DATA_EVT:
249 HAL_CBACK(bt_hd_callbacks, intr_data_cb, p_data->intr_data.report_id,
250 p_data->intr_data.len, p_data->intr_data.p_data);
251 break;
252
253 case BTA_HD_VC_UNPLUG_EVT:
254 HAL_CBACK(bt_hd_callbacks, connection_state_cb,
255 (bt_bdaddr_t*)&p_data->conn.bda, BTHD_CONN_STATE_DISCONNECTED);
256 if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) {
257 BTIF_TRACE_DEBUG("%s: Removing bonding as only HID profile connected",
258 __func__);
259 BTA_DmRemoveDevice((uint8_t*)&p_data->conn.bda);
260 } else {
261 bt_bdaddr_t* bd_addr = (bt_bdaddr_t*)&p_data->conn.bda;
262 BTIF_TRACE_DEBUG(
263 "%s: Only removing HID data as some other profiles "
264 "connected",
265 __func__);
266 btif_hd_remove_device(*bd_addr);
267 }
268 HAL_CBACK(bt_hd_callbacks, vc_unplug_cb);
269 break;
270
271 case BTA_HD_CONN_STATE_EVT:
272 HAL_CBACK(bt_hd_callbacks, connection_state_cb,
273 (bt_bdaddr_t*)&p_data->conn.bda,
274 (bthd_connection_state_t)p_data->conn.status);
275 break;
276
277 default:
278 BTIF_TRACE_WARNING("%s: unknown event (%d)", __func__, event);
279 break;
280 }
281 }
282
283 /*******************************************************************************
284 *
285 * Function bte_hd_evt
286 *
287 * Description Switches context from BTE to BTIF for all BT-HD events
288 *
289 * Returns void
290 *
291 ******************************************************************************/
292
bte_hd_evt(tBTA_HD_EVT event,tBTA_HD * p_data)293 static void bte_hd_evt(tBTA_HD_EVT event, tBTA_HD* p_data) {
294 bt_status_t status;
295 int param_len = 0;
296 tBTIF_COPY_CBACK* p_copy_cback = NULL;
297
298 BTIF_TRACE_API("%s event=%d", __func__, event);
299
300 switch (event) {
301 case BTA_HD_ENABLE_EVT:
302 case BTA_HD_DISABLE_EVT:
303 case BTA_HD_UNREGISTER_APP_EVT:
304 param_len = sizeof(tBTA_HD_STATUS);
305 break;
306
307 case BTA_HD_REGISTER_APP_EVT:
308 param_len = sizeof(tBTA_HD_REG_STATUS);
309 break;
310
311 case BTA_HD_OPEN_EVT:
312 case BTA_HD_CLOSE_EVT:
313 case BTA_HD_VC_UNPLUG_EVT:
314 case BTA_HD_CONN_STATE_EVT:
315 param_len = sizeof(tBTA_HD_CONN);
316 break;
317
318 case BTA_HD_GET_REPORT_EVT:
319 param_len += sizeof(tBTA_HD_GET_REPORT);
320 break;
321
322 case BTA_HD_SET_REPORT_EVT:
323 param_len = sizeof(tBTA_HD_SET_REPORT) + p_data->set_report.len;
324 p_copy_cback = set_report_copy_cb;
325 break;
326
327 case BTA_HD_SET_PROTOCOL_EVT:
328 param_len += sizeof(p_data->set_protocol);
329 break;
330
331 case BTA_HD_INTR_DATA_EVT:
332 param_len = sizeof(tBTA_HD_INTR_DATA) + p_data->intr_data.len;
333 p_copy_cback = intr_data_copy_cb;
334 break;
335 }
336
337 status = btif_transfer_context(btif_hd_upstreams_evt, (uint16_t)event,
338 (char*)p_data, param_len, p_copy_cback);
339
340 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
341 }
342
343 /*******************************************************************************
344 *
345 * Function init
346 *
347 * Description Initializes BT-HD interface
348 *
349 * Returns BT_STATUS_SUCCESS
350 *
351 ******************************************************************************/
init(bthd_callbacks_t * callbacks)352 static bt_status_t init(bthd_callbacks_t* callbacks) {
353 BTIF_TRACE_API("%s", __func__);
354
355 bt_hd_callbacks = callbacks;
356 memset(&btif_hd_cb, 0, sizeof(btif_hd_cb));
357
358 btif_enable_service(BTA_HIDD_SERVICE_ID);
359
360 return BT_STATUS_SUCCESS;
361 }
362
363 /*******************************************************************************
364 *
365 * Function cleanup
366 *
367 * Description Cleans up BT-HD interface
368 *
369 * Returns none
370 *
371 ******************************************************************************/
cleanup(void)372 static void cleanup(void) {
373 BTIF_TRACE_API("hd:%s", __func__);
374
375 if (bt_hd_callbacks) {
376 /* update flag, not to enable hid host service now as BT is switching off */
377 btif_hd_cb.service_dereg_active = FALSE;
378 btif_disable_service(BTA_HIDD_SERVICE_ID);
379 bt_hd_callbacks = NULL;
380 }
381 }
382
383 /*******************************************************************************
384 *
385 * Function register_app
386 *
387 * Description Registers HID Device application
388 *
389 * Returns bt_status_t
390 *
391 ******************************************************************************/
register_app(bthd_app_param_t * p_app_param,bthd_qos_param_t * p_in_qos,bthd_qos_param_t * p_out_qos)392 static bt_status_t register_app(bthd_app_param_t* p_app_param,
393 bthd_qos_param_t* p_in_qos,
394 bthd_qos_param_t* p_out_qos) {
395 BTIF_TRACE_API("%s", __func__);
396
397 if (btif_hd_cb.app_registered) {
398 BTIF_TRACE_WARNING("%s: application already registered", __func__);
399 return BT_STATUS_BUSY;
400 }
401
402 app_info.p_name = (char*)osi_malloc(BTIF_HD_APP_NAME_LEN);
403 memcpy(app_info.p_name, p_app_param->name, BTIF_HD_APP_NAME_LEN);
404 app_info.p_description = (char*)osi_malloc(BTIF_HD_APP_DESCRIPTION_LEN);
405 memcpy(app_info.p_description, p_app_param->description,
406 BTIF_HD_APP_DESCRIPTION_LEN);
407 app_info.p_provider = (char*)osi_malloc(BTIF_HD_APP_PROVIDER_LEN);
408 memcpy(app_info.p_provider, p_app_param->provider, BTIF_HD_APP_PROVIDER_LEN);
409 app_info.subclass = p_app_param->subclass;
410 app_info.descriptor.dl_len = p_app_param->desc_list_len;
411 app_info.descriptor.dsc_list =
412 (uint8_t*)osi_malloc(app_info.descriptor.dl_len);
413 memcpy(app_info.descriptor.dsc_list, p_app_param->desc_list,
414 p_app_param->desc_list_len);
415
416 in_qos.service_type = p_in_qos->service_type;
417 in_qos.token_rate = p_in_qos->token_rate;
418 in_qos.token_bucket_size = p_in_qos->token_bucket_size;
419 in_qos.peak_bandwidth = p_in_qos->peak_bandwidth;
420 in_qos.access_latency = p_in_qos->access_latency;
421 in_qos.delay_variation = p_in_qos->delay_variation;
422
423 out_qos.service_type = p_out_qos->service_type;
424 out_qos.token_rate = p_out_qos->token_rate;
425 out_qos.token_bucket_size = p_out_qos->token_bucket_size;
426 out_qos.peak_bandwidth = p_out_qos->peak_bandwidth;
427 out_qos.access_latency = p_out_qos->access_latency;
428 out_qos.delay_variation = p_out_qos->delay_variation;
429
430 /* register HID Device with L2CAP and unregister HID Host with L2CAP */
431 /* Disable HH */
432 btif_hh_service_registration(FALSE);
433
434 return BT_STATUS_SUCCESS;
435 }
436
437 /*******************************************************************************
438 *
439 * Function unregister_app
440 *
441 * Description Unregisters HID Device application
442 *
443 * Returns bt_status_t
444 *
445 ******************************************************************************/
unregister_app(void)446 static bt_status_t unregister_app(void) {
447 BTIF_TRACE_API("%s", __func__);
448
449 if (!btif_hd_cb.app_registered) {
450 BTIF_TRACE_WARNING("%s: application not yet registered", __func__);
451 return BT_STATUS_NOT_READY;
452 }
453
454 if (btif_hd_cb.status != BTIF_HD_ENABLED) {
455 BTIF_TRACE_WARNING("%s: BT-HD not enabled, status=%d", __func__,
456 btif_hd_cb.status);
457 return BT_STATUS_NOT_READY;
458 }
459
460 if (btif_hd_cb.service_dereg_active) {
461 BTIF_TRACE_WARNING("%s: BT-HD deregistering in progress", __func__);
462 return BT_STATUS_BUSY;
463 }
464
465 btif_hd_cb.service_dereg_active = TRUE;
466 BTA_HdUnregisterApp();
467
468 return BT_STATUS_SUCCESS;
469 }
470
471 /*******************************************************************************
472 *
473 * Function connect
474 *
475 * Description Connects to host
476 *
477 * Returns bt_status_t
478 *
479 ******************************************************************************/
connect(bt_bdaddr_t * bd_addr)480 static bt_status_t connect(bt_bdaddr_t* bd_addr) {
481 BTIF_TRACE_API("%s", __func__);
482
483 if (!btif_hd_cb.app_registered) {
484 BTIF_TRACE_WARNING("%s: application not yet registered", __func__);
485 return BT_STATUS_NOT_READY;
486 }
487
488 if (btif_hd_cb.status != BTIF_HD_ENABLED) {
489 BTIF_TRACE_WARNING("%s: BT-HD not enabled, status=%d", __func__,
490 btif_hd_cb.status);
491 return BT_STATUS_NOT_READY;
492 }
493
494 BTA_HdConnect(bd_addr->address);
495
496 return BT_STATUS_SUCCESS;
497 }
498
499 /*******************************************************************************
500 *
501 * Function disconnect
502 *
503 * Description Disconnects from host
504 *
505 * Returns bt_status_t
506 *
507 ******************************************************************************/
disconnect(void)508 static bt_status_t disconnect(void) {
509 BTIF_TRACE_API("%s", __func__);
510
511 if (!btif_hd_cb.app_registered) {
512 BTIF_TRACE_WARNING("%s: application not yet registered", __func__);
513 return BT_STATUS_NOT_READY;
514 }
515
516 if (btif_hd_cb.status != BTIF_HD_ENABLED) {
517 BTIF_TRACE_WARNING("%s: BT-HD not enabled, status=%d", __func__,
518 btif_hd_cb.status);
519 return BT_STATUS_NOT_READY;
520 }
521
522 BTA_HdDisconnect();
523
524 return BT_STATUS_SUCCESS;
525 }
526
527 /*******************************************************************************
528 *
529 * Function send_report
530 *
531 * Description Sends Reports to hid host
532 *
533 * Returns bt_status_t
534 *
535 ******************************************************************************/
send_report(bthd_report_type_t type,uint8_t id,uint16_t len,uint8_t * p_data)536 static bt_status_t send_report(bthd_report_type_t type, uint8_t id,
537 uint16_t len, uint8_t* p_data) {
538 tBTA_HD_REPORT report;
539
540 APPL_TRACE_VERBOSE("%s: type=%d id=%d len=%d", __func__, type, id, len);
541
542 if (!btif_hd_cb.app_registered) {
543 BTIF_TRACE_WARNING("%s: application not yet registered", __func__);
544 return BT_STATUS_NOT_READY;
545 }
546
547 if (btif_hd_cb.status != BTIF_HD_ENABLED) {
548 BTIF_TRACE_WARNING("%s: BT-HD not enabled, status=%d", __func__,
549 btif_hd_cb.status);
550 return BT_STATUS_NOT_READY;
551 }
552
553 if (type == BTHD_REPORT_TYPE_INTRDATA) {
554 report.type = BTHD_REPORT_TYPE_INPUT;
555 report.use_intr = TRUE;
556 } else {
557 report.type = (type & 0x03);
558 report.use_intr = FALSE;
559 }
560
561 report.id = id;
562 report.len = len;
563 report.p_data = p_data;
564
565 BTA_HdSendReport(&report);
566
567 return BT_STATUS_SUCCESS;
568 }
569
570 /*******************************************************************************
571 *
572 * Function report_error
573 *
574 * Description Sends HANDSHAKE with error info for invalid SET_REPORT
575 *
576 * Returns bt_status_t
577 *
578 ******************************************************************************/
report_error(uint8_t error)579 static bt_status_t report_error(uint8_t error) {
580 BTIF_TRACE_API("%s", __func__);
581
582 if (!btif_hd_cb.app_registered) {
583 BTIF_TRACE_WARNING("%s: application not yet registered", __func__);
584 return BT_STATUS_NOT_READY;
585 }
586
587 if (btif_hd_cb.status != BTIF_HD_ENABLED) {
588 BTIF_TRACE_WARNING("%s: BT-HD not enabled, status=%d", __func__,
589 btif_hd_cb.status);
590 return BT_STATUS_NOT_READY;
591 }
592
593 BTA_HdReportError(error);
594
595 return BT_STATUS_SUCCESS;
596 }
597
598 /*******************************************************************************
599 *
600 * Function virtual_cable_unplug
601 *
602 * Description Sends Virtual Cable Unplug to host
603 *
604 * Returns bt_status_t
605 *
606 ******************************************************************************/
virtual_cable_unplug(void)607 static bt_status_t virtual_cable_unplug(void) {
608 BTIF_TRACE_API("%s", __func__);
609
610 if (!btif_hd_cb.app_registered) {
611 BTIF_TRACE_WARNING("%s: application not yet registered", __func__);
612 return BT_STATUS_NOT_READY;
613 }
614
615 if (btif_hd_cb.status != BTIF_HD_ENABLED) {
616 BTIF_TRACE_WARNING("%s: BT-HD not enabled, status=%d", __func__,
617 btif_hd_cb.status);
618 return BT_STATUS_NOT_READY;
619 }
620
621 BTA_HdVirtualCableUnplug();
622
623 return BT_STATUS_SUCCESS;
624 }
625
626 static const bthd_interface_t bthdInterface = {
627 sizeof(bthdInterface),
628 init,
629 cleanup,
630 register_app,
631 unregister_app,
632 connect,
633 disconnect,
634 send_report,
635 report_error,
636 virtual_cable_unplug,
637 };
638
639 /*******************************************************************************
640 *
641 * Function btif_hd_execute_service
642 *
643 * Description Enabled/disables BT-HD service
644 *
645 * Returns BT_STATUS_SUCCESS
646 *
647 ******************************************************************************/
btif_hd_execute_service(bool b_enable)648 bt_status_t btif_hd_execute_service(bool b_enable) {
649 BTIF_TRACE_API("%s: b_enable=%d", __func__, b_enable);
650
651 if (!b_enable) BTA_HdDisable();
652
653 return BT_STATUS_SUCCESS;
654 }
655
656 /*******************************************************************************
657 *
658 * Function btif_hd_get_interface
659 *
660 * Description Gets BT-HD interface
661 *
662 * Returns bthd_interface_t
663 *
664 ******************************************************************************/
btif_hd_get_interface()665 const bthd_interface_t* btif_hd_get_interface() {
666 BTIF_TRACE_API("%s", __func__);
667 return &bthdInterface;
668 }
669
670 /*******************************************************************************
671 *
672 * Function btif_hd_service_registration
673 *
674 * Description Registers hid device service
675 *
676 * Returns none
677 *
678 ******************************************************************************/
btif_hd_service_registration()679 void btif_hd_service_registration() {
680 BTIF_TRACE_API("%s", __func__);
681 /* enable HD */
682 if (bt_hd_callbacks != NULL) {
683 BTA_HdEnable(bte_hd_evt);
684 }
685 }
686