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