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