• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (c) 2016 The Android Open Source Project
4  *  Copyright 2003-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 #include <cstdint>
21 #include <cstdio>
22 
23 #include "bta/hf_client/bta_hf_client_int.h"
24 #include "bta/include/utl.h"
25 #include "osi/include/allocator.h"
26 #include "osi/include/osi.h"  // UNUSED_ATTR
27 #include "stack/include/btm_api.h"
28 
29 static const char* bta_hf_client_evt_str(uint16_t event);
30 static const char* bta_hf_client_state_str(uint8_t state);
31 void bta_hf_client_cb_init(tBTA_HF_CLIENT_CB* client_cb, uint16_t handle);
32 
33 /* state machine states */
34 enum {
35   BTA_HF_CLIENT_INIT_ST,
36   BTA_HF_CLIENT_OPENING_ST,
37   BTA_HF_CLIENT_OPEN_ST,
38   BTA_HF_CLIENT_CLOSING_ST
39 };
40 
41 /* state machine action enumeration list */
42 enum {
43   BTA_HF_CLIENT_RFC_DO_CLOSE,
44   BTA_HF_CLIENT_START_CLOSE,
45   BTA_HF_CLIENT_START_OPEN,
46   BTA_HF_CLIENT_RFC_ACP_OPEN,
47   BTA_HF_CLIENT_SCO_LISTEN,
48   BTA_HF_CLIENT_SCO_CONN_OPEN,
49   BTA_HF_CLIENT_SCO_CONN_CLOSE,
50   BTA_HF_CLIENT_SCO_OPEN,
51   BTA_HF_CLIENT_SCO_CLOSE,
52   BTA_HF_CLIENT_FREE_DB,
53   BTA_HF_CLIENT_OPEN_FAIL,
54   BTA_HF_CLIENT_RFC_OPEN,
55   BTA_HF_CLIENT_RFC_FAIL,
56   BTA_HF_CLIENT_DISC_INT_RES,
57   BTA_HF_CLIENT_RFC_DO_OPEN,
58   BTA_HF_CLIENT_DISC_FAIL,
59   BTA_HF_CLIENT_RFC_CLOSE,
60   BTA_HF_CLIENT_RFC_DATA,
61   BTA_HF_CLIENT_DISC_ACP_RES,
62   BTA_HF_CLIENT_SVC_CONN_OPEN,
63   BTA_HF_CLIENT_SEND_AT_CMD,
64   BTA_HF_CLIENT_NUM_ACTIONS,
65 };
66 
67 #define BTA_HF_CLIENT_IGNORE BTA_HF_CLIENT_NUM_ACTIONS
68 
69 /* type for action functions */
70 typedef void (*tBTA_HF_CLIENT_ACTION)(tBTA_HF_CLIENT_DATA* p_data);
71 
72 /* action functions table, indexed with action enum */
73 const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = {
74     /* BTA_HF_CLIENT_RFC_DO_CLOSE */ bta_hf_client_rfc_do_close,
75     /* BTA_HF_CLIENT_START_CLOSE */ bta_hf_client_start_close,
76     /* BTA_HF_CLIENT_START_OPEN */ bta_hf_client_start_open,
77     /* BTA_HF_CLIENT_RFC_ACP_OPEN */ bta_hf_client_rfc_acp_open,
78     /* BTA_HF_CLIENT_SCO_LISTEN */ NULL,
79     /* BTA_HF_CLIENT_SCO_CONN_OPEN */ bta_hf_client_sco_conn_open,
80     /* BTA_HF_CLIENT_SCO_CONN_CLOSE*/ bta_hf_client_sco_conn_close,
81     /* BTA_HF_CLIENT_SCO_OPEN */ bta_hf_client_sco_open,
82     /* BTA_HF_CLIENT_SCO_CLOSE */ bta_hf_client_sco_close,
83     /* BTA_HF_CLIENT_FREE_DB */ bta_hf_client_free_db,
84     /* BTA_HF_CLIENT_OPEN_FAIL */ bta_hf_client_open_fail,
85     /* BTA_HF_CLIENT_RFC_OPEN */ bta_hf_client_rfc_open,
86     /* BTA_HF_CLIENT_RFC_FAIL */ bta_hf_client_rfc_fail,
87     /* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res,
88     /* BTA_HF_CLIENT_RFC_DO_OPEN */ bta_hf_client_rfc_do_open,
89     /* BTA_HF_CLIENT_DISC_FAIL */ bta_hf_client_disc_fail,
90     /* BTA_HF_CLIENT_RFC_CLOSE */ bta_hf_client_rfc_close,
91     /* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data,
92     /* BTA_HF_CLIENT_DISC_ACP_RES */ bta_hf_client_disc_acp_res,
93     /* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open,
94     /* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd,
95 };
96 
97 /* state table information */
98 #define BTA_HF_CLIENT_ACTIONS 2    /* number of actions */
99 #define BTA_HF_CLIENT_NEXT_STATE 2 /* position of next state */
100 #define BTA_HF_CLIENT_NUM_COLS 3   /* number of columns in state tables */
101 
102 /* state table for init state */
103 const uint8_t bta_hf_client_st_init[][BTA_HF_CLIENT_NUM_COLS] = {
104     /* Event                    Action 1                       Action 2
105        Next state */
106     /* API_OPEN_EVT */ {BTA_HF_CLIENT_START_OPEN, BTA_HF_CLIENT_IGNORE,
107                         BTA_HF_CLIENT_OPENING_ST},
108     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
109                          BTA_HF_CLIENT_INIT_ST},
110     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
111                               BTA_HF_CLIENT_INIT_ST},
112     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
113                                BTA_HF_CLIENT_INIT_ST},
114     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_ACP_OPEN, BTA_HF_CLIENT_IGNORE,
115                         BTA_HF_CLIENT_OPEN_ST},
116     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
117                          BTA_HF_CLIENT_INIT_ST},
118     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
119                              BTA_HF_CLIENT_INIT_ST},
120     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
121                         BTA_HF_CLIENT_INIT_ST},
122     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE,
123                             BTA_HF_CLIENT_INIT_ST},
124     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
125                             BTA_HF_CLIENT_INIT_ST},
126     /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
127                        BTA_HF_CLIENT_INIT_ST},
128     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
129                          BTA_HF_CLIENT_INIT_ST},
130     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
131                         BTA_HF_CLIENT_INIT_ST},
132     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
133                          BTA_HF_CLIENT_INIT_ST},
134     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
135                            BTA_HF_CLIENT_INIT_ST},
136 };
137 
138 /* state table for opening state */
139 const uint8_t bta_hf_client_st_opening[][BTA_HF_CLIENT_NUM_COLS] = {
140     /* Event                    Action 1                       Action 2
141        Next state */
142     /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE,
143                         BTA_HF_CLIENT_OPENING_ST},
144     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_DO_CLOSE, BTA_HF_CLIENT_IGNORE,
145                          BTA_HF_CLIENT_CLOSING_ST},
146     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
147                               BTA_HF_CLIENT_OPENING_ST},
148     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
149                                BTA_HF_CLIENT_OPENING_ST},
150     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_OPEN, BTA_HF_CLIENT_IGNORE,
151                         BTA_HF_CLIENT_OPEN_ST},
152     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_FAIL, BTA_HF_CLIENT_IGNORE,
153                          BTA_HF_CLIENT_INIT_ST},
154     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
155                              BTA_HF_CLIENT_OPENING_ST},
156     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
157                         BTA_HF_CLIENT_OPENING_ST},
158     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
159                             BTA_HF_CLIENT_OPENING_ST},
160     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_DISC_INT_RES, BTA_HF_CLIENT_IGNORE,
161                             BTA_HF_CLIENT_OPENING_ST},
162     /* DISC_OK_EVT */ {BTA_HF_CLIENT_RFC_DO_OPEN, BTA_HF_CLIENT_IGNORE,
163                        BTA_HF_CLIENT_OPENING_ST},
164     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_DISC_FAIL, BTA_HF_CLIENT_IGNORE,
165                          BTA_HF_CLIENT_INIT_ST},
166     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
167                         BTA_HF_CLIENT_OPENING_ST},
168     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
169                          BTA_HF_CLIENT_OPENING_ST},
170     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
171                            BTA_HF_CLIENT_OPENING_ST},
172 };
173 
174 /* state table for open state */
175 const uint8_t bta_hf_client_st_open[][BTA_HF_CLIENT_NUM_COLS] = {
176     /* Event                    Action 1                       Action 2
177        Next state */
178     /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE,
179                         BTA_HF_CLIENT_OPEN_ST},
180     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_START_CLOSE, BTA_HF_CLIENT_IGNORE,
181                          BTA_HF_CLIENT_CLOSING_ST},
182     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_OPEN, BTA_HF_CLIENT_IGNORE,
183                               BTA_HF_CLIENT_OPEN_ST},
184     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CLOSE, BTA_HF_CLIENT_IGNORE,
185                                BTA_HF_CLIENT_OPEN_ST},
186     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
187                         BTA_HF_CLIENT_OPEN_ST},
188     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE,
189                          BTA_HF_CLIENT_INIT_ST},
190     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
191                              BTA_HF_CLIENT_OPEN_ST},
192     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_RFC_DATA, BTA_HF_CLIENT_IGNORE,
193                         BTA_HF_CLIENT_OPEN_ST},
194     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_DISC_ACP_RES, BTA_HF_CLIENT_IGNORE,
195                             BTA_HF_CLIENT_OPEN_ST},
196     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
197                             BTA_HF_CLIENT_OPEN_ST},
198     /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
199                        BTA_HF_CLIENT_OPEN_ST},
200     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
201                          BTA_HF_CLIENT_OPEN_ST},
202     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_CONN_OPEN, BTA_HF_CLIENT_IGNORE,
203                         BTA_HF_CLIENT_OPEN_ST},
204     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE,
205                          BTA_HF_CLIENT_OPEN_ST},
206     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_SEND_AT_CMD, BTA_HF_CLIENT_IGNORE,
207                            BTA_HF_CLIENT_OPEN_ST},
208 };
209 
210 /* state table for closing state */
211 const uint8_t bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = {
212     /* Event                    Action 1                       Action 2
213        Next state */
214     /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE,
215                         BTA_HF_CLIENT_CLOSING_ST},
216     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
217                          BTA_HF_CLIENT_CLOSING_ST},
218     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
219                               BTA_HF_CLIENT_CLOSING_ST},
220     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
221                                BTA_HF_CLIENT_CLOSING_ST},
222     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
223                         BTA_HF_CLIENT_CLOSING_ST},
224     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE,
225                          BTA_HF_CLIENT_INIT_ST},
226     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
227                              BTA_HF_CLIENT_CLOSING_ST},
228     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
229                         BTA_HF_CLIENT_CLOSING_ST},
230     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE,
231                             BTA_HF_CLIENT_CLOSING_ST},
232     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE,
233                             BTA_HF_CLIENT_INIT_ST},
234     /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
235                        BTA_HF_CLIENT_CLOSING_ST},
236     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
237                          BTA_HF_CLIENT_CLOSING_ST},
238     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
239                         BTA_HF_CLIENT_CLOSING_ST},
240     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
241                          BTA_HF_CLIENT_CLOSING_ST},
242     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
243                            BTA_HF_CLIENT_CLOSING_ST},
244 };
245 
246 /* type for state table */
247 typedef const uint8_t (*tBTA_HF_CLIENT_ST_TBL)[BTA_HF_CLIENT_NUM_COLS];
248 
249 /* state table */
250 const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = {
251     bta_hf_client_st_init, bta_hf_client_st_opening, bta_hf_client_st_open,
252     bta_hf_client_st_closing};
253 
254 /* HF Client control block */
255 tBTA_HF_CLIENT_CB_ARR bta_hf_client_cb_arr;
256 
257 /* Event handler for the state machine */
258 static const tBTA_SYS_REG bta_hf_client_reg = {bta_hf_client_hdl_event,
259                                                BTA_HfClientDisable};
260 
261 /*******************************************************************************
262  *
263  * Function         bta_hf_client_cb_arr_init
264  *
265  * Description      Initialize entire control block array set
266  *
267  *
268  * Returns          void
269  *
270  ******************************************************************************/
bta_hf_client_cb_arr_init()271 void bta_hf_client_cb_arr_init() {
272   memset(&bta_hf_client_cb_arr, 0, sizeof(tBTA_HF_CLIENT_CB_ARR));
273 
274   // reset the handles and make the CBs non-allocated
275   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
276     // Allocate the handles in increasing order of indices
277     bta_hf_client_cb_init(&(bta_hf_client_cb_arr.cb[i]), i);
278     bta_hf_client_cb_arr.cb[i].handle = BTA_HF_CLIENT_CB_FIRST_HANDLE + i;
279   }
280 }
281 
282 /*******************************************************************************
283  *
284  * Function         bta_hf_client_cb_init
285  *
286  * Description      Initialize an HF_Client service control block. Assign the
287  *                  handle to cb->handle.
288  *
289  *
290  *
291  * Returns          void
292  *
293  ******************************************************************************/
bta_hf_client_cb_init(tBTA_HF_CLIENT_CB * client_cb,uint16_t handle)294 void bta_hf_client_cb_init(tBTA_HF_CLIENT_CB* client_cb, uint16_t handle) {
295   APPL_TRACE_DEBUG("%s", __func__);
296 
297   // Free any memory we need to explicity release
298   alarm_free(client_cb->collision_timer);
299 
300   // release unique pointers
301   client_cb->enabled_hf_indicators.clear();
302   client_cb->peer_hf_indicators.clear();
303 
304   // Memset the rest of the block
305   // memset(client_cb, 0, sizeof(tBTA_HF_CLIENT_CB));
306   *client_cb = {};
307 
308   // Re allocate any variables required
309   client_cb->collision_timer = alarm_new("bta_hf_client.scb_collision_timer");
310   client_cb->handle = handle;
311   client_cb->sco_idx = BTM_INVALID_SCO_INDEX;
312 }
313 
314 /*******************************************************************************
315  *
316  * Function         bta_hf_client_resume_open
317  *
318  * Description      Resume opening process.
319  *
320  *
321  * Returns          void
322  *
323  ******************************************************************************/
bta_hf_client_resume_open(tBTA_HF_CLIENT_CB * client_cb)324 void bta_hf_client_resume_open(tBTA_HF_CLIENT_CB* client_cb) {
325   APPL_TRACE_DEBUG("%s", __func__);
326 
327   /* resume opening process.  */
328   if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
329     client_cb->state = BTA_HF_CLIENT_OPENING_ST;
330     tBTA_HF_CLIENT_DATA msg;
331     msg.hdr.layer_specific = client_cb->handle;
332     msg.api_open.bd_addr = client_cb->peer_addr;
333     bta_hf_client_start_open(&msg);
334   }
335 }
336 
337 /*******************************************************************************
338  *
339  * Function         bta_hf_client_collision_timer_cback
340  *
341  * Description      HF Client connection collision timer callback
342  *
343  *
344  * Returns          void
345  *
346  ******************************************************************************/
bta_hf_client_collision_timer_cback(void * data)347 static void bta_hf_client_collision_timer_cback(void* data) {
348   APPL_TRACE_DEBUG("%s", __func__);
349   tBTA_HF_CLIENT_CB* client_cb = (tBTA_HF_CLIENT_CB*)data;
350 
351   /* If the peer haven't opened connection, restart opening process */
352   bta_hf_client_resume_open(client_cb);
353 }
354 
355 /*******************************************************************************
356  *
357  * Function         bta_hf_client_collision_cback
358  *
359  * Description      Get notified about collision.
360  *
361  *
362  * Returns          void
363  *
364  ******************************************************************************/
bta_hf_client_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status,uint8_t id,UNUSED_ATTR uint8_t app_id,const RawAddress & peer_addr)365 void bta_hf_client_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status,
366                                    uint8_t id, UNUSED_ATTR uint8_t app_id,
367                                    const RawAddress& peer_addr) {
368   tBTA_HF_CLIENT_CB* client_cb = bta_hf_client_find_cb_by_bda(peer_addr);
369   if (client_cb != NULL && client_cb->state == BTA_HF_CLIENT_OPENING_ST) {
370     if (id == BTA_ID_SYS) /* ACL collision */
371     {
372       APPL_TRACE_WARNING("HF Client found collision (ACL) ...");
373     } else if (id == BTA_ID_HS) /* RFCOMM collision */
374     {
375       APPL_TRACE_WARNING("HF Client found collision (RFCOMM) ...");
376     } else {
377       APPL_TRACE_WARNING("HF Client found collision (\?\?\?) ...");
378     }
379 
380     client_cb->state = BTA_HF_CLIENT_INIT_ST;
381 
382     /* Cancel SDP if it had been started. */
383     if (client_cb->p_disc_db) {
384       (void)SDP_CancelServiceSearch(client_cb->p_disc_db);
385       osi_free_and_reset((void**)&client_cb->p_disc_db);
386     }
387 
388     /* reopen registered server */
389     /* Collision may be detected before or after we close servers. */
390     bta_hf_client_start_server();
391 
392     /* Start timer to handle connection opening restart */
393     alarm_set_on_mloop(client_cb->collision_timer,
394                        BTA_HF_CLIENT_COLLISION_TIMER_MS,
395                        bta_hf_client_collision_timer_cback, (void*)client_cb);
396   }
397 }
398 
399 /*******************************************************************************
400  *
401  * Function         bta_hf_client_api_enable
402  *
403  * Description      Handle an API enable event.
404  *
405  *
406  * Returns          void
407  *
408  ******************************************************************************/
bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK * p_cback,tBTA_HF_CLIENT_FEAT features,const char * p_service_name)409 tBTA_STATUS bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK* p_cback,
410                                      tBTA_HF_CLIENT_FEAT features,
411                                      const char* p_service_name) {
412   /* If already registered then return error */
413   if (bta_sys_is_register(BTA_ID_HS)) {
414     APPL_TRACE_ERROR("BTA HF Client is already enabled, ignoring ...");
415     return BTA_FAILURE;
416   }
417 
418   /* register with BTA system manager */
419   bta_sys_register(BTA_ID_HS, &bta_hf_client_reg);
420 
421   /* reset the control blocks */
422   bta_hf_client_cb_arr_init();
423 
424   bta_hf_client_cb_arr.p_cback = p_cback;
425   bta_hf_client_cb_arr.features = features;
426 
427   /* create SDP records */
428   bta_hf_client_create_record(&bta_hf_client_cb_arr, p_service_name);
429 
430   /* set same setting as AG does */
431   BTM_WriteVoiceSettings(AG_VOICE_SETTINGS);
432 
433   bta_sys_collision_register(BTA_ID_HS, bta_hf_client_collision_cback);
434 
435   /* Set the Audio service class bit */
436   tBTA_UTL_COD cod;
437   cod.service = BTM_COD_SERVICE_AUDIO;
438   utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
439 
440   /* start RFCOMM server */
441   bta_hf_client_start_server();
442 
443   return BTA_SUCCESS;
444 }
445 
446 /*******************************************************************************
447  *
448  * Function         bta_hf_client_find_cb_by_handle
449  *
450  * Description      Finds the control block by handle provided
451  *
452  *                  handle: Handle as obtained from BTA_HfClientOpen call
453  *
454  *
455  * Returns          Control block corresponding to the handle and NULL if
456  *                  none exists
457  *
458  ******************************************************************************/
bta_hf_client_find_cb_by_handle(uint16_t handle)459 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_handle(uint16_t handle) {
460   // Handles are limited from 1 through HF_CLIENT_MAX_DEVICES
461   if (handle < 1 || handle > HF_CLIENT_MAX_DEVICES) {
462     APPL_TRACE_ERROR("%s: handle out of range (%d, %d) %d", __func__, 1,
463                      HF_CLIENT_MAX_DEVICES, handle);
464     return NULL;
465   }
466 
467   // Check if the associated index is allocated. Index is (handle - 1).
468   if (bta_hf_client_cb_arr.cb[handle - 1].is_allocated)
469     return &(bta_hf_client_cb_arr.cb[handle - 1]);
470 
471   APPL_TRACE_ERROR("%s: block not found for handle %d", __func__, handle);
472   return NULL;
473 }
474 
475 /*******************************************************************************
476  *
477  * Function         bta_hf_client_find_cb_by_bda
478  *
479  * Description      Finds the control block by handle provided
480  *
481  *                  bda: address of the device to find the handle for.
482  *                  Since there can only be one HF connection for a device
483  *                  we should always find a unique block
484  *
485  * Returns          Control block corresponding to the address and NULL if
486  *                  none exists
487  *
488  ******************************************************************************/
bta_hf_client_find_cb_by_bda(const RawAddress & peer_addr)489 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_bda(const RawAddress& peer_addr) {
490   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
491     // Check if the associated index is allocated and that BD ADDR matches
492     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
493     if (client_cb->is_allocated && peer_addr == client_cb->peer_addr) {
494       return client_cb;
495     } else {
496       APPL_TRACE_WARNING("%s: bdaddr mismatch for handle %d alloc %d", __func__,
497                          i, client_cb->is_allocated);
498     }
499   }
500   APPL_TRACE_ERROR("%s: block not found", __func__);
501   return NULL;
502 }
503 
504 /*******************************************************************************
505  *
506  * Function         bta_hf_client_find_cb_by_rfc_handle
507  *
508  * Description      Finds the control block by RFC handle provided.
509  *
510  *                  handle: RFC handle for the established connection
511  *
512  *
513  * Returns          Control block corresponding to the handle and NULL if none
514  *                  exists
515  *
516  ******************************************************************************/
bta_hf_client_find_cb_by_rfc_handle(uint16_t handle)517 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_rfc_handle(uint16_t handle) {
518   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
519     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
520     bool is_allocated = client_cb->is_allocated;
521     uint16_t conn_handle = client_cb->conn_handle;
522 
523     APPL_TRACE_DEBUG("%s: cb rfc_handle %d alloc %d conn_handle %d", __func__,
524                      handle, is_allocated, conn_handle);
525 
526     if (is_allocated && conn_handle == handle) {
527       return client_cb;
528     }
529 
530     APPL_TRACE_WARNING("%s: no cb yet %d alloc %d conn_handle %d", __func__,
531                        handle, is_allocated, conn_handle);
532   }
533 
534   APPL_TRACE_ERROR("%s: no cb found for rfc handle %d", __func__, handle);
535   return NULL;
536 }
537 
538 /*******************************************************************************
539  *
540  * Function         bta_hf_client_find_cb_by_sco_handle
541  *
542  * Description      Finds the control block by sco handle provided
543  *
544  *                  handle: sco handle
545  *
546  *
547  * Returns          Control block corresponding to the sco handle and
548  *                  none if none exists
549  *
550  ******************************************************************************/
bta_hf_client_find_cb_by_sco_handle(uint16_t handle)551 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_sco_handle(uint16_t handle) {
552   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
553     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
554     if (client_cb->is_allocated && client_cb->sco_idx == handle) {
555       return client_cb;
556     }
557   }
558   APPL_TRACE_ERROR("%s: block not found for handle %d", __func__, handle);
559   return NULL;
560 }
561 
562 /*******************************************************************************
563  *
564  * Function         bta_hf_client_allocate_handle
565  *
566  * Description      Allocates a handle for the new BD ADDR that needs a new RF
567  *                  channel for HF connection. If the channel cannot be created
568  *                  for a reason then false is returned
569  *
570  *                  bd_addr: Address of the device for which this block is
571  *                  being created. Single device can only have one block.
572  *                  p_handle: OUT variable to store the outcome of allocate. If
573  *                  allocate failed then value is not valid
574  *
575  *
576  * Returns          true if the creation of p_handle succeeded, false otherwise
577  *
578  ******************************************************************************/
bta_hf_client_allocate_handle(const RawAddress & bd_addr,uint16_t * p_handle)579 bool bta_hf_client_allocate_handle(const RawAddress& bd_addr,
580                                    uint16_t* p_handle) {
581   tBTA_HF_CLIENT_CB* existing_cb = bta_hf_client_find_cb_by_bda(bd_addr);
582   if (existing_cb != NULL) {
583     BTIF_TRACE_ERROR("%s: cannot allocate handle since BDADDR already exists",
584                      __func__);
585     return false;
586   }
587   /* Check that we do not have a request to for same device in the control
588    * blocks */
589   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
590     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
591     if (client_cb->is_allocated) {
592       APPL_TRACE_WARNING("%s: control block already used index %d", __func__,
593                          i);
594       continue;
595     }
596 
597     // Reset the client control block
598     bta_hf_client_cb_init(client_cb, client_cb->handle);
599 
600     *p_handle = client_cb->handle;
601     APPL_TRACE_DEBUG("%s: marking CB handle %d to true", __func__,
602                      client_cb->handle);
603 
604     client_cb->is_allocated = true;
605     client_cb->peer_addr = bd_addr;
606     bta_hf_client_at_init(client_cb);
607     return true;
608   }
609 
610   return false;
611   APPL_TRACE_ERROR("%s: all control blocks in use!", __func__);
612 }
613 
614 /*******************************************************************************
615  *
616  * Function         bta_hf_client_app_callback
617  *
618  * Description      Calls the application callback
619  *
620  *
621  * Returns          Void
622  *
623  ******************************************************************************/
bta_hf_client_app_callback(uint16_t event,tBTA_HF_CLIENT * data)624 void bta_hf_client_app_callback(uint16_t event, tBTA_HF_CLIENT* data) {
625   if (bta_hf_client_cb_arr.p_cback != NULL) {
626     bta_hf_client_cb_arr.p_cback(event, data);
627   }
628 }
629 
630 /*******************************************************************************
631  *
632  * Function         bta_hf_client_api_disable
633  *
634  * Description      Handle an API disable event.
635  *
636  *
637  * Returns          void
638  *
639  ******************************************************************************/
bta_hf_client_api_disable()640 void bta_hf_client_api_disable() {
641   if (!bta_sys_is_register(BTA_ID_HS)) {
642     APPL_TRACE_WARNING("BTA HF Client is already disabled, ignoring ...");
643     return;
644   }
645 
646   /* Remove the collision handler */
647   bta_sys_collision_register(BTA_ID_HS, NULL);
648 
649   bta_hf_client_cb_arr.deregister = true;
650 
651   /* remove sdp record */
652   bta_hf_client_del_record(&bta_hf_client_cb_arr);
653 
654   /* remove rfcomm server */
655   bta_hf_client_close_server();
656 
657   /* reinit the control block */
658   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
659     if (bta_hf_client_cb_arr.cb[i].is_allocated) {
660       bta_hf_client_cb_init(&(bta_hf_client_cb_arr.cb[i]), i);
661     }
662   }
663 
664   /* De-register with BTA system manager */
665   bta_sys_deregister(BTA_ID_HS);
666 }
667 
668 /*******************************************************************************
669  *
670  * Function         bta_hf_client_hdl_event
671  *
672  * Description      Data HF Client main event handling function.
673  *
674  *
675  * Returns          bool
676  *
677  ******************************************************************************/
bta_hf_client_hdl_event(BT_HDR_RIGID * p_msg)678 bool bta_hf_client_hdl_event(BT_HDR_RIGID* p_msg) {
679   APPL_TRACE_DEBUG("%s: %s (0x%x)", __func__,
680                    bta_hf_client_evt_str(p_msg->event), p_msg->event);
681   bta_hf_client_sm_execute(p_msg->event, (tBTA_HF_CLIENT_DATA*)p_msg);
682   return true;
683 }
684 
685 /*******************************************************************************
686  *
687  * Function         bta_hf_client_sm_execute
688  *
689  * Description      State machine event handling function for HF Client
690  *
691  *
692  * Returns          void
693  *
694  ******************************************************************************/
bta_hf_client_sm_execute(uint16_t event,tBTA_HF_CLIENT_DATA * p_data)695 void bta_hf_client_sm_execute(uint16_t event, tBTA_HF_CLIENT_DATA* p_data) {
696   tBTA_HF_CLIENT_CB* client_cb =
697       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
698   if (client_cb == NULL) {
699     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
700                      p_data->hdr.layer_specific);
701     return;
702   }
703 
704   tBTA_HF_CLIENT_ST_TBL state_table;
705   uint8_t action;
706   int i;
707 
708   uint16_t in_event = event;
709   uint8_t in_state = client_cb->state;
710 
711   /* Ignore displaying of AT results when not connected (Ignored in state
712    * machine) */
713   if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
714     APPL_TRACE_EVENT("HF Client evt : State %d (%s), Event 0x%04x (%s)",
715                      client_cb->state,
716                      bta_hf_client_state_str(client_cb->state), event,
717                      bta_hf_client_evt_str(event));
718   }
719 
720   event &= 0x00FF;
721   if (event >= (BTA_HF_CLIENT_MAX_EVT & 0x00FF)) {
722     APPL_TRACE_ERROR("HF Client evt out of range, ignoring...");
723     return;
724   }
725 
726   /* look up the state table for the current state */
727   state_table = bta_hf_client_st_tbl[client_cb->state];
728 
729   /* set next state */
730   client_cb->state = state_table[event][BTA_HF_CLIENT_NEXT_STATE];
731 
732   /* execute action functions */
733   for (i = 0; i < BTA_HF_CLIENT_ACTIONS; i++) {
734     action = state_table[event][i];
735     if (action != BTA_HF_CLIENT_IGNORE) {
736       (*bta_hf_client_action[action])(p_data);
737     } else {
738       break;
739     }
740   }
741 
742   /* If the state has changed then notify the app of the corresponding change */
743   if (in_state != client_cb->state) {
744     VLOG(1) << __func__ << ": notifying state change to " << in_state << " -> "
745             << client_cb->state << " device " << client_cb->peer_addr;
746     tBTA_HF_CLIENT evt;
747     memset(&evt, 0, sizeof(evt));
748     evt.bd_addr = client_cb->peer_addr;
749     if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
750       bta_hf_client_app_callback(BTA_HF_CLIENT_CLOSE_EVT, &evt);
751       APPL_TRACE_DEBUG("%s: marking CB handle %d to false", __func__, client_cb->handle);
752       client_cb->is_allocated = false;
753     } else if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
754       evt.open.handle = client_cb->handle;
755       bta_hf_client_app_callback(BTA_HF_CLIENT_OPEN_EVT, &evt);
756     }
757   }
758 
759   VLOG(2) << __func__ << ": device " << client_cb->peer_addr
760           << "state change: [" << bta_hf_client_state_str(in_state) << "] -> ["
761           << bta_hf_client_state_str(client_cb->state) << "] after Event ["
762           << bta_hf_client_evt_str(in_event) << "]";
763 }
764 
send_post_slc_cmd(tBTA_HF_CLIENT_CB * client_cb)765 static void send_post_slc_cmd(tBTA_HF_CLIENT_CB* client_cb) {
766   client_cb->at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
767 
768   tBTA_HF_CLIENT_DATA p_data;
769   p_data.hdr.layer_specific = client_cb->handle;
770   bta_hf_client_sco_listen(&p_data);
771   bta_hf_client_send_at_bia(client_cb);
772   bta_hf_client_send_at_ccwa(client_cb, true);
773   bta_hf_client_send_at_cmee(client_cb, true);
774   bta_hf_client_send_at_cops(client_cb, false);
775   bta_hf_client_send_at_btrh(client_cb, true, 0);
776   bta_hf_client_send_at_clip(client_cb, true);
777 }
778 
779 /*******************************************************************************
780  *
781  * Function         bta_hf_client_slc_seq
782  *
783  * Description      Handles AT commands sequence required for SLC creation
784  *
785  *
786  * Returns          void
787  *
788  ******************************************************************************/
bta_hf_client_slc_seq(tBTA_HF_CLIENT_CB * client_cb,bool error)789 void bta_hf_client_slc_seq(tBTA_HF_CLIENT_CB* client_cb, bool error) {
790   APPL_TRACE_DEBUG("bta_hf_client_slc_seq cmd: %u",
791                    client_cb->at_cb.current_cmd);
792 
793   if (error) {
794     /* SLC establishment error, sent close rfcomm event */
795     APPL_TRACE_ERROR(
796         "HFPClient: Failed to create SLC due to AT error, disconnecting (%u)",
797         client_cb->at_cb.current_cmd);
798 
799     tBTA_HF_CLIENT_DATA msg;
800     msg.hdr.layer_specific = client_cb->handle;
801     bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, &msg);
802     return;
803   }
804 
805   if (client_cb->svc_conn) {
806     APPL_TRACE_WARNING("%s: SLC already connected for CB handle %d", __func__,
807                        client_cb->handle);
808     return;
809   }
810 
811   switch (client_cb->at_cb.current_cmd) {
812     case BTA_HF_CLIENT_AT_NONE:
813       bta_hf_client_send_at_brsf(client_cb, bta_hf_client_cb_arr.features);
814       break;
815 
816     case BTA_HF_CLIENT_AT_BRSF:
817       if ((bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_CODEC) &&
818           (client_cb->peer_features & BTA_HF_CLIENT_PEER_CODEC)) {
819         bta_hf_client_send_at_bac(client_cb);
820         break;
821       }
822 
823       bta_hf_client_send_at_cind(client_cb, false);
824       break;
825 
826     case BTA_HF_CLIENT_AT_BAC:
827       bta_hf_client_send_at_cind(client_cb, false);
828       break;
829 
830     case BTA_HF_CLIENT_AT_CIND:
831       bta_hf_client_send_at_cind(client_cb, true);
832       break;
833 
834     case BTA_HF_CLIENT_AT_CIND_STATUS:
835       bta_hf_client_send_at_cmer(client_cb, true);
836       break;
837 
838     case BTA_HF_CLIENT_AT_CMER:
839       if (client_cb->peer_features & BTA_HF_CLIENT_PEER_FEAT_3WAY &&
840           bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_3WAY) {
841         bta_hf_client_send_at_chld(client_cb, '?', 0);
842       } else if (bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_HF_IND &&
843                  client_cb->peer_features & BTA_HF_CLIENT_PEER_HF_IND) {
844         bta_hf_client_send_at_bind(client_cb, 0);
845       } else {
846         tBTA_HF_CLIENT_DATA msg;
847         msg.hdr.layer_specific = client_cb->handle;
848         bta_hf_client_svc_conn_open(&msg);
849         send_post_slc_cmd(client_cb);
850       }
851       break;
852 
853     case BTA_HF_CLIENT_AT_CHLD:
854       if (bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_HF_IND &&
855           client_cb->peer_features & BTA_HF_CLIENT_PEER_HF_IND) {
856         bta_hf_client_send_at_bind(client_cb, 0);
857       } else {
858         tBTA_HF_CLIENT_DATA msg;
859         msg.hdr.layer_specific = client_cb->handle;
860         bta_hf_client_svc_conn_open(&msg);
861         send_post_slc_cmd(client_cb);
862       }
863       break;
864 
865     case BTA_HF_CLIENT_AT_BIND_SET_IND:
866       bta_hf_client_send_at_bind(client_cb, 1);
867       break;
868 
869     case BTA_HF_CLIENT_AT_BIND_READ_SUPPORTED_IND:
870       bta_hf_client_send_at_bind(client_cb, 2);
871       break;
872 
873     case BTA_HF_CLIENT_AT_BIND_READ_ENABLED_IND:
874       tBTA_HF_CLIENT_DATA msg;
875       msg.hdr.layer_specific = client_cb->handle;
876       bta_hf_client_svc_conn_open(&msg);
877       send_post_slc_cmd(client_cb);
878       break;
879 
880     default: {
881       /* If happen there is a bug in SLC creation procedure... */
882       APPL_TRACE_ERROR(
883           "HFPClient: Failed to create SLCdue to unexpected AT command, "
884           "disconnecting (%u)",
885           client_cb->at_cb.current_cmd);
886 
887       tBTA_HF_CLIENT_DATA msg;
888       msg.hdr.layer_specific = client_cb->handle;
889       bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, &msg);
890       break;
891     }
892   }
893 }
894 
895 #ifndef CASE_RETURN_STR
896 #define CASE_RETURN_STR(const) \
897   case const:                  \
898     return #const;
899 #endif
900 
bta_hf_client_evt_str(uint16_t event)901 static const char* bta_hf_client_evt_str(uint16_t event) {
902   switch (event) {
903     CASE_RETURN_STR(BTA_HF_CLIENT_API_OPEN_EVT)
904     CASE_RETURN_STR(BTA_HF_CLIENT_API_CLOSE_EVT)
905     CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_OPEN_EVT)
906     CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT)
907     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_OPEN_EVT)
908     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_CLOSE_EVT)
909     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT)
910     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_DATA_EVT)
911     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_ACP_RES_EVT)
912     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_INT_RES_EVT)
913     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_OK_EVT)
914     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_FAIL_EVT)
915     CASE_RETURN_STR(BTA_HF_CLIENT_API_ENABLE_EVT)
916     CASE_RETURN_STR(BTA_HF_CLIENT_API_DISABLE_EVT)
917     CASE_RETURN_STR(BTA_HF_CLIENT_SCO_OPEN_EVT)
918     CASE_RETURN_STR(BTA_HF_CLIENT_SCO_CLOSE_EVT)
919     CASE_RETURN_STR(BTA_HF_CLIENT_SEND_AT_CMD_EVT)
920     default:
921       return "Unknown HF Client Event";
922   }
923 }
924 
bta_hf_client_state_str(uint8_t state)925 static const char* bta_hf_client_state_str(uint8_t state) {
926   switch (state) {
927     CASE_RETURN_STR(BTA_HF_CLIENT_INIT_ST)
928     CASE_RETURN_STR(BTA_HF_CLIENT_OPENING_ST)
929     CASE_RETURN_STR(BTA_HF_CLIENT_OPEN_ST)
930     CASE_RETURN_STR(BTA_HF_CLIENT_CLOSING_ST)
931     default:
932       return "Unknown HF Client State";
933   }
934 }
935 
bta_hf_client_dump_statistics(int fd)936 void bta_hf_client_dump_statistics(int fd) {
937   dprintf(fd, "\nBluetooth HF Client BTA Statistics\n");
938 
939   // We dump statistics for all control blocks
940   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
941     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
942     if (!client_cb->is_allocated) {
943       // Skip the blocks which are not allocated
944       continue;
945     }
946 
947     dprintf(fd, "  Control block #%d\n", i + 1);
948 
949     uint8_t* a = client_cb->peer_addr.address;
950     // Device name
951     dprintf(fd, "    Peer Device: %02x:%02x:%02x:%02x:%02x:%02x\n", a[0], a[1],
952             a[2], a[3], a[4], a[5]);
953 
954     // State machine state
955     dprintf(fd, "    State Machine State: %s\n",
956             bta_hf_client_state_str(client_cb->state));
957 
958     // Local RFC channelfor communication
959     dprintf(fd, "    RFCOMM Channel (local) %d\n", client_cb->conn_handle);
960 
961     // BTA Handle shared between BTA and client (ex BTIF)
962     dprintf(fd, "    BTA Generated handle %d\n", client_cb->handle);
963   }
964 }
965