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