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