• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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