1 /*
2  * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /******************************************************************************
8  **
9  **  Name:          btc_hf_client.c
10  **
11  ******************************************************************************/
12 #include "common/bt_target.h"
13 #include "common/bt_trace.h"
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include "common/bt_defs.h"
19 #include "device/bdaddr.h"
20 #include "btc/btc_dm.h"
21 #include "btc_hf_client.h"
22 #include "btc/btc_profile_queue.h"
23 #include "osi/allocator.h"
24 #include "btc/btc_manage.h"
25 #include "btc/btc_util.h"
26 #include "esp_hf_client_api.h"
27 #include "bta/bta_hf_client_api.h"
28 #include "esp_bt.h"
29 #include <assert.h>
30 
31 #if BT_HF_CLIENT_BQB_INCLUDED
32 static BOOLEAN s_bta_hf_client_bqb_esco_s4_flag = false;
33 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
34 
35 #if (BTC_HF_CLIENT_INCLUDED == TRUE)
36 
37 /************************************************************************************
38 **  Constants & Macros
39 ************************************************************************************/
40 
41 #ifndef BTC_HF_CLIENT_SERVICE_NAME
42 #define BTC_HF_CLIENT_SERVICE_NAME ("Handsfree")
43 #endif
44 
45 #ifndef BTC_HF_CLIENT_SECURITY
46 #define BTC_HF_CLIENT_SECURITY    (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
47 #endif
48 
49 #ifndef BTC_HF_CLIENT_FEATURES
50 #define BTC_HF_CLIENT_FEATURES   ( BTA_HF_CLIENT_FEAT_ECNR    | \
51                                     BTA_HF_CLIENT_FEAT_3WAY   | \
52                                     BTA_HF_CLIENT_FEAT_CLI    | \
53                                     BTA_HF_CLIENT_FEAT_VREC   | \
54                                     BTA_HF_CLIENT_FEAT_VOL    | \
55                                     BTA_HF_CLIENT_FEAT_ECS    | \
56                                     BTA_HF_CLIENT_FEAT_ECC    | \
57                                     BTA_HF_CLIENT_FEAT_CODEC)
58 #endif
59 
60 
61 /*******************************************************************************
62 **
63 ** Function     bta_hf_client_bqb_esco_s4_ctrl
64 **
65 ** Description  Control the usage of BTA_HF_CLIENT_FEAT_ESCO_S4 for BQB test
66 **
67 ** Returns      void
68 **
69 *******************************************************************************/
70 #if BT_HF_CLIENT_BQB_INCLUDED
bta_hf_client_bqb_esco_s4_ctrl(BOOLEAN enable)71 void bta_hf_client_bqb_esco_s4_ctrl(BOOLEAN enable)
72 {
73     s_bta_hf_client_bqb_esco_s4_flag = enable;
74 }
75 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
76 
77 /************************************************************************************
78 **  Static variables
79 ************************************************************************************/
80 const int btc_hf_client_version = HFP_HF_VERSION_1_7;
81 
82 #if HFP_DYNAMIC_MEMORY == FALSE
83 static hf_client_local_param_t hf_client_local_param;
84 #else
85 hf_client_local_param_t *hf_client_local_param_ptr;
86 #endif
87 
88 /************************************************************************************
89 **  Static functions
90 ************************************************************************************/
91 #define CHECK_HF_CLIENT_INIT() do { \
92 if (! hf_client_local_param.btc_hf_client_cb.initialized) { \
93     return BT_STATUS_NOT_READY; \
94 } \
95 } while (0)
96 
97 #define CHECK_HF_CLIENT_SLC_CONNECTED() do { \
98 if (! hf_client_local_param.btc_hf_client_cb.initialized || \
99     hf_client_local_param.btc_hf_client_cb.state != ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { \
100     return BT_STATUS_NOT_READY; \
101 } \
102 } while (0)
103 
btc_hf_client_cb_to_app(esp_hf_client_cb_event_t event,esp_hf_client_cb_param_t * param)104 static inline void btc_hf_client_cb_to_app(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param)
105 {
106     esp_hf_client_cb_t btc_hf_client_callback = (esp_hf_client_cb_t)btc_profile_cb_get(BTC_PID_HF_CLIENT);
107     if (btc_hf_client_callback) {
108         btc_hf_client_callback(event, param);
109     }
110 }
111 
clear_state(void)112 static void clear_state(void)
113 {
114     memset(&hf_client_local_param.btc_hf_client_cb, 0, sizeof(btc_hf_client_cb_t));
115 }
116 
is_connected(bt_bdaddr_t * bd_addr)117 static BOOLEAN is_connected(bt_bdaddr_t *bd_addr)
118 {
119     if (((hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_CONNECTED) ||
120             (hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED))&&
121         ((bd_addr == NULL) || (bdcmp(bd_addr->address, hf_client_local_param.btc_hf_client_cb.connected_bda.address) == 0)))
122         return TRUE;
123     return FALSE;
124 }
125 
btc_hf_client_reg_data_cb(esp_hf_client_incoming_data_cb_t recv,esp_hf_client_outgoing_data_cb_t send)126 void btc_hf_client_reg_data_cb(esp_hf_client_incoming_data_cb_t recv,
127                                esp_hf_client_outgoing_data_cb_t send)
128 {
129     hf_client_local_param.btc_hf_client_incoming_data_cb = recv;
130     hf_client_local_param.btc_hf_client_outgoing_data_cb = send;
131 }
132 
btc_hf_client_incoming_data_cb_to_app(const uint8_t * data,uint32_t len)133 void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len)
134 {
135     // todo: critical section protection
136     if (hf_client_local_param.btc_hf_client_incoming_data_cb) {
137         hf_client_local_param.btc_hf_client_incoming_data_cb(data, len);
138     }
139 }
140 
btc_hf_client_outgoing_data_cb_to_app(uint8_t * data,uint32_t len)141 uint32_t btc_hf_client_outgoing_data_cb_to_app(uint8_t *data, uint32_t len)
142 {
143     // todo: critical section protection
144     if (hf_client_local_param.btc_hf_client_outgoing_data_cb) {
145         return hf_client_local_param.btc_hf_client_outgoing_data_cb(data, len);
146     } else {
147         return 0;
148     }
149 }
150 
151 /*****************************************************************************
152 **
153 **   btc hf api functions
154 **
155 *****************************************************************************/
156 
157 /*******************************************************************************
158 **
159 ** Function        btc_hf_client_init
160 **
161 ** Description     initializes the hf interface
162 **
163 ** Returns         bt_status_t
164 **
165 *******************************************************************************/
btc_hf_client_init(void)166 bt_status_t btc_hf_client_init(void)
167 {
168     BTC_TRACE_EVENT("%s", __FUNCTION__);
169 
170     uint8_t data_path;
171     if (hf_client_local_param.btc_hf_client_cb.initialized) {
172         esp_hf_client_cb_param_t param = {
173             .prof_stat.state = ESP_HF_INIT_ALREADY,
174         };
175         btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, &param);
176         return BT_STATUS_SUCCESS;
177     }
178 
179     btc_dm_enable_service(BTA_HFP_HS_SERVICE_ID);
180 
181     clear_state();
182 
183 #if BTM_SCO_HCI_INCLUDED
184     data_path = ESP_SCO_DATA_PATH_HCI;
185 #else
186     data_path = ESP_SCO_DATA_PATH_PCM;
187 #endif
188     esp_bredr_sco_datapath_set(data_path);
189     return BT_STATUS_SUCCESS;
190 }
191 
192 
193 /*******************************************************************************
194 **
195 ** Function        btc_hf_client_connect
196 **
197 ** Description     connect to audio gateway
198 **
199 ** Returns         bt_status_t
200 **
201 *******************************************************************************/
connect_int(bt_bdaddr_t * bd_addr,uint16_t uuid)202 static bt_status_t connect_int( bt_bdaddr_t *bd_addr, uint16_t uuid )
203 {
204     if (is_connected(bd_addr)) {
205         return BT_STATUS_BUSY;
206     }
207 
208     hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_CONNECTING;
209     bdcpy(hf_client_local_param.btc_hf_client_cb.connected_bda.address, bd_addr->address);
210 
211     BTA_HfClientOpen(hf_client_local_param.btc_hf_client_cb.handle, hf_client_local_param.btc_hf_client_cb.connected_bda.address,
212                BTC_HF_CLIENT_SECURITY);
213 
214     return BT_STATUS_SUCCESS;
215 }
216 
217 
btc_hf_client_connect(bt_bdaddr_t * bd_addr)218 bt_status_t btc_hf_client_connect( bt_bdaddr_t *bd_addr )
219 {
220     BTC_TRACE_EVENT("HFP Client version is  0x%04x", btc_hf_client_version);
221     CHECK_HF_CLIENT_INIT();
222     return btc_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int);
223 }
224 
225 /*******************************************************************************
226 **
227 ** Function         btc_hf_client_deinit
228 **
229 ** Description      Closes the HF interface
230 **
231 ** Returns          bt_status_t
232 **
233 *******************************************************************************/
btc_hf_client_deinit(void)234 void  btc_hf_client_deinit( void )
235 {
236     BTC_TRACE_EVENT("%s", __FUNCTION__);
237 
238     if (!hf_client_local_param.btc_hf_client_cb.initialized) {
239         esp_hf_client_cb_param_t param = {
240             .prof_stat.state = ESP_HF_DEINIT_ALREADY,
241         };
242         btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, &param);
243         return;
244     }
245 
246     btc_dm_disable_service(BTA_HFP_HS_SERVICE_ID);
247 }
248 
249 /*******************************************************************************
250 **
251 ** Function         btc_hf_client_disconnect
252 **
253 ** Description      disconnect from audio gateway
254 **
255 ** Returns         bt_status_t
256 **
257 *******************************************************************************/
btc_hf_client_disconnect(bt_bdaddr_t * bd_addr)258 bt_status_t btc_hf_client_disconnect( bt_bdaddr_t *bd_addr )
259 {
260     CHECK_HF_CLIENT_INIT();
261 
262     if (is_connected(bd_addr))
263     {
264         BTA_HfClientClose(hf_client_local_param.btc_hf_client_cb.handle);
265         return BT_STATUS_SUCCESS;
266     }
267 
268     return BT_STATUS_FAIL;
269 }
270 
271 /*******************************************************************************
272 **
273 ** Function        btc_hf_client_connect_audio
274 **
275 ** Description     create an audio connection
276 **
277 ** Returns         bt_status_t
278 **
279 *******************************************************************************/
btc_hf_client_connect_audio(bt_bdaddr_t * bd_addr)280 bt_status_t btc_hf_client_connect_audio( bt_bdaddr_t *bd_addr )
281 {
282     CHECK_HF_CLIENT_SLC_CONNECTED();
283 
284     if (is_connected(bd_addr))
285     {
286         if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_CODEC)
287         {
288             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BCC, 0, 0, NULL);
289         }
290         else
291         {
292             BTA_HfClientAudioOpen(hf_client_local_param.btc_hf_client_cb.handle);
293         }
294 
295         /* Inform the application that the audio connection has been initiated successfully */
296         do {
297             esp_hf_client_cb_param_t param;
298             memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
299             param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTING;
300             memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, sizeof(esp_bd_addr_t));
301             btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
302         } while (0);
303 
304         return BT_STATUS_SUCCESS;
305     }
306 
307     return BT_STATUS_FAIL;
308 }
309 
310 /*******************************************************************************
311 **
312 ** Function         btc_hf_client_disconnect_audio
313 **
314 ** Description      close the audio connection
315 **
316 ** Returns         bt_status_t
317 **
318 *******************************************************************************/
btc_hf_client_disconnect_audio(bt_bdaddr_t * bd_addr)319 bt_status_t btc_hf_client_disconnect_audio( bt_bdaddr_t *bd_addr )
320 {
321     CHECK_HF_CLIENT_SLC_CONNECTED();
322 
323     if (is_connected(bd_addr))
324     {
325         BTA_HfClientAudioClose(hf_client_local_param.btc_hf_client_cb.handle);
326         return BT_STATUS_SUCCESS;
327     }
328 
329     return BT_STATUS_FAIL;
330 }
331 
332 /*******************************************************************************
333 **
334 ** Function         btc_hf_client_start_voice_recognition
335 **
336 ** Description      start voice recognition
337 **
338 ** Returns          bt_status_t
339 **
340 *******************************************************************************/
btc_hf_client_start_voice_recognition(void)341 static bt_status_t btc_hf_client_start_voice_recognition(void)
342 {
343     CHECK_HF_CLIENT_SLC_CONNECTED();
344 
345     if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC)
346     {
347         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BVRA, 1, 0, NULL);
348 
349         return BT_STATUS_SUCCESS;
350     }
351 
352     return BT_STATUS_UNSUPPORTED;
353 }
354 
355 
356 /*******************************************************************************
357 **
358 ** Function         btc_hf_client_stop_voice_recognition
359 **
360 ** Description      stop voice recognition
361 **
362 ** Returns          bt_status_t
363 **
364 *******************************************************************************/
btc_hf_client_stop_voice_recognition(void)365 static bt_status_t btc_hf_client_stop_voice_recognition(void)
366 {
367     CHECK_HF_CLIENT_SLC_CONNECTED();
368 
369     if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC)
370     {
371         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BVRA, 0, 0, NULL);
372 
373         return BT_STATUS_SUCCESS;
374     }
375 
376     return BT_STATUS_UNSUPPORTED;
377 }
378 
379 /*******************************************************************************
380 **
381 ** Function         btc_hf_client_volume_update
382 **
383 ** Description      volume update
384 **
385 ** Returns          bt_status_t
386 **
387 *******************************************************************************/
btc_hf_client_volume_update(esp_hf_volume_control_target_t type,int volume)388 static bt_status_t btc_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume)
389 {
390     CHECK_HF_CLIENT_SLC_CONNECTED();
391 
392     switch (type)
393     {
394         case ESP_HF_VOLUME_CONTROL_TARGET_SPK:
395             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_VGS, volume, 0, NULL);
396             break;
397         case ESP_HF_VOLUME_CONTROL_TARGET_MIC:
398             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_VGM, volume, 0, NULL);
399             break;
400         default:
401             return BT_STATUS_UNSUPPORTED;
402     }
403 
404     return BT_STATUS_SUCCESS;
405 }
406 
407 /*******************************************************************************
408 **
409 ** Function         btc_hf_client_dial
410 **
411 ** Description      place a call
412 **
413 ** Returns          bt_status_t
414 **
415 *******************************************************************************/
btc_hf_client_dial(const char * number)416 static bt_status_t btc_hf_client_dial(const char *number)
417 {
418     CHECK_HF_CLIENT_SLC_CONNECTED();
419 
420     if (strlen(number) != 0)
421     {
422         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATD, 0, 0, number);
423     }
424     else
425     {
426         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BLDN, 0, 0, NULL);
427     }
428 
429     return BT_STATUS_SUCCESS;
430 }
431 
432 /*******************************************************************************
433 **
434 ** Function         dial_memory
435 **
436 ** Description      place a call with number specified by location (speed dial)
437 **
438 ** Returns          bt_status_t
439 **
440 *******************************************************************************/
btc_hf_client_dial_memory(int location)441 static bt_status_t btc_hf_client_dial_memory(int location)
442 {
443     CHECK_HF_CLIENT_SLC_CONNECTED();
444 
445     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATD, location, 0, NULL);
446 
447     return BT_STATUS_SUCCESS;
448 }
449 
btc_hf_client_send_chld_cmd(esp_hf_chld_type_t type,int idx)450 static bt_status_t btc_hf_client_send_chld_cmd(esp_hf_chld_type_t type, int idx)
451 {
452     CHECK_HF_CLIENT_SLC_CONNECTED();
453 
454     switch (type)
455     {
456     case ESP_HF_CHLD_TYPE_REL:
457         if (hf_client_local_param.btc_hf_client_cb.chld_feat & BTA_HF_CLIENT_CHLD_REL)
458         {
459             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 0, 0, NULL);
460             break;
461         }
462         return BT_STATUS_UNSUPPORTED;
463     case ESP_HF_CHLD_TYPE_REL_ACC:
464         // CHLD 1 is mandatory for 3 way calling
465         if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY)
466         {
467             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, 0, NULL);
468             break;
469         }
470         return BT_STATUS_UNSUPPORTED;
471     case ESP_HF_CHLD_TYPE_HOLD_ACC:
472         // CHLD 2 is mandatory for 3 way calling
473         if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY)
474         {
475             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, 0, NULL);
476             break;
477         }
478         return BT_STATUS_UNSUPPORTED;
479     case ESP_HF_CHLD_TYPE_MERGE:
480         if (hf_client_local_param.btc_hf_client_cb.chld_feat & BTA_HF_CLIENT_CHLD_MERGE)
481         {
482             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 3, 0, NULL);
483             break;
484         }
485         return BT_STATUS_UNSUPPORTED;
486     case ESP_HF_CHLD_TYPE_MERGE_DETACH:
487         if (hf_client_local_param.btc_hf_client_cb.chld_feat & BTA_HF_CLIENT_CHLD_MERGE_DETACH)
488         {
489             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 4, 0, NULL);
490             break;
491         }
492         return BT_STATUS_UNSUPPORTED;
493     case ESP_HF_CHLD_TYPE_REL_X:
494         if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_ECC)
495         {
496             if (idx < 1)
497             {
498                 return BT_STATUS_FAIL;
499             }
500             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, idx, NULL);
501             break;
502         }
503         return BT_STATUS_UNSUPPORTED;
504     case ESP_HF_CHLD_TYPE_PRIV_X:
505         if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_ECC)
506         {
507             if (idx < 1)
508             {
509                 return BT_STATUS_FAIL;
510             }
511             BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, idx, NULL);
512             break;
513         }
514         return BT_STATUS_UNSUPPORTED;
515 
516     }
517     return BT_STATUS_SUCCESS;
518 }
519 
btc_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh)520 static bt_status_t btc_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh)
521 {
522     CHECK_HF_CLIENT_SLC_CONNECTED();
523 
524     switch (btrh) {
525     case ESP_HF_BTRH_CMD_HOLD:
526         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BTRH, 0, 0, NULL);
527         break;
528     case ESP_HF_BTRH_CMD_ACCEPT:
529         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BTRH, 1, 0, NULL);
530         break;
531     case ESP_HF_BTRH_CMD_REJECT:
532         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BTRH, 2, 0, NULL);
533         break;
534     default:
535         return BT_STATUS_FAIL;
536     }
537 
538     return BT_STATUS_SUCCESS;
539 }
540 
btc_hf_client_answer_call(void)541 static bt_status_t btc_hf_client_answer_call(void)
542 {
543     CHECK_HF_CLIENT_SLC_CONNECTED();
544     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATA, 0, 0, NULL);
545     return BT_STATUS_SUCCESS;
546 }
547 
btc_hf_client_reject_call(void)548 static bt_status_t btc_hf_client_reject_call(void)
549 {
550     CHECK_HF_CLIENT_SLC_CONNECTED();
551     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHUP, 0, 0, NULL);
552     return BT_STATUS_SUCCESS;
553 }
554 
555 /*******************************************************************************
556 **
557 ** Function         btc_hf_client_query_current_calls
558 **
559 ** Description      query list of current calls
560 **
561 ** Returns          bt_status_t
562 **
563 *******************************************************************************/
btc_hf_client_query_current_calls(void)564 static bt_status_t btc_hf_client_query_current_calls(void)
565 {
566     CHECK_HF_CLIENT_SLC_CONNECTED();
567 
568     if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_ECS)
569     {
570         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CLCC, 0, 0, NULL);
571 
572         return BT_STATUS_SUCCESS;
573     }
574 
575     return BT_STATUS_UNSUPPORTED;
576 }
577 
578 /*******************************************************************************
579 **
580 ** Function         btc_hf_client_query_current_operator_name
581 **
582 ** Description      query current selected operator name
583 **
584 ** Returns          bt_status_t
585 **
586 *******************************************************************************/
btc_hf_client_query_current_operator_name(void)587 static bt_status_t btc_hf_client_query_current_operator_name(void)
588 {
589     CHECK_HF_CLIENT_SLC_CONNECTED();
590 
591     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_COPS, 0, 0, NULL);
592 
593     return BT_STATUS_SUCCESS;
594 }
595 
596 /*******************************************************************************
597 **
598 ** Function         btc_hf_client_retieve_subscriber_info
599 **
600 ** Description      retrieve subscriber number information
601 **
602 ** Returns          bt_status_t
603 **
604 *******************************************************************************/
btc_hf_client_retrieve_subscriber_info(void)605 static bt_status_t btc_hf_client_retrieve_subscriber_info(void)
606 {
607     CHECK_HF_CLIENT_SLC_CONNECTED();
608 
609     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CNUM, 0, 0, NULL);
610 
611     return BT_STATUS_SUCCESS;
612 }
613 
614 /*******************************************************************************
615 **
616 ** Function         btc_hf_client_send_dtmf
617 **
618 ** Description      send dtmf
619 **
620 ** Returns          bt_status_t
621 **
622 *******************************************************************************/
btc_hf_client_send_dtmf(char code)623 static bt_status_t btc_hf_client_send_dtmf(char code)
624 {
625     CHECK_HF_CLIENT_SLC_CONNECTED();
626 
627     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_VTS, code, 0, NULL);
628 
629     return BT_STATUS_SUCCESS;
630 }
631 
632 /*******************************************************************************
633 **
634 ** Function         btc_hf_client_send_xapl
635 **
636 ** Description      send xapl
637 **
638 ** Returns          bt_status_t
639 **
640 *******************************************************************************/
btc_hf_client_send_xapl(char * buf,UINT32 features)641 static bt_status_t btc_hf_client_send_xapl(char *buf, UINT32 features)
642 {
643     CHECK_HF_CLIENT_SLC_CONNECTED();
644 
645     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_XAPL, features, 0, buf);
646 
647     return BT_STATUS_SUCCESS;
648 }
649 
650 /*******************************************************************************
651 **
652 ** Function         btc_hf_client_send_iphoneaccev
653 **
654 ** Description      send IPHONEACCEV
655 **
656 ** Returns          bt_status_t
657 **
658 *******************************************************************************/
btc_hf_client_send_iphoneaccev(uint32_t bat_level,BOOLEAN docked)659 static bt_status_t btc_hf_client_send_iphoneaccev(uint32_t bat_level, BOOLEAN docked)
660 {
661     CHECK_HF_CLIENT_SLC_CONNECTED();
662 
663     BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_IPHONEACCEV, bat_level, (UINT32)docked, NULL);
664 
665     return BT_STATUS_SUCCESS;
666 }
667 /*******************************************************************************
668 **
669 ** Function         btc_hf_client_request_last_voice_tag_number
670 **
671 ** Description      Request number from AG for VR purposes
672 **
673 ** Returns          bt_status_t
674 **
675 *******************************************************************************/
btc_hf_client_request_last_voice_tag_number(void)676 static bt_status_t btc_hf_client_request_last_voice_tag_number(void)
677 {
678     CHECK_HF_CLIENT_SLC_CONNECTED();
679 
680     if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_VTAG)
681     {
682         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BINP, 1, 0, NULL);
683 
684         return BT_STATUS_SUCCESS;
685     }
686 
687     return BT_STATUS_UNSUPPORTED;
688 }
689 
690 /*******************************************************************************
691 **
692 ** Function         btc_hf_client_send_nrec
693 **
694 ** Description      Request AG to disable echo cancellation & noise reduction
695 **
696 ** Returns          bt_status_t
697 **
698 *******************************************************************************/
btc_hf_client_send_nrec(void)699 static bt_status_t btc_hf_client_send_nrec(void)
700 {
701     CHECK_HF_CLIENT_SLC_CONNECTED();
702 
703     if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_ECNR)
704     {
705         BTA_HfClientSendAT(hf_client_local_param.btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_NREC, 0, 0, NULL);
706         return BT_STATUS_SUCCESS;
707     }
708     return BT_STATUS_UNSUPPORTED;
709 }
710 
711 /*******************************************************************************
712 **
713 ** Function         btc_hf_client_pkt_stat_nums_get;
714 **
715 ** Description      Request packet status numbers for a specific (e)SCO connection handle
716 **
717 ** Returns          bt_status_t
718 **
719 *******************************************************************************/
btc_hf_client_pkt_stat_nums_get(UINT16 sync_conn_handle)720 static bt_status_t btc_hf_client_pkt_stat_nums_get(UINT16 sync_conn_handle)
721 {
722     CHECK_HF_CLIENT_SLC_CONNECTED();
723 #if (BTM_SCO_HCI_INCLUDED == TRUE)
724     BTA_HfClientPktStatsNumsGet(sync_conn_handle);
725 #endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE) */
726     return BT_STATUS_SUCCESS;
727 }
728 
729 /*******************************************************************************
730 **
731 ** Function         bte_hf_client_evt
732 **
733 ** Description      Switches context from BTE to BTIF for all HF Client events
734 **
735 ** Returns          void
736 **
737 *******************************************************************************/
bte_hf_client_evt(tBTA_HF_CLIENT_EVT event,void * p_data)738 static void bte_hf_client_evt(tBTA_HF_CLIENT_EVT event, void *p_data)
739 {
740     bt_status_t stat;
741     btc_msg_t msg;
742     int arg_len = BTA_HfClientGetCbDataSize(event);
743     void *arg = (p_data != NULL && arg_len > 0) ? p_data : NULL;
744 
745     msg.sig = BTC_SIG_API_CB;
746     msg.pid = BTC_PID_HF_CLIENT;
747     msg.act = (uint8_t) event;
748 
749     stat = btc_transfer_context(&msg, arg, arg_len, NULL, NULL);
750 
751     if (stat) {
752         BTC_TRACE_ERROR("%s transfer failed\n", __func__);
753     }
754 }
755 
756 /*******************************************************************************
757 **
758 ** Function         btc_hf_client_execute_service
759 **
760 ** Description      Initializes/Shuts down the service
761 **
762 ** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
763 **
764 *******************************************************************************/
btc_hf_client_execute_service(BOOLEAN b_enable)765 bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable)
766 {
767     BTC_TRACE_EVENT("%s enable:%d", __FUNCTION__, b_enable);
768 
769     if (b_enable)
770     {
771         /* Enable and register with BTA-HFClient */
772         BTA_HfClientEnable(bte_hf_client_evt);
773         hf_client_local_param.btc_hf_client_features = BTC_HF_CLIENT_FEATURES;
774         if (btc_hf_client_version >= HFP_HF_VERSION_1_7)
775         {
776             hf_client_local_param.btc_hf_client_features |= BTA_HF_CLIENT_FEAT_ESCO_S4;
777 #if BT_HF_CLIENT_BQB_INCLUDED
778         if (s_bta_hf_client_bqb_esco_s4_flag == true) {
779             hf_client_local_param.btc_hf_client_features = BTA_HF_CLIENT_FEAT_ESCO_S4;
780         }
781 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
782             BTC_TRACE_EVENT("eSCO S4 Setting Supported");
783 
784         }
785         else if (btc_hf_client_version >= HFP_HF_VERSION_1_6)
786         {
787             BTC_TRACE_EVENT("No eSCO S4 Setting Supported");
788         }
789         else
790         {
791             BTC_TRACE_EVENT("No Codec Nego Supported");
792             hf_client_local_param.btc_hf_client_features = hf_client_local_param.btc_hf_client_features & (~BTA_HF_CLIENT_FEAT_CODEC);
793         }
794         BTC_TRACE_EVENT("hf_client_local_param.btc_hf_client_features is   %d", hf_client_local_param.btc_hf_client_features);
795         BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, hf_client_local_param.btc_hf_client_features,
796                     BTC_HF_CLIENT_SERVICE_NAME);
797     }
798     else
799     {
800         BTA_HfClientDeregister(hf_client_local_param.btc_hf_client_cb.handle);
801         BTA_HfClientDisable();
802     }
803     return BT_STATUS_SUCCESS;
804 }
805 
process_ind_evt(tBTA_HF_CLIENT_IND * ind)806 static void process_ind_evt(tBTA_HF_CLIENT_IND *ind)
807 {
808     esp_hf_client_cb_param_t param;
809     memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
810 
811     switch (ind->type)
812     {
813         case BTA_HF_CLIENT_IND_CALL:
814             param.call.status = ind->value;
815             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_CALL_EVT, &param);
816             break;
817 
818         case BTA_HF_CLIENT_IND_CALLSETUP:
819             param.call_setup.status = ind->value;
820             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_CALL_SETUP_EVT, &param);
821             break;
822         case BTA_HF_CLIENT_IND_CALLHELD:
823             param.call_held.status = ind->value;
824             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_CALL_HELD_EVT, &param);
825             break;
826 
827         case BTA_HF_CLIENT_IND_SERVICE:
828             param.service_availability.status = ind->value;
829             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT, &param);
830             break;
831 
832         case BTA_HF_CLIENT_IND_SIGNAL:
833             param.signal_strength.value = ind->value;
834             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT, &param);
835             break;
836 
837         case BTA_HF_CLIENT_IND_ROAM:
838             param.roaming.status = ind->value;
839             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT, &param);
840             break;
841 
842         case BTA_HF_CLIENT_IND_BATTCH:
843             param.battery_level.value = ind->value;
844             btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT, &param);
845             break;
846 
847         default:
848             break;
849     }
850 }
851 
btc_hf_client_cb_handler(btc_msg_t * msg)852 void btc_hf_client_cb_handler(btc_msg_t *msg)
853 {
854     uint16_t event = msg->act;
855     tBTA_HF_CLIENT *p_data = (tBTA_HF_CLIENT *)msg->arg;
856     esp_hf_client_cb_param_t param;
857     bdstr_t bdstr;
858 
859     memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
860 
861     switch (event)
862     {
863         case BTA_HF_CLIENT_ENABLE_EVT:
864             break;
865         case BTA_HF_CLIENT_DISABLE_EVT:
866             if (hf_client_local_param.btc_hf_client_cb.initialized) {
867                 param.prof_stat.state = ESP_HF_DEINIT_SUCCESS,
868                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, &param);
869             }
870             hf_client_local_param.btc_hf_client_cb.initialized = false;
871             break;
872         case BTA_HF_CLIENT_REGISTER_EVT:
873             hf_client_local_param.btc_hf_client_cb.handle = p_data->reg.handle;
874             if (!hf_client_local_param.btc_hf_client_cb.initialized) {
875                 param.prof_stat.state = ESP_HF_INIT_SUCCESS,
876                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, &param);
877             }
878             hf_client_local_param.btc_hf_client_cb.initialized = true;
879             break;
880         case BTA_HF_CLIENT_OPEN_EVT:
881             if (p_data->open.status == BTA_HF_CLIENT_SUCCESS)
882             {
883                 bdcpy(hf_client_local_param.btc_hf_client_cb.connected_bda.address, p_data->open.bd_addr);
884                 hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_CONNECTED;
885                 hf_client_local_param.btc_hf_client_cb.peer_feat = 0;
886                 hf_client_local_param.btc_hf_client_cb.chld_feat = 0;
887                 //clear_phone_state();
888             }
889             else if (hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_CONNECTING)
890             {
891                 hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED;
892             }
893             else
894             {
895                 BTC_TRACE_WARNING("%s: HF CLient open failed, but another device connected. status=%d state=%d connected device=%s",
896                         __FUNCTION__, p_data->open.status, hf_client_local_param.btc_hf_client_cb.state, bdaddr_to_string(&hf_client_local_param.btc_hf_client_cb.connected_bda, bdstr, sizeof(bdstr)));
897                 UNUSED(bdstr);
898                 break;
899             }
900 
901             do {
902                 param.conn_stat.state = hf_client_local_param.btc_hf_client_cb.state;
903                 param.conn_stat.peer_feat = 0;
904                 param.conn_stat.chld_feat = 0;
905 
906                 memcpy(param.conn_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
907                        sizeof(esp_bd_addr_t));
908 
909                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CONNECTION_STATE_EVT, &param);
910             } while (0);
911 
912             if (hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED)
913                 bdsetany(hf_client_local_param.btc_hf_client_cb.connected_bda.address);
914 
915             if (p_data->open.status != BTA_HF_CLIENT_SUCCESS) {
916                 btc_queue_advance();
917             }
918 
919             break;
920 
921         case BTA_HF_CLIENT_CONN_EVT:
922             hf_client_local_param.btc_hf_client_cb.peer_feat = p_data->conn.peer_feat;
923             hf_client_local_param.btc_hf_client_cb.chld_feat = p_data->conn.chld_feat;
924             hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED;
925 
926             do {
927                 param.conn_stat.state = hf_client_local_param.btc_hf_client_cb.state;
928                 param.conn_stat.peer_feat = hf_client_local_param.btc_hf_client_cb.peer_feat;
929                 param.conn_stat.chld_feat = hf_client_local_param.btc_hf_client_cb.chld_feat;
930 
931                 memcpy(param.conn_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
932                        sizeof(esp_bd_addr_t));
933 
934                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CONNECTION_STATE_EVT, &param);
935             } while (0);
936 
937             /* Inform the application about in-band ringtone */
938             if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_INBAND)
939             {
940                 do {
941                     param.bsir.state =  ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED;
942                     btc_hf_client_cb_to_app(ESP_HF_CLIENT_BSIR_EVT, &param);
943                 } while (0);
944             }
945 
946             btc_queue_advance();
947             break;
948 
949         case BTA_HF_CLIENT_CLOSE_EVT:
950             hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED;
951             do {
952                 param.conn_stat.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED;
953                 param.conn_stat.peer_feat = 0;
954                 param.conn_stat.chld_feat = 0;
955 
956                 memcpy(param.conn_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
957                        sizeof(esp_bd_addr_t));
958 
959                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CONNECTION_STATE_EVT, &param);
960             } while (0);
961 
962             bdsetany(hf_client_local_param.btc_hf_client_cb.connected_bda.address);
963             hf_client_local_param.btc_hf_client_cb.peer_feat = 0;
964             hf_client_local_param.btc_hf_client_cb.chld_feat = 0;
965             btc_queue_advance();
966             break;
967         case BTA_HF_CLIENT_IND_EVT:
968             process_ind_evt(&p_data->ind);
969             break;
970         case BTA_HF_CLIENT_MIC_EVT:
971             do {
972                 param.volume_control.type = ESP_HF_VOLUME_CONTROL_TARGET_MIC;
973                 param.volume_control.volume = p_data->val.value;
974 
975                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_VOLUME_CONTROL_EVT, &param);
976             } while (0);
977             break;
978         case BTA_HF_CLIENT_SPK_EVT:
979             do {
980                 param.volume_control.type = ESP_HF_VOLUME_CONTROL_TARGET_SPK;
981                 param.volume_control.volume = p_data->val.value;
982 
983                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_VOLUME_CONTROL_EVT, &param);
984             } while (0);
985             break;
986         case BTA_HF_CLIENT_VOICE_REC_EVT:
987             do {
988                 param.bvra.value = p_data->val.value;
989 
990                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_BVRA_EVT, &param);
991             } while (0);
992             break;
993         case BTA_HF_CLIENT_OPERATOR_NAME_EVT:
994             do {
995                 param.cops.name = p_data->operator.name;
996                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT, &param);
997             } while (0);
998             break;
999         case BTA_HF_CLIENT_CLIP_EVT:
1000             do {
1001                 param.clip.number = p_data->number.number;
1002                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CLIP_EVT, &param);
1003             } while (0);
1004             break;
1005         case BTA_HF_CLIENT_BINP_EVT:
1006             do {
1007                 param.binp.number = p_data->number.number;
1008                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_BINP_EVT, &param);
1009             } while (0);
1010             break;
1011         case BTA_HF_CLIENT_CCWA_EVT:
1012             do {
1013                 param.ccwa.number = p_data->number.number;
1014                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CCWA_EVT, &param);
1015             } while (0);
1016             break;
1017         case BTA_HF_CLIENT_AT_RESULT_EVT:
1018             do {
1019                 param.at_response.code = p_data->result.type;
1020                 param.at_response.cme = p_data->result.cme;
1021 
1022                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AT_RESPONSE_EVT, &param);
1023             } while (0);
1024             break;
1025         case BTA_HF_CLIENT_CLCC_EVT:
1026             do {
1027                 param.clcc.idx = p_data->clcc.idx;
1028                 param.clcc.dir = p_data->clcc.inc ? ESP_HF_CURRENT_CALL_DIRECTION_INCOMING :
1029                     ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING;
1030                 param.clcc.status = p_data->clcc.status;
1031                 param.clcc.mpty = p_data->clcc.mpty ? ESP_HF_CURRENT_CALL_MPTY_TYPE_MULTI :
1032                     ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE;
1033                 param.clcc.number = p_data->clcc.number_present ? p_data->clcc.number : NULL;
1034                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CLCC_EVT, &param);
1035             } while (0);
1036             break;
1037         case BTA_HF_CLIENT_CNUM_EVT:
1038             do {
1039                 param.cnum.number = p_data->cnum.number;
1040                 if (p_data->cnum.service == 4) {
1041                     param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE;
1042                 } else if (p_data->cnum.service == 5) {
1043                     param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX;
1044                 } else {
1045                     param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_UNKNOWN;
1046                 }
1047                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CNUM_EVT, &param);
1048                 break;
1049             } while (0);
1050             break;
1051         case BTA_HF_CLIENT_BTRH_EVT:
1052             if (p_data->val.value <= ESP_HF_BTRH_STATUS_REJECTED) {
1053                 do {
1054                     param.btrh.status = p_data->val.value;
1055 
1056                     btc_hf_client_cb_to_app(ESP_HF_CLIENT_BTRH_EVT, &param);
1057                 } while (0);
1058             }
1059             break;
1060         case BTA_HF_CLIENT_BSIR_EVT:
1061             if (p_data->val.value != 0)
1062             {
1063                 param.bsir.state = ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED;
1064             }
1065             else
1066             {
1067                 param.bsir.state = ESP_HF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED;
1068             }
1069             btc_hf_client_cb_to_app(ESP_HF_CLIENT_BSIR_EVT, &param);
1070             break;
1071         case BTA_HF_CLIENT_AUDIO_OPEN_EVT:
1072             do {
1073                 param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED;
1074                 memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
1075                        sizeof(esp_bd_addr_t));
1076                 param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
1077                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
1078             } while (0);
1079             break;
1080         case BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT:
1081             do {
1082                 param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC;
1083                 memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
1084                        sizeof(esp_bd_addr_t));
1085                 param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
1086                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
1087             } while (0);
1088             break;
1089         case BTA_HF_CLIENT_AUDIO_CLOSE_EVT:
1090             do {
1091                 param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
1092                 memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
1093                        sizeof(esp_bd_addr_t));
1094                 param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
1095                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
1096             } while (0);
1097             break;
1098         case BTA_HF_CLIENT_RING_INDICATION:
1099             do {
1100                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_RING_IND_EVT, NULL);
1101             } while (0);
1102             break;
1103         case BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT:
1104         {
1105             memcpy(&param.pkt_nums, &p_data->pkt_num, sizeof(struct hf_client_pkt_status_nums));
1106             btc_hf_client_cb_to_app(ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT, &param);
1107             break;
1108         }
1109         default:
1110             BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
1111             break;
1112     }
1113 }
1114 
btc_hf_client_call_handler(btc_msg_t * msg)1115 void btc_hf_client_call_handler(btc_msg_t *msg)
1116 {
1117     btc_hf_client_args_t *arg = (btc_hf_client_args_t *)(msg->arg);
1118     switch (msg->act) {
1119 
1120     case BTC_HF_CLIENT_INIT_EVT:
1121         btc_hf_client_init();
1122         break;
1123     case BTC_HF_CLIENT_DEINIT_EVT:
1124         btc_hf_client_deinit();
1125         break;
1126     case BTC_HF_CLIENT_CONNECT_EVT:
1127         btc_hf_client_connect(&arg->connect);
1128         break;
1129     case BTC_HF_CLIENT_DISCONNECT_EVT:
1130         btc_hf_client_disconnect(&arg->disconnect);
1131         break;
1132     case BTC_HF_CLIENT_CONNECT_AUDIO_EVT:
1133         btc_hf_client_connect_audio(&arg->connect_audio);
1134         break;
1135     case BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT:
1136         btc_hf_client_disconnect_audio(&arg->disconnect_audio);
1137         break;
1138     case BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT:
1139         btc_hf_client_start_voice_recognition();
1140         break;
1141     case BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT:
1142         btc_hf_client_stop_voice_recognition();
1143         break;
1144     case BTC_HF_CLIENT_VOLUME_UPDATE_EVT:
1145         btc_hf_client_volume_update(arg->volume_update.type, arg->volume_update.volume);
1146         break;
1147     case BTC_HF_CLIENT_DIAL_EVT:
1148         btc_hf_client_dial(arg->dial.number);
1149         break;
1150     case BTC_HF_CLIENT_DIAL_MEMORY_EVT:
1151         btc_hf_client_dial_memory(arg->dial_memory.location);
1152         break;
1153     case BTC_HF_CLIENT_SEND_CHLD_CMD_EVT:
1154         btc_hf_client_send_chld_cmd(arg->chld.type, arg->chld.idx);
1155         break;
1156     case BTC_HF_CLIENT_SEND_BTRH_CMD_EVT:
1157         btc_hf_client_send_btrh_cmd(arg->btrh.cmd);
1158         break;
1159     case BTC_HF_CLIENT_ANSWER_CALL_EVT:
1160         btc_hf_client_answer_call();
1161         break;
1162     case BTC_HF_CLIENT_REJECT_CALL_EVT:
1163         btc_hf_client_reject_call();
1164         break;
1165     case BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT:
1166         btc_hf_client_query_current_calls();
1167         break;
1168     case BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT:
1169         btc_hf_client_query_current_operator_name();
1170         break;
1171     case BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT:
1172         btc_hf_client_retrieve_subscriber_info();
1173         break;
1174     case BTC_HF_CLIENT_SEND_DTMF_EVT:
1175         btc_hf_client_send_dtmf(arg->send_dtmf.code);
1176         break;
1177     case BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT:
1178         btc_hf_client_request_last_voice_tag_number();
1179         break;
1180     case BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT:
1181         btc_hf_client_reg_data_cb(arg->reg_data_cb.recv, arg->reg_data_cb.send);
1182         break;
1183     case BTC_HF_CLIENT_SEND_NREC_EVT:
1184         btc_hf_client_send_nrec();
1185         break;
1186     case BTC_HF_CLIENT_SEND_XAPL_EVT:
1187         btc_hf_client_send_xapl(arg->send_xapl.information, arg->send_xapl.features);
1188         break;
1189     case BTC_HF_CLIENT_SEND_IPHONEACCEV_EVT:
1190         btc_hf_client_send_iphoneaccev(arg->send_iphoneaccev.bat_level, arg->send_iphoneaccev.docked);
1191         break;
1192     case BTC_HF_CLIENT_REQUEST_PKT_STAT_EVT:
1193         btc_hf_client_pkt_stat_nums_get(arg->pkt_sync_hd.sync_conn_handle);
1194         break;
1195     default:
1196         BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
1197     }
1198 }
1199 
1200 #endif /* #if (BTC_HF_CLIENT_INCLUDED == TRUE) */
1201