1 /******************************************************************************
2 *
3 * Copyright (c) 2014 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_hf_client.c
23 *
24 * Description: Handsfree Profile (HF role) Bluetooth Interface
25 *
26 * Notes:
27 * a) Lifecycle of a control block
28 * Control block handles the lifecycle for a particular remote device's
29 * connection. The connection can go via the classic phases but more
30 * importantly there's only two messages from BTA that affect this.
31 * BTA_HF_CLIENT_OPEN_EVT and BTA_HF_CLIENT_CLOSE_EVT. Since the API between
32 * BTIF and BTA is controlled entirely by handles it's important to know where
33 * the handles are created and destroyed. Handles can be created at two
34 * locations:
35 * -- While connect() is called from BTIF. This is an outgoing connection
36 * -- While accepting an incoming connection (see BTA_HF_CLIENT_OPEN_EVT
37 * handling).
38 *
39 * The destruction or rather reuse of handles can be done when
40 * BTA_HF_CLIENT_CLOSE_EVT is called. Refer to the event handling for details
41 * of this.
42 *
43 ******************************************************************************/
44
45 #ifndef LOG_TAG
46 #define LOG_TAG "bt_btif_hfc"
47 #endif
48
49 #include <hardware/bluetooth.h>
50 #include <hardware/bt_hf_client.h>
51 #include <string.h>
52
53 #include "bta_hf_client_api.h"
54 #include "btif_common.h"
55 #include "btif_profile_queue.h"
56 #include "btif_util.h"
57 #include "osi/include/osi.h"
58 #include "osi/include/properties.h"
59 #include "types/raw_address.h"
60
61 #include <base/logging.h>
62
63 /*******************************************************************************
64 * Constants & Macros
65 ******************************************************************************/
66
67 #ifndef BTIF_HF_CLIENT_SERVICE_NAME
68 #define BTIF_HF_CLIENT_SERVICE_NAME ("Handsfree")
69 #endif
70
71 /*******************************************************************************
72 * Local type definitions
73 ******************************************************************************/
74 /* BTIF-HF control block to map bdaddr to BTA handle */
75 typedef struct {
76 uint16_t handle; // Handle obtained frm the BTA
77 RawAddress peer_bda; // Device corresponding to handle
78 bthf_client_connection_state_t state; // State of current connection
79 tBTA_HF_CLIENT_PEER_FEAT peer_feat; // HF features
80 tBTA_HF_CLIENT_CHLD_FEAT chld_feat; // AT+CHLD=<> command features
81 } btif_hf_client_cb_t;
82
83 /* Max devices supported by BTIF (useful to match the value in BTA) */
84 #define HF_CLIENT_MAX_DEVICES 10
85 typedef struct {
86 btif_hf_client_cb_t cb[HF_CLIENT_MAX_DEVICES];
87 } btif_hf_client_cb_arr_t;
88
89 /******************************************************************************
90 * Local function declarations
91 ******************************************************************************/
92 btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle);
93 btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& addr);
94 bool is_connected(const btif_hf_client_cb_t* cb);
95
96 /*******************************************************************************
97 * Static variables
98 ******************************************************************************/
99 static bthf_client_callbacks_t* bt_hf_client_callbacks = NULL;
100
101 char btif_hf_client_version[PROPERTY_VALUE_MAX];
102
dump_hf_client_conn_state(uint16_t event)103 static const char* dump_hf_client_conn_state(uint16_t event) {
104 switch (event) {
105 CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED)
106 CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_CONNECTING)
107 CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_CONNECTED)
108 CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED)
109 CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING)
110 default:
111 return "UNKNOWN MSG ID";
112 }
113 }
114
115 #define CHECK_BTHF_CLIENT_INIT() \
116 do { \
117 if (bt_hf_client_callbacks == NULL) { \
118 BTIF_TRACE_WARNING("BTHF CLIENT: %s: not initialized", __func__); \
119 return BT_STATUS_NOT_READY; \
120 } else { \
121 BTIF_TRACE_EVENT("BTHF CLIENT: %s", __func__); \
122 } \
123 } while (0)
124
125 #define CHECK_BTHF_CLIENT_SLC_CONNECTED(cb) \
126 do { \
127 if (bt_hf_client_callbacks == NULL) { \
128 BTIF_TRACE_WARNING("BTHF CLIENT: %s: not initialized", __func__); \
129 return BT_STATUS_NOT_READY; \
130 } else if ((cb)->state != BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { \
131 BTIF_TRACE_WARNING("BTHF CLIENT: %s: SLC connection not up. state=%s", \
132 __func__, dump_hf_client_conn_state((cb)->state)); \
133 return BT_STATUS_NOT_READY; \
134 } else { \
135 BTIF_TRACE_EVENT("BTHF CLIENT: %s", __func__); \
136 } \
137 } while (0)
138
139 static btif_hf_client_cb_arr_t btif_hf_client_cb_arr;
140
141 /*******************************************************************************
142 * Static functions
143 ******************************************************************************/
144
145 /*******************************************************************************
146 *
147 * Function btif_in_hf_client_generic_evt
148 *
149 * Description Processes generic events to be sent to JNI that are not
150 * triggered from the BTA.
151 * Always runs in BTIF context
152 *
153 * Returns void
154 *
155 ******************************************************************************/
btif_in_hf_client_generic_evt(uint16_t event,char * p_param)156 static void btif_in_hf_client_generic_evt(uint16_t event, char* p_param) {
157 BTIF_TRACE_DEBUG("%s", __func__);
158 RawAddress* bd_addr = (RawAddress*)p_param;
159 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
160 if (cb == NULL || !is_connected(cb)) {
161 BTIF_TRACE_ERROR("%s: failed to find block for bda", __func__);
162 return;
163 }
164
165 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
166 switch (event) {
167 case BTIF_HF_CLIENT_CB_AUDIO_CONNECTING: {
168 HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
169 (bthf_client_audio_state_t)BTHF_CLIENT_AUDIO_STATE_CONNECTING);
170 } break;
171 default: {
172 BTIF_TRACE_WARNING("%s: : Unknown event 0x%x", __func__, event);
173 } break;
174 }
175 }
176
177 /*******************************************************************************
178 * Functions
179 ******************************************************************************/
is_connected(const btif_hf_client_cb_t * cb)180 bool is_connected(const btif_hf_client_cb_t* cb) {
181 if ((cb->state == BTHF_CLIENT_CONNECTION_STATE_CONNECTED) ||
182 (cb->state == BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED))
183 return true;
184
185 BTIF_TRACE_ERROR("%s: not connected!", __func__);
186 return false;
187 }
188
189 /*******************************************************************************
190 *
191 * Function btif_hf_client_get_cb_by_handle
192 *
193 * Description Get control block by handle
194 *
195 * Returns btif_hf_client_cb_t pointer if available NULL otherwise
196 *
197 ******************************************************************************/
btif_hf_client_get_cb_by_handle(uint16_t handle)198 btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle) {
199 BTIF_TRACE_DEBUG("%s: cb by handle %d", __func__, handle);
200 for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
201 // Block is valid only if it is allocated i.e. state is not DISCONNECTED
202 if (btif_hf_client_cb_arr.cb[i].state !=
203 BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED &&
204 btif_hf_client_cb_arr.cb[i].handle == handle) {
205 return &btif_hf_client_cb_arr.cb[i];
206 }
207 }
208 BTIF_TRACE_ERROR("%s: could not find block for handle %d", __func__, handle);
209 return NULL;
210 }
211
212 /*******************************************************************************
213 *
214 * Function btif_hf_client_get_cb_by_bda
215 *
216 * Description Get control block by bda
217 *
218 * Returns btif_hf_client_cb_t pointer if available NULL otherwise
219 *
220 ******************************************************************************/
btif_hf_client_get_cb_by_bda(const RawAddress & bd_addr)221 btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& bd_addr) {
222 VLOG(1) << __func__ << " incoming addr " << ADDRESS_TO_LOGGABLE_CSTR(bd_addr);
223
224 for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
225 // Block is valid only if it is allocated i.e. state is not DISCONNECTED
226 if (btif_hf_client_cb_arr.cb[i].state !=
227 BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED &&
228 btif_hf_client_cb_arr.cb[i].peer_bda == bd_addr) {
229 return &btif_hf_client_cb_arr.cb[i];
230 }
231 }
232 BTIF_TRACE_ERROR("%s: could not find block for bdaddr", __func__);
233 return NULL;
234 }
235
236 /*******************************************************************************
237 *
238 * Function btif_hf_client_allocate_cb
239 *
240 * Description Get control block by bda
241 *
242 * Returns btif_hf_client_cb_t pointer if available NULL otherwise
243 *
244 ******************************************************************************/
btif_hf_client_allocate_cb()245 btif_hf_client_cb_t* btif_hf_client_allocate_cb() {
246 for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
247 btif_hf_client_cb_t* cb = &btif_hf_client_cb_arr.cb[i];
248 if (cb->state == BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED) {
249 return cb;
250 }
251 }
252 BTIF_TRACE_ERROR("%s: unable to allocate control block", __func__);
253 return NULL;
254 }
255
256 /*****************************************************************************
257 *
258 * btif hf api functions (no context switch)
259 *
260 ****************************************************************************/
261
262 /*******************************************************************************
263 *
264 * Function btif_hf_client_init
265 *
266 * Description initializes the hf interface
267 *
268 * Returns bt_status_t
269 *
270 ******************************************************************************/
init(bthf_client_callbacks_t * callbacks)271 static bt_status_t init(bthf_client_callbacks_t* callbacks) {
272 BTIF_TRACE_EVENT("%s", __func__);
273
274 bt_hf_client_callbacks = callbacks;
275
276 btif_enable_service(BTA_HFP_HS_SERVICE_ID);
277
278 memset(&btif_hf_client_cb_arr, 0, sizeof(btif_hf_client_cb_arr_t));
279
280 return BT_STATUS_SUCCESS;
281 }
282
283 /*******************************************************************************
284 *
285 * Function connect
286 *
287 * Description connect to audio gateway
288 *
289 * Returns bt_status_t
290 *
291 ******************************************************************************/
connect_int(RawAddress * bd_addr,uint16_t uuid)292 static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) {
293 btif_hf_client_cb_t* cb = btif_hf_client_allocate_cb();
294 if (cb == NULL) {
295 BTIF_TRACE_ERROR("%s: could not allocate block!", __func__);
296 return BT_STATUS_BUSY;
297 }
298
299 cb->peer_bda = *bd_addr;
300 if (is_connected(cb)) return BT_STATUS_BUSY;
301
302 cb->state = BTHF_CLIENT_CONNECTION_STATE_CONNECTING;
303 cb->peer_bda = *bd_addr;
304
305 /* Open HF connection to remote device and get the relevant handle.
306 * The handle is valid until we have called BTA_HfClientClose or the LL
307 * has notified us of channel close due to remote closing, error etc.
308 */
309 return BTA_HfClientOpen(cb->peer_bda, &cb->handle);
310 }
311
connect(const RawAddress * bd_addr)312 static bt_status_t connect(const RawAddress* bd_addr) {
313 BTIF_TRACE_EVENT("HFP Client version is %s", btif_hf_client_version);
314 CHECK_BTHF_CLIENT_INIT();
315 return btif_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int);
316 }
317
318 /*******************************************************************************
319 *
320 * Function disconnect
321 *
322 * Description disconnect from audio gateway
323 *
324 * Returns bt_status_t
325 *
326 ******************************************************************************/
disconnect(const RawAddress * bd_addr)327 static bt_status_t disconnect(const RawAddress* bd_addr) {
328 CHECK_BTHF_CLIENT_INIT();
329
330 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
331 if (cb != NULL) {
332 BTA_HfClientClose(cb->handle);
333 return BT_STATUS_SUCCESS;
334 } else {
335 return BT_STATUS_BUSY;
336 }
337 }
338
339 /*******************************************************************************
340 *
341 * Function connect_audio
342 *
343 * Description create an audio connection
344 *
345 * Returns bt_status_t
346 *
347 ******************************************************************************/
connect_audio(const RawAddress * bd_addr)348 static bt_status_t connect_audio(const RawAddress* bd_addr) {
349 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
350 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
351
352 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
353
354 if ((get_default_hf_client_features() & BTA_HF_CLIENT_FEAT_CODEC) &&
355 (cb->peer_feat & BTA_HF_CLIENT_PEER_CODEC)) {
356 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BCC, 0, 0, NULL);
357 } else {
358 BTA_HfClientAudioOpen(cb->handle);
359 }
360
361 /* Inform the application that the audio connection has been initiated
362 * successfully */
363 btif_transfer_context(btif_in_hf_client_generic_evt,
364 BTIF_HF_CLIENT_CB_AUDIO_CONNECTING, (char*)bd_addr,
365 sizeof(RawAddress), NULL);
366 return BT_STATUS_SUCCESS;
367 }
368
369 /*******************************************************************************
370 *
371 * Function disconnect_audio
372 *
373 * Description close the audio connection
374 *
375 * Returns bt_status_t
376 *
377 ******************************************************************************/
disconnect_audio(const RawAddress * bd_addr)378 static bt_status_t disconnect_audio(const RawAddress* bd_addr) {
379 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
380 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
381
382 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
383
384 BTA_HfClientAudioClose(cb->handle);
385 return BT_STATUS_SUCCESS;
386 }
387
388 /*******************************************************************************
389 *
390 * Function start_voice_recognition
391 *
392 * Description start voice recognition
393 *
394 * Returns bt_status_t
395 *
396 ******************************************************************************/
start_voice_recognition(const RawAddress * bd_addr)397 static bt_status_t start_voice_recognition(const RawAddress* bd_addr) {
398 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
399 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
400
401 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
402
403 if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC) {
404 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BVRA, 1, 0, NULL);
405 return BT_STATUS_SUCCESS;
406 }
407 return BT_STATUS_UNSUPPORTED;
408 }
409
410 /*******************************************************************************
411 *
412 * Function stop_voice_recognition
413 *
414 * Description stop voice recognition
415 *
416 * Returns bt_status_t
417 *
418 ******************************************************************************/
stop_voice_recognition(const RawAddress * bd_addr)419 static bt_status_t stop_voice_recognition(const RawAddress* bd_addr) {
420 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
421 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
422
423 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
424
425 if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC) {
426 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BVRA, 0, 0, NULL);
427 return BT_STATUS_SUCCESS;
428 }
429 return BT_STATUS_UNSUPPORTED;
430 }
431
432 /*******************************************************************************
433 *
434 * Function volume_control
435 *
436 * Description volume control
437 *
438 * Returns bt_status_t
439 *
440 ******************************************************************************/
volume_control(const RawAddress * bd_addr,bthf_client_volume_type_t type,int volume)441 static bt_status_t volume_control(const RawAddress* bd_addr,
442 bthf_client_volume_type_t type, int volume) {
443 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
444 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
445
446 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
447
448 switch (type) {
449 case BTHF_CLIENT_VOLUME_TYPE_SPK:
450 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_VGS, volume, 0, NULL);
451 break;
452 case BTHF_CLIENT_VOLUME_TYPE_MIC:
453 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_VGM, volume, 0, NULL);
454 break;
455 default:
456 return BT_STATUS_UNSUPPORTED;
457 }
458
459 return BT_STATUS_SUCCESS;
460 }
461
462 /*******************************************************************************
463 *
464 * Function dial
465 *
466 * Description place a call
467 *
468 * Returns bt_status_t
469 *
470 ******************************************************************************/
dial(UNUSED_ATTR const RawAddress * bd_addr,const char * number)471 static bt_status_t dial(UNUSED_ATTR const RawAddress* bd_addr,
472 const char* number) {
473 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
474 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
475
476 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
477
478 if (number) {
479 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATD, 0, 0, number);
480 } else {
481 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BLDN, 0, 0, NULL);
482 }
483 return BT_STATUS_SUCCESS;
484 }
485
486 /*******************************************************************************
487 *
488 * Function dial_memory
489 *
490 * Description place a call with number specified by location (speed dial)
491 *
492 * Returns bt_status_t
493 *
494 ******************************************************************************/
dial_memory(const RawAddress * bd_addr,int location)495 static bt_status_t dial_memory(const RawAddress* bd_addr, int location) {
496 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
497 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
498
499 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
500
501 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATD, location, 0, NULL);
502 return BT_STATUS_SUCCESS;
503 }
504
505 /*******************************************************************************
506 *
507 * Function handle_call_action
508 *
509 * Description handle specified call related action
510 *
511 * Returns bt_status_t
512 *
513 ******************************************************************************/
handle_call_action(const RawAddress * bd_addr,bthf_client_call_action_t action,int idx)514 static bt_status_t handle_call_action(const RawAddress* bd_addr,
515 bthf_client_call_action_t action,
516 int idx) {
517 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
518 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
519
520 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
521
522 switch (action) {
523 case BTHF_CLIENT_CALL_ACTION_CHLD_0:
524 if (cb->chld_feat & BTA_HF_CLIENT_CHLD_REL) {
525 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 0, 0, NULL);
526 break;
527 }
528 return BT_STATUS_UNSUPPORTED;
529 case BTHF_CLIENT_CALL_ACTION_CHLD_1:
530 // CHLD 1 is mandatory for 3 way calling
531 if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
532 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, 0, NULL);
533 break;
534 }
535 return BT_STATUS_UNSUPPORTED;
536 case BTHF_CLIENT_CALL_ACTION_CHLD_2:
537 // CHLD 2 is mandatory for 3 way calling
538 if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
539 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, 0, NULL);
540 break;
541 }
542 return BT_STATUS_UNSUPPORTED;
543 case BTHF_CLIENT_CALL_ACTION_CHLD_3:
544 if (cb->chld_feat & BTA_HF_CLIENT_CHLD_MERGE) {
545 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 3, 0, NULL);
546 break;
547 }
548 return BT_STATUS_UNSUPPORTED;
549 case BTHF_CLIENT_CALL_ACTION_CHLD_4:
550 if (cb->chld_feat & BTA_HF_CLIENT_CHLD_MERGE_DETACH) {
551 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 4, 0, NULL);
552 break;
553 }
554 return BT_STATUS_UNSUPPORTED;
555 case BTHF_CLIENT_CALL_ACTION_CHLD_1x:
556 if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECC) {
557 if (idx < 1) {
558 return BT_STATUS_FAIL;
559 }
560 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, idx, NULL);
561 break;
562 }
563 return BT_STATUS_UNSUPPORTED;
564 case BTHF_CLIENT_CALL_ACTION_CHLD_2x:
565 if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECC) {
566 if (idx < 1) {
567 return BT_STATUS_FAIL;
568 }
569 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, idx, NULL);
570 break;
571 }
572 return BT_STATUS_UNSUPPORTED;
573 case BTHF_CLIENT_CALL_ACTION_ATA:
574 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATA, 0, 0, NULL);
575 break;
576 case BTHF_CLIENT_CALL_ACTION_CHUP:
577 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHUP, 0, 0, NULL);
578 break;
579 case BTHF_CLIENT_CALL_ACTION_BTRH_0:
580 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 0, 0, NULL);
581 break;
582 case BTHF_CLIENT_CALL_ACTION_BTRH_1:
583 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 1, 0, NULL);
584 break;
585 case BTHF_CLIENT_CALL_ACTION_BTRH_2:
586 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 2, 0, NULL);
587 break;
588 default:
589 return BT_STATUS_FAIL;
590 }
591
592 return BT_STATUS_SUCCESS;
593 }
594
595 /*******************************************************************************
596 *
597 * Function query_current_calls
598 *
599 * Description query list of current calls
600 *
601 * Returns bt_status_t
602 *
603 ******************************************************************************/
query_current_calls(UNUSED_ATTR const RawAddress * bd_addr)604 static bt_status_t query_current_calls(UNUSED_ATTR const RawAddress* bd_addr) {
605 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
606 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
607
608 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
609
610 if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECS) {
611 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CLCC, 0, 0, NULL);
612 return BT_STATUS_SUCCESS;
613 }
614
615 return BT_STATUS_UNSUPPORTED;
616 }
617
618 /*******************************************************************************
619 *
620 * Function query_current_operator_name
621 *
622 * Description query current selected operator name
623 *
624 * Returns bt_status_t
625 *
626 ******************************************************************************/
query_current_operator_name(const RawAddress * bd_addr)627 static bt_status_t query_current_operator_name(const RawAddress* bd_addr) {
628 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
629 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
630
631 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
632
633 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_COPS, 0, 0, NULL);
634 return BT_STATUS_SUCCESS;
635 }
636
637 /*******************************************************************************
638 *
639 * Function retieve_subscriber_info
640 *
641 * Description retrieve subscriber number information
642 *
643 * Returns bt_status_t
644 *
645 ******************************************************************************/
retrieve_subscriber_info(const RawAddress * bd_addr)646 static bt_status_t retrieve_subscriber_info(const RawAddress* bd_addr) {
647 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
648 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
649
650 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
651
652 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CNUM, 0, 0, NULL);
653 return BT_STATUS_SUCCESS;
654 }
655
656 /*******************************************************************************
657 *
658 * Function send_dtmf
659 *
660 * Description send dtmf
661 *
662 * Returns bt_status_t
663 *
664 ******************************************************************************/
send_dtmf(const RawAddress * bd_addr,char code)665 static bt_status_t send_dtmf(const RawAddress* bd_addr, char code) {
666 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
667 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
668
669 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
670
671 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_VTS, code, 0, NULL);
672 return BT_STATUS_SUCCESS;
673 }
674
675 /*******************************************************************************
676 *
677 * Function request_last_voice_tag_number
678 *
679 * Description Request number from AG for VR purposes
680 *
681 * Returns bt_status_t
682 *
683 ******************************************************************************/
request_last_voice_tag_number(const RawAddress * bd_addr)684 static bt_status_t request_last_voice_tag_number(const RawAddress* bd_addr) {
685 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
686 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
687
688 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
689
690 if (cb->peer_feat & BTA_HF_CLIENT_PEER_VTAG) {
691 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BINP, 1, 0, NULL);
692 return BT_STATUS_SUCCESS;
693 }
694 return BT_STATUS_UNSUPPORTED;
695 }
696
697 /*******************************************************************************
698 *
699 * Function cleanup
700 *
701 * Description Closes the HF interface
702 *
703 * Returns bt_status_t
704 *
705 ******************************************************************************/
cleanup(void)706 static void cleanup(void) {
707 BTIF_TRACE_EVENT("%s", __func__);
708
709 btif_queue_cleanup(UUID_SERVCLASS_HF_HANDSFREE);
710 if (bt_hf_client_callbacks) {
711 btif_disable_service(BTA_HFP_HS_SERVICE_ID);
712 bt_hf_client_callbacks = NULL;
713 }
714 }
715
716 /*******************************************************************************
717 *
718 * Function send_at_cmd
719 *
720 * Description Send requested AT command to rempte device.
721 *
722 * Returns bt_status_t
723 *
724 ******************************************************************************/
send_at_cmd(const RawAddress * bd_addr,int cmd,int val1,int val2,const char * arg)725 static bt_status_t send_at_cmd(const RawAddress* bd_addr, int cmd, int val1,
726 int val2, const char* arg) {
727 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
728 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
729
730 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
731
732 BTIF_TRACE_EVENT("%s: Cmd %d val1 %d val2 %d arg %s", __func__, cmd, val1,
733 val2, (arg != NULL) ? arg : "<null>");
734 BTA_HfClientSendAT(cb->handle, cmd, val1, val2, arg);
735
736 return BT_STATUS_SUCCESS;
737 }
738
739 /*******************************************************************************
740 *
741 * Function send_hfp_audio_policy
742 *
743 * Description Send requested audio policies to remote device.
744 *
745 * Returns bt_status_t
746 *
747 ******************************************************************************/
send_android_at(const RawAddress * bd_addr,const char * arg)748 static bt_status_t send_android_at(const RawAddress* bd_addr, const char* arg) {
749 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
750 if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
751
752 CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
753
754 BTIF_TRACE_EVENT("%s: val1 %s", __func__, arg);
755 BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ANDROID, 0, 0, arg);
756
757 return BT_STATUS_SUCCESS;
758 }
759
760 static const bthf_client_interface_t bthfClientInterface = {
761 .size = sizeof(bthf_client_interface_t),
762 .init = init,
763 .connect = connect,
764 .disconnect = disconnect,
765 .connect_audio = connect_audio,
766 .disconnect_audio = disconnect_audio,
767 .start_voice_recognition = start_voice_recognition,
768 .stop_voice_recognition = stop_voice_recognition,
769 .volume_control = volume_control,
770 .dial = dial,
771 .dial_memory = dial_memory,
772 .handle_call_action = handle_call_action,
773 .query_current_calls = query_current_calls,
774 .query_current_operator_name = query_current_operator_name,
775 .retrieve_subscriber_info = retrieve_subscriber_info,
776 .send_dtmf = send_dtmf,
777 .request_last_voice_tag_number = request_last_voice_tag_number,
778 .cleanup = cleanup,
779 .send_at_cmd = send_at_cmd,
780 .send_android_at = send_android_at,
781 };
782
process_ind_evt(tBTA_HF_CLIENT_IND * ind)783 static void process_ind_evt(tBTA_HF_CLIENT_IND* ind) {
784 BTIF_TRACE_DEBUG("%s", __func__);
785
786 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(ind->bd_addr);
787 if (cb == NULL || !is_connected(cb)) return;
788
789 switch (ind->type) {
790 case BTA_HF_CLIENT_IND_CALL:
791 HAL_CBACK(bt_hf_client_callbacks, call_cb, &cb->peer_bda,
792 (bthf_client_call_t)ind->value);
793 break;
794
795 case BTA_HF_CLIENT_IND_CALLSETUP:
796 HAL_CBACK(bt_hf_client_callbacks, callsetup_cb, &cb->peer_bda,
797 (bthf_client_callsetup_t)ind->value);
798 break;
799 case BTA_HF_CLIENT_IND_CALLHELD:
800 HAL_CBACK(bt_hf_client_callbacks, callheld_cb, &cb->peer_bda,
801 (bthf_client_callheld_t)ind->value);
802 break;
803
804 case BTA_HF_CLIENT_IND_SERVICE:
805 HAL_CBACK(bt_hf_client_callbacks, network_state_cb, &cb->peer_bda,
806 (bthf_client_network_state_t)ind->value);
807 break;
808
809 case BTA_HF_CLIENT_IND_SIGNAL:
810 HAL_CBACK(bt_hf_client_callbacks, network_signal_cb, &cb->peer_bda,
811 ind->value);
812 break;
813
814 case BTA_HF_CLIENT_IND_ROAM:
815 HAL_CBACK(bt_hf_client_callbacks, network_roaming_cb, &cb->peer_bda,
816 (bthf_client_service_type_t)ind->value);
817 break;
818
819 case BTA_HF_CLIENT_IND_BATTCH:
820 HAL_CBACK(bt_hf_client_callbacks, battery_level_cb, &cb->peer_bda,
821 ind->value);
822 break;
823
824 default:
825 break;
826 }
827 }
828
829 /*******************************************************************************
830 *
831 * Function btif_hf_client_upstreams_evt
832 *
833 * Description Executes HF CLIENT UPSTREAMS events in btif context
834 *
835 * Returns void
836 *
837 ******************************************************************************/
btif_hf_client_upstreams_evt(uint16_t event,char * p_param)838 static void btif_hf_client_upstreams_evt(uint16_t event, char* p_param) {
839 tBTA_HF_CLIENT* p_data = (tBTA_HF_CLIENT*)p_param;
840
841 btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(p_data->bd_addr);
842 if (cb == NULL && event == BTA_HF_CLIENT_OPEN_EVT) {
843 BTIF_TRACE_DEBUG("%s: event BTA_HF_CLIENT_OPEN_EVT allocating block",
844 __func__);
845 cb = btif_hf_client_allocate_cb();
846 if (cb == NULL) {
847 BTIF_TRACE_ERROR("%s: event BTA_HF_CLIENT_OPEN_EVT failed to allocate cb",
848 __func__, event);
849 return;
850 }
851 cb->handle = p_data->open.handle;
852 cb->peer_bda = p_data->open.bd_addr;
853 } else if (cb == NULL) {
854 BTIF_TRACE_ERROR("%s: event %d but not allocating block: cb not found",
855 __func__, event);
856 return;
857 }
858
859 BTIF_TRACE_DEBUG("%s: event=%s (%u)", __func__, dump_hf_client_event(event),
860 event);
861
862 switch (event) {
863 case BTA_HF_CLIENT_OPEN_EVT:
864 if (p_data->open.status == BTA_HF_CLIENT_SUCCESS) {
865 cb->state = BTHF_CLIENT_CONNECTION_STATE_CONNECTED;
866 cb->peer_feat = 0;
867 cb->chld_feat = 0;
868 cb->handle = p_data->open.handle;
869 } else if (cb->state == BTHF_CLIENT_CONNECTION_STATE_CONNECTING) {
870 cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
871 } else {
872 BTIF_TRACE_WARNING(
873 "%s: HF CLient open failed, but another device connected. "
874 "status=%d state=%d connected device=%s",
875 __func__, p_data->open.status, cb->state,
876 ADDRESS_TO_LOGGABLE_CSTR(cb->peer_bda));
877 break;
878 }
879
880 HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
881 cb->state, 0, /* peer feat */
882 0 /* AT+CHLD feat */);
883
884 if (cb->state == BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED)
885 cb->peer_bda = RawAddress::kAny;
886
887 if (p_data->open.status != BTA_HF_CLIENT_SUCCESS) btif_queue_advance();
888 break;
889
890 case BTA_HF_CLIENT_CONN_EVT:
891 cb->peer_feat = p_data->conn.peer_feat;
892 cb->chld_feat = p_data->conn.chld_feat;
893 cb->state = BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED;
894
895 HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
896 cb->state, cb->peer_feat, cb->chld_feat);
897
898 /* Inform the application about in-band ringtone */
899 if (cb->peer_feat & BTA_HF_CLIENT_PEER_INBAND) {
900 HAL_CBACK(bt_hf_client_callbacks, in_band_ring_tone_cb, &cb->peer_bda,
901 BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED);
902 }
903
904 btif_queue_advance();
905 break;
906
907 case BTA_HF_CLIENT_CLOSE_EVT:
908 cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
909 HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
910 cb->state, 0, 0);
911 cb->peer_bda = RawAddress::kAny;
912 cb->peer_feat = 0;
913 cb->chld_feat = 0;
914 cb->handle = 0;
915
916 /* Clean up any btif_hf_client_cb for the same disconnected bd_addr.
917 * when there is an Incoming hf_client connection is in progress and
918 * at the same time, outgoing hf_client connection is initiated then
919 * due to race condition two btif_hf_client_cb is created. This creates
920 * problem for successive connections
921 */
922 while ((cb = btif_hf_client_get_cb_by_bda(p_data->bd_addr)) != NULL) {
923 cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
924 cb->peer_bda = RawAddress::kAny;
925 cb->peer_feat = 0;
926 cb->chld_feat = 0;
927 cb->handle = 0;
928 }
929
930 btif_queue_advance();
931 break;
932
933 case BTA_HF_CLIENT_IND_EVT:
934 process_ind_evt(&p_data->ind);
935 break;
936
937 case BTA_HF_CLIENT_MIC_EVT:
938 HAL_CBACK(bt_hf_client_callbacks, volume_change_cb, &cb->peer_bda,
939 BTHF_CLIENT_VOLUME_TYPE_MIC, p_data->val.value);
940 break;
941
942 case BTA_HF_CLIENT_SPK_EVT:
943 HAL_CBACK(bt_hf_client_callbacks, volume_change_cb, &cb->peer_bda,
944 BTHF_CLIENT_VOLUME_TYPE_SPK, p_data->val.value);
945 break;
946
947 case BTA_HF_CLIENT_VOICE_REC_EVT:
948 HAL_CBACK(bt_hf_client_callbacks, vr_cmd_cb, &cb->peer_bda,
949 (bthf_client_vr_state_t)p_data->val.value);
950 break;
951
952 case BTA_HF_CLIENT_OPERATOR_NAME_EVT:
953 HAL_CBACK(bt_hf_client_callbacks, current_operator_cb, &cb->peer_bda,
954 p_data->operator_name.name);
955 break;
956
957 case BTA_HF_CLIENT_CLIP_EVT:
958 HAL_CBACK(bt_hf_client_callbacks, clip_cb, &cb->peer_bda,
959 p_data->number.number);
960 break;
961
962 case BTA_HF_CLIENT_BINP_EVT:
963 HAL_CBACK(bt_hf_client_callbacks, last_voice_tag_number_callback,
964 &cb->peer_bda, p_data->number.number);
965 break;
966
967 case BTA_HF_CLIENT_CCWA_EVT:
968 HAL_CBACK(bt_hf_client_callbacks, call_waiting_cb, &cb->peer_bda,
969 p_data->number.number);
970 break;
971
972 case BTA_HF_CLIENT_AT_RESULT_EVT:
973 HAL_CBACK(bt_hf_client_callbacks, cmd_complete_cb, &cb->peer_bda,
974 (bthf_client_cmd_complete_t)p_data->result.type,
975 p_data->result.cme);
976 break;
977
978 case BTA_HF_CLIENT_CLCC_EVT:
979 HAL_CBACK(bt_hf_client_callbacks, current_calls_cb, &cb->peer_bda,
980 p_data->clcc.idx,
981 p_data->clcc.inc ? BTHF_CLIENT_CALL_DIRECTION_INCOMING
982 : BTHF_CLIENT_CALL_DIRECTION_OUTGOING,
983 (bthf_client_call_state_t)p_data->clcc.status,
984 p_data->clcc.mpty ? BTHF_CLIENT_CALL_MPTY_TYPE_MULTI
985 : BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE,
986 p_data->clcc.number_present ? p_data->clcc.number : "");
987 break;
988
989 case BTA_HF_CLIENT_CNUM_EVT:
990 if (p_data->cnum.service == 4) {
991 HAL_CBACK(bt_hf_client_callbacks, subscriber_info_cb, &cb->peer_bda,
992 p_data->cnum.number, BTHF_CLIENT_SERVICE_VOICE);
993 } else if (p_data->cnum.service == 5) {
994 HAL_CBACK(bt_hf_client_callbacks, subscriber_info_cb, &cb->peer_bda,
995 p_data->cnum.number, BTHF_CLIENT_SERVICE_FAX);
996 } else {
997 HAL_CBACK(bt_hf_client_callbacks, subscriber_info_cb, &cb->peer_bda,
998 p_data->cnum.number, BTHF_CLIENT_SERVICE_UNKNOWN);
999 }
1000 break;
1001
1002 case BTA_HF_CLIENT_BTRH_EVT:
1003 if (p_data->val.value <= BTRH_CLIENT_RESP_AND_HOLD_REJECT) {
1004 HAL_CBACK(bt_hf_client_callbacks, resp_and_hold_cb, &cb->peer_bda,
1005 (bthf_client_resp_and_hold_t)p_data->val.value);
1006 }
1007 break;
1008
1009 case BTA_HF_CLIENT_BSIR_EVT:
1010 if (p_data->val.value != 0) {
1011 HAL_CBACK(bt_hf_client_callbacks, in_band_ring_tone_cb, &cb->peer_bda,
1012 BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED);
1013 } else {
1014 HAL_CBACK(bt_hf_client_callbacks, in_band_ring_tone_cb, &cb->peer_bda,
1015 BTHF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED);
1016 }
1017 break;
1018
1019 case BTA_HF_CLIENT_AUDIO_OPEN_EVT:
1020 HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
1021 BTHF_CLIENT_AUDIO_STATE_CONNECTED);
1022 break;
1023
1024 case BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT:
1025 HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
1026 BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC);
1027 break;
1028
1029 case BTA_HF_CLIENT_AUDIO_CLOSE_EVT:
1030 HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
1031 BTHF_CLIENT_AUDIO_STATE_DISCONNECTED);
1032 break;
1033 case BTA_HF_CLIENT_RING_INDICATION:
1034 HAL_CBACK(bt_hf_client_callbacks, ring_indication_cb, &cb->peer_bda);
1035 break;
1036 case BTA_HF_CLIENT_UNKNOWN_EVT:
1037 HAL_CBACK(bt_hf_client_callbacks, unknown_event_cb, &cb->peer_bda,
1038 p_data->unknown.event_string);
1039 break;
1040 default:
1041 BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
1042 break;
1043 }
1044 }
1045
1046 /*******************************************************************************
1047 *
1048 * Function bta_hf_client_evt
1049 *
1050 * Description Switches context from BTA to BTIF for all HF Client events
1051 *
1052 * Returns void
1053 *
1054 ******************************************************************************/
1055
bta_hf_client_evt(tBTA_HF_CLIENT_EVT event,tBTA_HF_CLIENT * p_data)1056 static void bta_hf_client_evt(tBTA_HF_CLIENT_EVT event,
1057 tBTA_HF_CLIENT* p_data) {
1058 bt_status_t status;
1059
1060 /* switch context to btif task context (copy full union size for convenience)
1061 */
1062 status = btif_transfer_context(btif_hf_client_upstreams_evt, (uint16_t)event,
1063 (char*)p_data, sizeof(*p_data), NULL);
1064
1065 /* catch any failed context transfers */
1066 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
1067 }
1068
1069 /*******************************************************************************
1070 *
1071 * Function btif_hf_client_execute_service
1072 *
1073 * Description Initializes/Shuts down the service
1074 *
1075 * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1076 *
1077 ******************************************************************************/
btif_hf_client_execute_service(bool b_enable)1078 bt_status_t btif_hf_client_execute_service(bool b_enable) {
1079 BTIF_TRACE_EVENT("%s: enable: %d", __func__, b_enable);
1080
1081 tBTA_HF_CLIENT_FEAT features = get_default_hf_client_features();
1082 uint16_t hfp_version = get_default_hfp_version();
1083 if (hfp_version >= HFP_VERSION_1_7) {
1084 features |= BTA_HF_CLIENT_FEAT_ESCO_S4;
1085 }
1086
1087 if (b_enable) {
1088 /* Enable and register with BTA-HFClient */
1089 BTIF_TRACE_EVENT("%s: support codec negotiation %d ", __func__,
1090 features);
1091 BTA_HfClientEnable(bta_hf_client_evt, features,
1092 BTIF_HF_CLIENT_SERVICE_NAME);
1093 } else {
1094 BTA_HfClientDisable();
1095 }
1096 return BT_STATUS_SUCCESS;
1097 }
1098
1099 /*******************************************************************************
1100 *
1101 * Function btif_hf_get_interface
1102 *
1103 * Description Get the hf callback interface
1104 *
1105 * Returns bthf_interface_t
1106 *
1107 ******************************************************************************/
btif_hf_client_get_interface(void)1108 const bthf_client_interface_t* btif_hf_client_get_interface(void) {
1109 BTIF_TRACE_EVENT("%s", __func__);
1110 return &bthfClientInterface;
1111 }
1112