1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /************************************************************************************
20 *
21 * Filename: btc_hf.c
22 *
23 * Description: Handsfree Profile Bluetooth Interface
24 * *
25 ***********************************************************************************/
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 #include "time.h"
32 #include "btc/btc_dm.h"
33 #include "btc_hf_ag.h"
34 #include "btc/btc_profile_queue.h"
35 #include "btc/btc_manage.h"
36 #include "btc/btc_util.h"
37 #include "btc/btc_common.h"
38 #include "bta/bta_ag_api.h"
39 #include "bt_common.h"
40 #include "common/bt_target.h"
41 #include "common/bt_trace.h"
42 #include "common/bt_defs.h"
43 #include "device/bdaddr.h"
44 #include "esp_bt.h"
45 #include "esp_hf_ag_api.h"
46 #include "osi/allocator.h"
47
48
49 #if (BTC_HF_INCLUDED == TRUE)
50 /************************************************************************************
51 ** Constants & Macros
52 ************************************************************************************/
53 /* Max HF Clients Supported From App */
54 static UINT16 btc_max_hf_clients = 1;
55 /* HF Param Definition */
56 #if HFP_DYNAMIC_MEMORY == FALSE
57 static hf_local_param_t hf_local_param[BTC_HF_NUM_CB];
58 #else
59 static hf_local_param_t *hf_local_param;
60 #endif
61
62 #if (BTM_WBS_INCLUDED == TRUE)
63 #ifndef BTC_HF_FEATURES
64 #define BTC_HF_FEATURES ( BTA_AG_FEAT_ECNR | \
65 BTA_AG_FEAT_REJECT | \
66 BTA_AG_FEAT_ECS | \
67 BTA_AG_FEAT_EXTERR | \
68 BTA_AG_FEAT_VREC | \
69 BTA_AG_FEAT_INBAND | \
70 BTA_AG_FEAT_CODEC | \
71 BTA_AG_FEAT_UNAT)
72 #endif
73 #else
74 #ifndef BTC_HF_FEATURES
75 #define BTC_HF_FEATURES ( BTA_AG_FEAT_ECNR | \
76 BTA_AG_FEAT_REJECT | \
77 BTA_AG_FEAT_ECS | \
78 BTA_AG_FEAT_EXTERR | \
79 BTA_AG_FEAT_VREC | \
80 BTA_AG_FEAT_INBAND | \
81 BTA_AG_FEAT_UNAT)
82 #endif
83 #endif
84
85 /* wide band synchronous */
86 #ifndef BTC_HF_WBS_PREFERRED
87 #define BTC_HF_WBS_PREFERRED TRUE
88 #endif
89 BOOLEAN btc_conf_hf_force_wbs = BTC_HF_WBS_PREFERRED;
90
91 #define CHECK_HF_INIT() do { \
92 if (! hf_local_param[idx].btc_hf_cb.initialized) { \
93 BTIF_TRACE_WARNING("CHECK_HF_INIT: %s: HF AG not initialized", __FUNCTION__);\
94 return BT_STATUS_NOT_READY; \
95 } \
96 else\
97 {\
98 BTIF_TRACE_EVENT("CHECK_HF_INIT: %s", __FUNCTION__);\
99 }\
100 } while (0)
101
102 #define CHECK_HF_SLC_CONNECTED() do { \
103 if (! hf_local_param[idx].btc_hf_cb.initialized || \
104 hf_local_param[idx].btc_hf_cb.connection_state != ESP_HF_CONNECTION_STATE_SLC_CONNECTED) { \
105 BTIF_TRACE_WARNING("CHECK_HF_INIT: %s: HF AG not initialized", __FUNCTION__);\
106 return BT_STATUS_NOT_READY; \
107 } \
108 else\
109 {\
110 BTIF_TRACE_EVENT("CHECK_HF_INIT: %s", __FUNCTION__);\
111 }\
112 } while (0)
113
114
115 #define clear_phone_state() \
116 hf_local_param[idx].btc_hf_cb.call_state = ESP_HF_CALL_STATUS_NO_CALLS; \
117 hf_local_param[idx].btc_hf_cb.call_setup_state = ESP_HF_CALL_SETUP_STATUS_IDLE;\
118 hf_local_param[idx].btc_hf_cb.num_active = 0; \
119 hf_local_param[idx].btc_hf_cb.num_held = 0;
120
121 /************************************************************************************
122 ** Static Function
123 ************************************************************************************/
btc_hf_idx_by_bdaddr(bt_bdaddr_t * bd_addr)124 static int btc_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
125 {
126 for (int i = 0; i < btc_max_hf_clients; ++i) {
127 if ((bdcmp(bd_addr->address, hf_local_param[i].btc_hf_cb.connected_bda.address) == 0)
128 || bd_addr->address) {
129 return i;
130 }
131 }
132 return BTC_HF_INVALID_IDX;
133 }
134
is_connected(bt_bdaddr_t * bd_addr)135 static BOOLEAN is_connected(bt_bdaddr_t *bd_addr)
136 {
137 int idx = btc_hf_idx_by_bdaddr(bd_addr);
138 if (((hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_CONNECTED) ||
139 (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED)) &&
140 ((bd_addr == NULL) || (bdcmp(bd_addr->address,hf_local_param[idx].btc_hf_cb.connected_bda.address) == 0))) {
141 return TRUE;
142 }
143 return FALSE;
144 }
145
btc_hf_latest_connected_idx(void)146 static int btc_hf_latest_connected_idx(void)
147 {
148 struct timespec now, conn_time_delta;
149 int latest_conn_idx = BTC_HF_INVALID_IDX;
150 clock_gettime(CLOCK_MONOTONIC, &now);
151 conn_time_delta.tv_sec = now.tv_sec;
152
153 for (int i = 0; i < btc_max_hf_clients; i++) {
154 if (hf_local_param[i].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) {
155 if ((now.tv_sec - hf_local_param[i].btc_hf_cb.connected_timestamp.tv_sec) < conn_time_delta.tv_sec) {
156 conn_time_delta.tv_sec = now.tv_sec - hf_local_param[i].btc_hf_cb.connected_timestamp.tv_sec;
157 latest_conn_idx = i;
158 }
159 }
160 }
161 return latest_conn_idx;
162 }
163
164 /************************************************************************************
165 ** Cb and Evt
166 ************************************************************************************/
btc_hf_cb_to_app(esp_hf_cb_event_t event,esp_hf_cb_param_t * param)167 static inline void btc_hf_cb_to_app(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
168 {
169 esp_hf_cb_t btc_hf_callbacks = (esp_hf_cb_t)btc_profile_cb_get(BTC_PID_HF);
170 if (btc_hf_callbacks) {
171 btc_hf_callbacks(event, param);
172 }
173 }
174
send_indicator_update(UINT16 indicator,UINT16 value)175 static void send_indicator_update(UINT16 indicator, UINT16 value)
176 {
177 tBTA_AG_RES_DATA ag_res;
178 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
179 ag_res.ind.type = indicator;
180 ag_res.ind.value = value;
181 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
182 }
183
btc_hf_cind_evt(tBTA_AG_IND * ind)184 static void btc_hf_cind_evt(tBTA_AG_IND *ind)
185 {
186 esp_hf_cb_param_t param;
187 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
188
189 switch (ind->type) {
190 case BTA_AG_IND_CALL:
191 param.cind.call_status = ind->value;
192 break;
193 case BTA_AG_IND_CALLSETUP:
194 param.cind.call_setup_status = ind->value;
195 break;
196 case BTA_AG_IND_SERVICE:
197 param.cind.svc = ind->value;
198 break;
199 case BTA_AG_IND_SIGNAL:
200 param.cind.signal_strength = ind->value;
201 break;
202 case BTA_AG_IND_ROAM:
203 param.cind.roam = ind->value;
204 break;
205 case BTA_AG_IND_BATTCHG:
206 param.cind.battery_level = ind->value;
207 break;
208 case BTA_AG_IND_CALLHELD:
209 param.cind.call_held_status = ind->value;
210 break;
211 }
212 btc_hf_cb_to_app(ESP_HF_CIND_RESPONSE_EVT, ¶m);
213 }
214
bte_hf_evt(tBTA_AG_EVT event,tBTA_AG * param)215 static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *param)
216 {
217 int param_len = 0;
218 /* TODO: BTA sends the union members and not tBTA_AG. If using param_len=sizeof(tBTA_AG), we get a crash on memcpy */
219 if (BTA_AG_REGISTER_EVT == event) {
220 param_len = sizeof(tBTA_AG_REGISTER);
221 }
222 else if (BTA_AG_OPEN_EVT == event) {
223 param_len = sizeof(tBTA_AG_OPEN);
224 }
225 else if ((BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event)) {
226 param_len = sizeof(tBTA_AG_HDR);
227 }
228 else if (BTA_AG_CONN_EVT == event) {
229 param_len = sizeof(tBTA_AG_CONN);
230 }
231 else if (param) {
232 param_len = sizeof(tBTA_AG_VAL);
233 }
234 btc_msg_t msg;
235 msg.sig = BTC_SIG_API_CB;
236 msg.pid = BTC_PID_HF;
237 msg.act = event;
238
239 /* Switch to BTC context */
240 bt_status_t status = btc_transfer_context(&msg, param, param_len, NULL);
241 /* catch any failed context transfers */
242 BTC_ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
243 }
244
245 /************************************************************************************
246 ** Data flow control & Service management.
247 ************************************************************************************/
btc_hf_reg_data_cb(esp_hf_incoming_data_cb_t recv,esp_hf_outgoing_data_cb_t send)248 void btc_hf_reg_data_cb(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send)
249 {
250 hf_local_param[0].btc_hf_incoming_data_cb = recv;
251 hf_local_param[0].btc_hf_outgoing_data_cb = send;
252 }
253
btc_hf_incoming_data_cb_to_app(const uint8_t * data,uint32_t len)254 void btc_hf_incoming_data_cb_to_app(const uint8_t *data, uint32_t len)
255 {
256 int idx = 0;
257 // todo: critical section protection
258 if (hf_local_param[idx].btc_hf_incoming_data_cb) {
259 hf_local_param[idx].btc_hf_incoming_data_cb(data, len);
260 }
261 }
262
btc_hf_outgoing_data_cb_to_app(uint8_t * data,uint32_t len)263 uint32_t btc_hf_outgoing_data_cb_to_app(uint8_t *data, uint32_t len)
264 {
265 int idx = 0;
266 // todo: critical section protection
267 if (hf_local_param[idx].btc_hf_outgoing_data_cb) {
268 return hf_local_param[idx].btc_hf_outgoing_data_cb(data, len);
269 } else {
270 return 0;
271 }
272 }
273
btc_hf_execute_service(BOOLEAN b_enable)274 bt_status_t btc_hf_execute_service(BOOLEAN b_enable)
275 {
276 char * p_service_names[] = BTC_HF_SERVICE_NAMES;
277 int idx;
278 if (b_enable) {
279 /* Enable and register with BTA-AG */
280 BTA_AgEnable(BTA_AG_PARSE, bte_hf_evt);
281 for (idx = 0; idx < btc_max_hf_clients; idx++) {
282 BTA_AgRegister(BTC_HF_SERVICES, BTC_HF_SECURITY, BTC_HF_FEATURES, p_service_names, BTC_HF_ID_1);
283 }
284 } else {
285 /* De-register AG */
286 for (idx = 0; idx < btc_max_hf_clients; idx++) {
287 BTA_AgDeregister(hf_local_param[idx].btc_hf_cb.handle);
288 }
289 /* Disable AG */
290 BTA_AgDisable();
291 }
292 return BT_STATUS_SUCCESS;
293 }
294
295 /************************************************************************************
296 ** BTC HFP AG API FUNCTION
297 ************************************************************************************/
298 /************************************************************************************
299 ** Initialization and Connection Handle
300 ************************************************************************************/
btc_hf_init(bt_bdaddr_t * bd_addr)301 bt_status_t btc_hf_init(bt_bdaddr_t *bd_addr)
302 {
303 int idx = 0;
304 UNUSED(bd_addr);
305
306 #if HFP_DYNAMIC_MEMORY == TRUE
307 if ((hf_local_param = (hf_local_param_t *)osi_malloc(sizeof(hf_local_param_t) * BTC_HF_NUM_CB)) == NULL) {
308 return BT_STATUS_FAIL;
309 }
310 #endif
311
312 BTC_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btc_max_hf_clients);
313 /* Invoke the enable service API to the core to set the appropriate service_id
314 * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone)
315 * othwerwise only HSP is enabled (tablet)*/
316 #if (defined(BTC_HF_SERVICES) && (BTC_HF_SERVICES & BTA_HFP_SERVICE_MASK))
317 btc_dm_enable_service(BTA_HFP_SERVICE_ID);
318 #else
319 btc_dm_enable_service(BTA_HSP_SERVICE_ID);
320 #endif
321 clear_phone_state();
322 memset(&hf_local_param[idx].btc_hf_cb, 0, sizeof(btc_hf_cb_t));
323 // custom initialization here
324 hf_local_param[idx].btc_hf_cb.initialized = true;
325 // set audio path
326 #if BTM_SCO_HCI_INCLUDED
327 uint8_t data_path = ESP_SCO_DATA_PATH_HCI;
328 #else
329 uint8_t data_path = ESP_SCO_DATA_PATH_PCM;
330 #endif
331 esp_bredr_sco_datapath_set(data_path);
332 return BT_STATUS_SUCCESS;
333 }
334
btc_hf_deinit(bt_bdaddr_t * bd_addr)335 void btc_hf_deinit(bt_bdaddr_t *bd_addr)
336 {
337 UNUSED(bd_addr);
338
339 BTC_TRACE_EVENT("%s", __FUNCTION__);
340 btc_dm_disable_service(BTA_HFP_SERVICE_ID);
341 #if HFP_DYNAMIC_MEMORY == TRUE
342 if (hf_local_param) {
343 osi_free(hf_local_param);
344 hf_local_param = NULL;
345 }
346 #else
347 hf_local_param[0].btc_hf_cb.initialized = false;
348 #endif
349 }
350
connect_init(bt_bdaddr_t * bd_addr,uint16_t uuid)351 static bt_status_t connect_init(bt_bdaddr_t *bd_addr, uint16_t uuid)
352 {
353 int idx = btc_hf_idx_by_bdaddr(bd_addr);
354 CHECK_HF_INIT();
355 if (idx == btc_max_hf_clients) {
356 return BT_STATUS_BUSY;
357 }
358
359 if (!is_connected(bd_addr)) {
360 hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_CONNECTING;
361 bdcpy(hf_local_param[idx].btc_hf_cb.connected_bda.address, bd_addr->address);
362 BTA_AgOpen(hf_local_param[idx].btc_hf_cb.handle, hf_local_param[idx].btc_hf_cb.connected_bda.address, BTC_HF_SECURITY, BTC_HF_SERVICES);
363 return BT_STATUS_SUCCESS;
364 }
365 return BT_STATUS_BUSY;
366 }
btc_hf_connect(bt_bdaddr_t * bd_addr)367 bt_status_t btc_hf_connect(bt_bdaddr_t *bd_addr)
368 {
369 return btc_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_init);
370 }
371
btc_hf_disconnect(bt_bdaddr_t * bd_addr)372 bt_status_t btc_hf_disconnect(bt_bdaddr_t *bd_addr)
373 {
374 int idx = btc_hf_idx_by_bdaddr(bd_addr);
375 CHECK_HF_INIT();
376 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
377 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
378 return BT_STATUS_FAIL;
379 }
380
381 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
382 BTA_AgClose(hf_local_param[idx].btc_hf_cb.handle);
383 return BT_STATUS_SUCCESS;
384 }
385 return BT_STATUS_FAIL;
386 }
387
btc_hf_connect_audio(bt_bdaddr_t * bd_addr)388 bt_status_t btc_hf_connect_audio(bt_bdaddr_t *bd_addr)
389 {
390 int idx = btc_hf_idx_by_bdaddr(bd_addr);
391 CHECK_HF_SLC_CONNECTED();
392 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
393 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
394 return BT_STATUS_FAIL;
395 }
396
397 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
398 BTA_AgAudioOpen(hf_local_param[idx].btc_hf_cb.handle);
399 /* Inform the application that the audio connection has been initiated successfully */
400 do {
401 esp_hf_cb_param_t param;
402 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
403 param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTING;
404 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
405 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
406 } while (0);
407 return BT_STATUS_SUCCESS;
408 }
409 return BT_STATUS_FAIL;
410 }
411
btc_hf_disconnect_audio(bt_bdaddr_t * bd_addr)412 bt_status_t btc_hf_disconnect_audio(bt_bdaddr_t *bd_addr)
413 {
414 int idx = btc_hf_idx_by_bdaddr(bd_addr);
415 CHECK_HF_SLC_CONNECTED();
416 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
417 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
418 return BT_STATUS_FAIL;
419 }
420
421 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
422 BTA_AgAudioClose(hf_local_param[idx].btc_hf_cb.handle);
423 return BT_STATUS_SUCCESS;
424 }
425 return BT_STATUS_FAIL;
426 }
427
428 /************************************************************************************
429 ** AT cmd Handle
430 ************************************************************************************/
431 //AT+VRA
btc_hf_vra(bt_bdaddr_t * bd_addr,esp_hf_vr_state_t value)432 static bt_status_t btc_hf_vra(bt_bdaddr_t *bd_addr, esp_hf_vr_state_t value)
433 {
434 int idx = btc_hf_idx_by_bdaddr(bd_addr);
435 CHECK_HF_SLC_CONNECTED();
436 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
437 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
438 return BT_STATUS_FAIL;
439 }
440
441 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
442 if (hf_local_param[idx].btc_hf_cb.peer_feat & BTA_AG_PEER_FEAT_VREC) {
443 tBTA_AG_RES_DATA ag_res;
444 memset(&ag_res, 0, sizeof(ag_res));
445 ag_res.state = value;
446 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res);
447 return BT_STATUS_SUCCESS;
448 } else {
449 return BT_STATUS_UNSUPPORTED;
450 }
451 }
452 return BT_STATUS_NOT_READY;
453 }
454
btc_hf_volume_control(bt_bdaddr_t * bd_addr,esp_hf_volume_type_t type,int volume)455 static bt_status_t btc_hf_volume_control(bt_bdaddr_t *bd_addr, esp_hf_volume_type_t type, int volume)
456 {
457 int idx = btc_hf_idx_by_bdaddr(bd_addr);
458 CHECK_HF_SLC_CONNECTED();
459 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
460 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
461 return BT_STATUS_FAIL;
462 }
463 tBTA_AG_RES_DATA ag_res;
464 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
465
466 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
467 ag_res.num = volume;
468 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, (type == ESP_HF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES, &ag_res);
469 return BT_STATUS_SUCCESS;
470 }
471 return BT_STATUS_FAIL;
472 }
473
474 // Pre-formatted AT response, typically in response to unknown AT cmd
btc_hf_unat_response(bt_bdaddr_t * bd_addr,const char * unat)475 static bt_status_t btc_hf_unat_response(bt_bdaddr_t *bd_addr, const char *unat)
476 {
477 int idx = btc_hf_idx_by_bdaddr(bd_addr);
478 CHECK_HF_INIT();
479 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
480 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
481 return BT_STATUS_FAIL;
482 }
483
484 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX))
485 {
486 tBTA_AG_RES_DATA ag_res;
487 /* Format the response and send */
488 memset(&ag_res, 0, sizeof(ag_res));
489 if (unat != NULL) {
490 strncpy(ag_res.str, unat, BTA_AG_AT_MAX_LEN);
491 } else {
492 ag_res.ok_flag = BTA_AG_OK_ERROR;
493 ag_res.errcode = BTA_AG_ERR_OP_NOT_SUPPORTED;
494 }
495
496 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
497 return BT_STATUS_SUCCESS;
498 }
499 return BT_STATUS_FAIL;
500 }
501
502 // +CMEE:<response>
btc_hf_cmee_response(bt_bdaddr_t * bd_addr,esp_hf_at_response_code_t response_code,esp_hf_cme_err_t error_code)503 static bt_status_t btc_hf_cmee_response(bt_bdaddr_t *bd_addr, esp_hf_at_response_code_t response_code, esp_hf_cme_err_t error_code)
504 {
505 int idx = btc_hf_idx_by_bdaddr(bd_addr);
506 CHECK_HF_INIT();
507 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
508 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
509 return BT_STATUS_FAIL;
510 }
511
512 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
513 tBTA_AG_RES_DATA ag_res;
514 memset(&ag_res, 0, sizeof(ag_res));
515 if (response_code == ESP_HF_AT_RESPONSE_CODE_OK) {
516 ag_res.ok_flag = BTA_AG_OK_DONE;
517 } else {
518 ag_res.ok_flag = BTA_AG_OK_ERROR;
519 ag_res.errcode = error_code;
520 }
521 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
522 return BT_STATUS_SUCCESS;
523 }
524 return BT_STATUS_FAIL;
525 }
526
527 // +CIEV<...> for device status update
btc_hf_indchange_notification(bt_bdaddr_t * bd_addr,esp_hf_call_status_t call_state,esp_hf_call_setup_status_t call_setup_state,esp_hf_network_state_t ntk_state,int signal)528 static bt_status_t btc_hf_indchange_notification(bt_bdaddr_t *bd_addr,
529 esp_hf_call_status_t call_state,
530 esp_hf_call_setup_status_t call_setup_state,
531 esp_hf_network_state_t ntk_state, int signal)
532 {
533 int idx = btc_hf_idx_by_bdaddr(bd_addr);
534 CHECK_HF_INIT();
535 if (is_connected(bd_addr)) {
536 /* Send all indicators to BTA.
537 * BTA will make sure no duplicates are sent out*/
538 send_indicator_update(BTA_AG_IND_CALL, call_state);
539 send_indicator_update(BTA_AG_IND_CALLSETUP, call_setup_state);
540 send_indicator_update(BTA_AG_IND_SERVICE, ntk_state);
541 send_indicator_update(BTA_AG_IND_SIGNAL, signal);
542 return BT_STATUS_SUCCESS;
543 }
544 return BT_STATUS_SUCCESS;
545 }
546
547 //AT+CIND response
btc_hf_cind_response(bt_bdaddr_t * bd_addr,esp_hf_call_setup_status_t call_status,esp_hf_call_setup_status_t call_setup_status,esp_hf_network_state_t ntk_state,int signal,esp_hf_service_type_t roam,int batt_lev,esp_hf_call_held_status_t call_held_status)548 static bt_status_t btc_hf_cind_response(bt_bdaddr_t *bd_addr,
549 esp_hf_call_setup_status_t call_status,
550 esp_hf_call_setup_status_t call_setup_status,
551 esp_hf_network_state_t ntk_state, int signal, esp_hf_service_type_t roam, int batt_lev,
552 esp_hf_call_held_status_t call_held_status)
553 {
554 int idx = btc_hf_idx_by_bdaddr(bd_addr);
555 CHECK_HF_INIT();
556 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
557 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
558 return BT_STATUS_FAIL;
559 }
560
561 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
562 tBTA_AG_RES_DATA ag_res;
563 memset(&ag_res, 0, sizeof (ag_res));
564 sprintf(ag_res.str, "%d,%d,%d,%d,%d,%d,%d",
565 call_status, /* Call state*/
566 call_setup_status, /* Callsetup state */
567 ntk_state, /* network service */
568 signal, /* Signal strength */
569 roam, /* Roaming indicator */
570 batt_lev, /* Battery level */
571 call_held_status /* Callheld state */
572 );
573 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CIND_RES, &ag_res);
574 return BT_STATUS_SUCCESS;
575 }
576 return BT_STATUS_FAIL;
577 }
578
579 //AT+COPS response
btc_hf_cops_response(bt_bdaddr_t * bd_addr,const char * name)580 static bt_status_t btc_hf_cops_response(bt_bdaddr_t *bd_addr, const char *name)
581 {
582 int idx = btc_hf_idx_by_bdaddr(bd_addr);
583 CHECK_HF_SLC_CONNECTED();
584 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
585 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
586 return BT_STATUS_FAIL;
587 }
588
589 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
590 tBTA_AG_RES_DATA ag_res;
591 memset (&ag_res, 0, sizeof (ag_res));
592 /* Format the response */
593 sprintf(ag_res.str, "0,0,\"%s\"", name);
594 ag_res.ok_flag = BTA_AG_OK_DONE;
595 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_COPS_RES, &ag_res);
596 return BT_STATUS_SUCCESS;
597 }
598 return BT_STATUS_FAIL;
599 }
600
601 //AT+CLCC response
btc_hf_clcc_response(bt_bdaddr_t * bd_addr,int index,esp_hf_current_call_direction_t dir,esp_hf_current_call_status_t current_call_state,esp_hf_current_call_mode_t mode,esp_hf_current_call_mpty_type_t mpty,const char * number,esp_hf_call_addr_type_t type)602 static bt_status_t btc_hf_clcc_response(bt_bdaddr_t *bd_addr, int index, esp_hf_current_call_direction_t dir,
603 esp_hf_current_call_status_t current_call_state,
604 esp_hf_current_call_mode_t mode, esp_hf_current_call_mpty_type_t mpty,
605 const char *number, esp_hf_call_addr_type_t type)
606 {
607 int idx = btc_hf_idx_by_bdaddr(bd_addr);
608 CHECK_HF_SLC_CONNECTED();
609 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
610 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
611 return BT_STATUS_FAIL;
612 }
613
614 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
615 tBTA_AG_RES_DATA ag_res;
616 memset (&ag_res, 0, sizeof (ag_res));
617 if (index == 0) {
618 ag_res.ok_flag = BTA_AG_OK_DONE;
619 } else {
620 BTC_TRACE_EVENT("clcc_response: [%d] dir: %d current_call_state: %d mode: %d number: %s type: %d",
621 index, dir, current_call_state, mode, number, type);
622 int loc = sprintf (ag_res.str, "%d,%d,%d,%d,%d", index, dir, current_call_state, mode, mpty);
623 if (number) {
624 if ((type == ESP_HF_CALL_ADDR_TYPE_INTERNATIONAL) && (*number != '+')) {
625 sprintf(&ag_res.str[loc], ",\"+%s\",%d", number, type);
626 } else {
627 sprintf(&ag_res.str[loc], ",\"%s\",%d", number, type);
628 }
629 }
630 }
631 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CLCC_RES, &ag_res);
632 return BT_STATUS_SUCCESS;
633 }
634 return BT_STATUS_FAIL;
635 }
636
637 //AT+CNUM
btc_hf_cnum_response(bt_bdaddr_t * bd_addr,const char * number,esp_hf_subscriber_service_type_t type)638 static bt_status_t btc_hf_cnum_response(bt_bdaddr_t *bd_addr, const char *number, esp_hf_subscriber_service_type_t type)
639 {
640 int idx = btc_hf_idx_by_bdaddr(bd_addr);
641 CHECK_HF_SLC_CONNECTED();
642
643 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
644 tBTA_AG_RES_DATA ag_res;
645 memset(&ag_res, 0, sizeof (ag_res));
646 BTC_TRACE_EVENT("cnum_response: number = %s, type = %d", number, type);
647 if (number) {
648 sprintf(ag_res.str, ",\"%s\",%d",number, type);
649 } else {
650 sprintf(ag_res.str, ",\"\",%d",type);
651 }
652 ag_res.ok_flag = BTA_AG_OK_DONE;
653 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CNUM_RES, &ag_res);
654 return BT_STATUS_SUCCESS;
655 }
656 return BT_STATUS_FAIL;
657 }
658
659 //+BSIR
btc_hf_inband_ring(bt_bdaddr_t * bd_addr,esp_hf_in_band_ring_state_t state)660 static bt_status_t btc_hf_inband_ring(bt_bdaddr_t *bd_addr, esp_hf_in_band_ring_state_t state)
661 {
662 int idx = btc_hf_idx_by_bdaddr(bd_addr);
663 CHECK_HF_SLC_CONNECTED();
664
665 if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
666 tBTA_AG_RES_DATA ag_res;
667 memset (&ag_res, 0, sizeof (ag_res));
668 ag_res.state = state;
669 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_INBAND_RING_RES, &ag_res);
670 return BT_STATUS_SUCCESS;
671 }
672 return BT_STATUS_FAIL;
673 }
674
675 //Update phone status whether AG or HF act
btc_hf_phone_state_update(bt_bdaddr_t * bd_addr,int num_active,int num_held,esp_hf_call_status_t call_state,esp_hf_call_setup_status_t call_setup_state,char * number,esp_hf_call_addr_type_t type)676 static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active, int num_held,
677 esp_hf_call_status_t call_state, esp_hf_call_setup_status_t call_setup_state,
678 char *number, esp_hf_call_addr_type_t type)
679 {
680 tBTA_AG_RES res = 0xff;
681 tBTA_AG_RES_DATA ag_res;
682 bt_status_t status = BT_STATUS_SUCCESS;
683 BOOLEAN activeCallUpdated = FALSE;
684 int idx = btc_hf_idx_by_bdaddr(bd_addr), i;
685
686 /* hf_idx is index of connected HS that sent ATA/BLDN, otherwise index of latest connected HS */
687 if (hf_local_param->hf_idx != BTC_HF_INVALID_IDX) {
688 idx = hf_local_param->hf_idx;
689 } else {
690 idx = btc_hf_latest_connected_idx();
691 }
692
693 BTC_TRACE_DEBUG("phone_state_change: idx = %d", idx);
694 CHECK_HF_SLC_CONNECTED();
695 BTC_TRACE_DEBUG("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d] call =%s [prev: %s] call_setup=%s [prev: %s]",
696 num_active, hf_local_param[idx].btc_hf_cb.num_active,
697 num_held, hf_local_param[idx].btc_hf_cb.num_held,
698 dump_hf_call_state(call_state), dump_hf_call_state(hf_local_param[idx].btc_hf_cb.call_state),
699 dump_hf_call_setup_state(call_setup_state), dump_hf_call_setup_state(hf_local_param[idx].btc_hf_cb.call_setup_state));
700
701 /* If all indicators are 0, send end call and return */
702 if (num_active == 0 && num_held == 0 && call_state == ESP_HF_CALL_STATUS_NO_CALLS && call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE) {
703 BTC_TRACE_DEBUG("%s: Phone on hook", __FUNCTION__);
704
705 /* Record call termination timestamp if there was an active/held call or call_setup_state > ESP_HF_CALL_SETUP_STATUS_IDLE */
706 if ((hf_local_param[idx].btc_hf_cb.call_state != ESP_HF_CALL_STATUS_NO_CALLS) ||
707 (hf_local_param[idx].btc_hf_cb.call_setup_state != ESP_HF_CALL_SETUP_STATUS_IDLE) ||
708 (hf_local_param[idx].btc_hf_cb.num_active) ||
709 (hf_local_param[idx].btc_hf_cb.num_held)) {
710 BTC_TRACE_DEBUG("%s: Record call termination timestamp", __FUNCTION__);
711 clock_gettime(CLOCK_MONOTONIC, &hf_local_param[0].btc_hf_cb.call_end_timestamp);
712 }
713 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
714 hf_local_param->hf_idx = BTC_HF_INVALID_IDX;
715
716 /* If held call was present, reset that as well. */
717 if (hf_local_param[idx].btc_hf_cb.num_held) {
718 send_indicator_update(BTA_AG_IND_CALLHELD, 0);
719 }
720 goto update_call_states;
721 }
722
723 /* Phone state can change when:
724 * 1. An outgoing/incoming call was answered.
725 * 2. A held was resumed.
726 * 3. Without callsetup notifications, call became active. (HF Unit links in during an Active call.)
727 */
728
729 /* Handle case(3) here prior to call setup handling.*/
730 if (((num_active + num_held) > 0) &&
731 (hf_local_param[idx].btc_hf_cb.num_active == 0) &&
732 (hf_local_param[idx].btc_hf_cb.num_held == 0) &&
733 (hf_local_param[idx].btc_hf_cb.call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE)) {
734 BTC_TRACE_DEBUG("%s: Active/Held call notification received without call setup update", __FUNCTION__);
735
736 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
737 ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
738
739 /* Addition callsetup with the Active call. */
740 if (call_setup_state != ESP_HF_CALL_SETUP_STATUS_IDLE) {
741 res = BTA_AG_MULTI_CALL_RES;
742 } else {
743 res = BTA_AG_OUT_CALL_CONN_RES;
744 }
745 /* CIND response should have been updated. */
746 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
747 /* Just open SCO conenction. */
748 BTA_AgAudioOpen(ag_res.audio_handle);
749 activeCallUpdated = TRUE;
750 }
751
752 /* Handle call_setup indicator change. */
753 if (call_setup_state != hf_local_param[idx].btc_hf_cb.call_setup_state) {
754 BTC_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s", __FUNCTION__,
755 dump_hf_call_setup_state(hf_local_param[idx].btc_hf_cb.call_setup_state),
756 dump_hf_call_setup_state(call_setup_state));
757 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
758
759 switch(call_setup_state)
760 {
761 case ESP_HF_CALL_SETUP_STATUS_IDLE:
762 {
763 switch(hf_local_param[idx].btc_hf_cb.call_setup_state)
764 {
765 case ESP_HF_CALL_SETUP_STATUS_INCOMING:
766 {
767 if (num_active > hf_local_param[idx].btc_hf_cb.num_active) {
768 res = BTA_AG_IN_CALL_CONN_RES;
769 ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
770 } else if (num_held > hf_local_param[idx].btc_hf_cb.num_held) {
771 res = BTA_AG_IN_CALL_HELD_RES;
772 } else {
773 res = BTA_AG_CALL_CANCEL_RES;
774 }
775 break;
776 }
777
778 case ESP_HF_CALL_SETUP_STATUS_OUTGOING_DIALING:
779 case ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING:
780 {
781 if (num_active > hf_local_param[idx].btc_hf_cb.num_active) {
782 res = BTA_AG_OUT_CALL_CONN_RES;
783 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
784 } else {
785 res = BTA_AG_CALL_CANCEL_RES;
786 }
787 break;
788 }
789
790 default:
791 BTC_TRACE_ERROR("%s: Call setup state no change.", __FUNCTION__);
792 status = BT_STATUS_PARM_INVALID;
793 break;
794 }
795 break;
796 }
797
798 case ESP_HF_CALL_SETUP_STATUS_INCOMING:
799 {
800 if (num_active || num_held) {
801 res = BTA_AG_CALL_WAIT_RES;
802 } else {
803 res = BTA_AG_IN_CALL_RES;
804 }
805
806 if (number) {
807 int loc = 0;
808 if ((type == ESP_HF_CALL_ADDR_TYPE_INTERNATIONAL) && (*number != '+')) {
809 loc = sprintf (ag_res.str, "\"+%s\"", number);
810 } else {
811 loc = sprintf (ag_res.str, "\"%s\"", number);
812 }
813 ag_res.num = type;
814 if (res == BTA_AG_CALL_WAIT_RES) {
815 sprintf(&ag_res.str[loc], ",%d", type);
816 }
817 }
818 break;
819 }
820
821 case ESP_HF_CALL_SETUP_STATUS_OUTGOING_DIALING:
822 {
823 if (!(num_active + num_held)) {
824 ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
825 }
826 res = BTA_AG_OUT_CALL_ORIG_RES;
827 break;
828 }
829
830 case ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING:
831 {
832 if ((hf_local_param[idx].btc_hf_cb.call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE) &&
833 !(num_active + num_held)) {
834 ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
835 /* Force SCO setup here.*/
836 BTA_AgAudioOpen(ag_res.audio_handle);
837 }
838 res = BTA_AG_OUT_CALL_ALERT_RES;
839 break;
840 }
841
842 default:
843 BTC_TRACE_ERROR("%s: Incorrect new ringing call state", __FUNCTION__);
844 status = BT_STATUS_PARM_INVALID;
845 break;
846 }
847 BTC_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle);
848 if (res) {
849 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
850 }
851 /* If call setup is idle, we have already updated call indicator, jump out */
852 if (call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE) {
853 /* Check & Update call_held_state */
854 if ((num_held > 0) && (num_active > 0))
855 send_indicator_update(BTA_AG_IND_CALLHELD, ESP_HF_CALL_HELD_STATUS_HELD_AND_ACTIVE);
856 goto update_call_states;
857 }
858 }
859
860 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
861
862 /* Handle call_state indicator change. */
863 if (!activeCallUpdated &&
864 ((num_active + num_held) != (hf_local_param[idx].btc_hf_cb.num_active + hf_local_param[idx].btc_hf_cb.num_held))) {
865 BTC_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d", __FUNCTION__, hf_local_param[idx].btc_hf_cb.num_active, num_active);
866 send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
867 }
868
869 /* Handle call_held_state indicator change. */
870 if (num_held != hf_local_param[idx].btc_hf_cb.num_held ||
871 ((num_active == 0) && ((num_held + hf_local_param[idx].btc_hf_cb.num_held) > 1))) {
872 BTC_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d", __FUNCTION__, hf_local_param[idx].btc_hf_cb.num_held, num_held);
873 send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
874 }
875
876 /* Handle Call Active/Held Swap indicator update.*/
877 if ((call_setup_state == hf_local_param[idx].btc_hf_cb.call_setup_state) &&
878 (num_active) &&
879 (num_held) &&
880 (num_active == hf_local_param[idx].btc_hf_cb.num_active) &&
881 (num_held == hf_local_param[idx].btc_hf_cb.num_held)) {
882 BTC_TRACE_DEBUG("%s: Calls swapped", __FUNCTION__);
883 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
884 }
885
886 update_call_states:
887 for (i = 0; i < btc_max_hf_clients; i++) {
888 hf_local_param[i].btc_hf_cb.num_active = num_active;
889 hf_local_param[i].btc_hf_cb.num_held = num_held;
890 hf_local_param[i].btc_hf_cb.call_state = call_state;
891 hf_local_param[i].btc_hf_cb.call_setup_state = call_setup_state;
892 }
893 return status;
894 }
895
btc_hf_ci_sco_data(void)896 bt_status_t btc_hf_ci_sco_data(void)
897 {
898 bt_status_t status = BT_STATUS_SUCCESS;
899 #if (BTM_SCO_HCI_INCLUDED == TRUE)
900 int idx = btc_hf_latest_connected_idx();
901 CHECK_HF_SLC_CONNECTED();
902
903 if (idx != BTC_HF_INVALID_IDX) {
904 BTA_AgCiData(hf_local_param[idx].btc_hf_cb.handle);
905 return status;
906 }
907 status = BT_STATUS_FAIL;
908 #endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE ) */
909 return status;
910 }
911
912 /************************************************************************************
913 ** Memory malloc and release
914 ************************************************************************************/
btc_hf_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)915 void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
916 {
917 btc_hf_args_t *dst = (btc_hf_args_t *) p_dest;
918 btc_hf_args_t *src = (btc_hf_args_t *) p_src;
919
920 switch (msg->act) {
921 case BTC_HF_UNAT_RESPONSE_EVT:
922 {
923 if (src->unat_rep.unat == NULL) {
924 break;
925 }
926
927 dst->unat_rep.unat = (char *)osi_malloc(strlen(src->unat_rep.unat)+1);
928 if(dst->unat_rep.unat) {
929 memcpy(dst->unat_rep.unat, src->unat_rep.unat, strlen(src->unat_rep.unat)+1);
930 } else if (strlen(src->unat_rep.unat) == 0) {
931 BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act);
932 } else {
933 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
934 }
935 break;
936 }
937
938 case BTC_HF_COPS_RESPONSE_EVT:
939 {
940 if (src->cops_rep.name == NULL) {
941 break;
942 }
943
944 dst->cops_rep.name = (char *)osi_malloc(strlen(src->cops_rep.name)+1);
945 if(dst->cops_rep.name) {
946 memcpy(dst->cops_rep.name, src->cops_rep.name, strlen(src->cops_rep.name)+1);
947 } else if (strlen(src->cops_rep.name) == 0) {
948 BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act);
949 } else {
950 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
951 }
952 break;
953 }
954
955 case BTC_HF_CLCC_RESPONSE_EVT:
956 {
957 if (src->clcc_rep.number == NULL) {
958 break;
959 }
960
961 dst->clcc_rep.number = (char *)osi_malloc(strlen(src->clcc_rep.number)+1);
962 if(dst->clcc_rep.number) {
963 memcpy(dst->clcc_rep.number, src->clcc_rep.number, strlen(src->clcc_rep.number)+1);
964 } else if (strlen(src->clcc_rep.number) == 0) {
965 BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act);
966 } else {
967 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
968 }
969 break;
970 }
971
972 case BTC_HF_CNUM_RESPONSE_EVT:
973 {
974 if (src->cnum_rep.number == NULL) {
975 break;
976 }
977
978 dst->cnum_rep.number = (char *)osi_malloc(strlen(src->cnum_rep.number)+1);
979 if(dst->cnum_rep.number) {
980 memcpy(dst->cnum_rep.number, src->cnum_rep.number, strlen(src->cnum_rep.number)+1);
981 } else if (strlen(src->cnum_rep.number) == 0) {
982 BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act);
983 } else {
984 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
985 }
986 break;
987 }
988
989 case BTC_HF_AC_INCALL_EVT:
990 case BTC_HF_RJ_INCALL_EVT:
991 case BTC_HF_OUT_CALL_EVT:
992 case BTC_HF_END_CALL_EVT:
993 {
994 if (src->phone.number == NULL) {
995 break;
996 }
997
998 dst->phone.number = (char *)osi_malloc(strlen(src->phone.number)+1);
999 if(dst->phone.number) {
1000 memcpy(dst->phone.number, src->phone.number, strlen(src->phone.number)+1);
1001 } else if (strlen(src->phone.number) == 0) {
1002 BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act);
1003 } else {
1004 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
1005 }
1006 break;
1007 }
1008
1009 default:
1010 break;
1011 }
1012 }
1013
btc_hf_arg_deep_free(btc_msg_t * msg)1014 void btc_hf_arg_deep_free(btc_msg_t *msg)
1015 {
1016 btc_hf_args_t *arg = (btc_hf_args_t *)msg->arg;
1017
1018 switch (msg->act) {
1019 case BTC_HF_UNAT_RESPONSE_EVT:
1020 {
1021 if (arg->unat_rep.unat) {
1022 osi_free(arg->unat_rep.unat);
1023 }
1024 break;
1025 }
1026
1027 case BTC_HF_COPS_RESPONSE_EVT:
1028 {
1029 if (arg->cops_rep.name) {
1030 osi_free(arg->cops_rep.name);
1031 }
1032 break;
1033 }
1034
1035 case BTC_HF_CLCC_RESPONSE_EVT:
1036 {
1037 if (arg->clcc_rep.number) {
1038 osi_free(arg->clcc_rep.number);
1039 }
1040 break;
1041 }
1042
1043 case BTC_HF_CNUM_RESPONSE_EVT:
1044 {
1045 if (arg->cnum_rep.number) {
1046 osi_free(arg->cnum_rep.number);
1047 }
1048 break;
1049 }
1050
1051 case BTC_HF_AC_INCALL_EVT:
1052 case BTC_HF_RJ_INCALL_EVT:
1053 case BTC_HF_OUT_CALL_EVT:
1054 case BTC_HF_END_CALL_EVT:
1055 {
1056 if (arg->phone.number) {
1057 osi_free(arg->phone.number);
1058 }
1059 break;
1060 }
1061
1062 default:
1063 break;
1064 }
1065 }
1066
1067 /************************************************************************************
1068 ** Handler Functions (handle the cmd from app)
1069 ************************************************************************************/
btc_hf_call_handler(btc_msg_t * msg)1070 void btc_hf_call_handler(btc_msg_t *msg)
1071 {
1072 btc_hf_args_t *arg = (btc_hf_args_t *)(msg->arg);
1073
1074 switch (msg->act) {
1075 case BTC_HF_INIT_EVT:
1076 {
1077 btc_hf_init(&arg->init);
1078 break;
1079 }
1080
1081 case BTC_HF_DEINIT_EVT:
1082 {
1083 btc_hf_deinit(&arg->deinit);
1084 break;
1085 }
1086
1087 case BTC_HF_CONNECT_EVT:
1088 {
1089 btc_hf_connect(&arg->connect);
1090 break;
1091 }
1092
1093 case BTC_HF_DISCONNECT_EVT:
1094 {
1095 btc_hf_disconnect(&arg->disconnect);
1096 break;
1097 }
1098
1099 case BTC_HF_CONNECT_AUDIO_EVT:
1100 {
1101 btc_hf_connect_audio(&arg->connect_audio);
1102 break;
1103 }
1104
1105 case BTC_HF_DISCONNECT_AUDIO_EVT:
1106 {
1107 btc_hf_disconnect_audio(&arg->disconnect_audio);
1108 break;
1109 }
1110
1111 case BTC_HF_VRA_EVT:
1112 {
1113 btc_hf_vra(&arg->vra_rep.remote_addr, arg->vra_rep.value);
1114 if (arg->vra_rep.value) {
1115 btc_hf_connect_audio(&arg->vra_rep.remote_addr);
1116 } else {
1117 btc_hf_disconnect_audio(&arg->vra_rep.remote_addr);
1118 }
1119 break;
1120 }
1121
1122 case BTC_HF_VOLUME_CONTROL_EVT:
1123 {
1124 btc_hf_volume_control(&arg->volcon.remote_addr, arg->volcon.target_type, arg->volcon.volume);
1125 break;
1126 }
1127
1128 case BTC_HF_UNAT_RESPONSE_EVT:
1129 {
1130 btc_hf_unat_response(&arg->unat_rep.remote_addr, arg->unat_rep.unat);
1131 break;
1132 }
1133
1134 case BTC_HF_CME_ERR_EVT:
1135 {
1136 btc_hf_cmee_response(&arg->ext_at.remote_addr, arg->ext_at.response_code, arg->ext_at.error_code);
1137 break;
1138 }
1139
1140 case BTC_HF_IND_NOTIFICATION_EVT:
1141 {
1142 btc_hf_indchange_notification(&arg->ind_change.remote_addr,
1143 arg->ind_change.call_state, arg->ind_change.call_setup_state,
1144 arg->ind_change.ntk_state, arg->ind_change.signal);
1145 break;
1146 }
1147
1148 case BTC_HF_CIND_RESPONSE_EVT:
1149 {
1150 btc_hf_cind_response(&arg->cind_rep.remote_addr,
1151 arg->cind_rep.call_state, arg->cind_rep.call_setup_state,
1152 arg->cind_rep.ntk_state, arg->cind_rep.signal, arg->cind_rep.roam, arg->cind_rep.batt_lev,
1153 arg->cind_rep.call_held_state);
1154 break;
1155 }
1156
1157 case BTC_HF_COPS_RESPONSE_EVT:
1158 {
1159 btc_hf_cops_response(&arg->cops_rep.remote_addr, arg->cops_rep.name);
1160 break;
1161 }
1162
1163 case BTC_HF_CLCC_RESPONSE_EVT:
1164 {
1165 btc_hf_clcc_response(&arg->clcc_rep.remote_addr, arg->clcc_rep.index,
1166 arg->clcc_rep.dir, arg->clcc_rep.current_call_state,
1167 arg->clcc_rep.mode, arg->clcc_rep.mpty, arg->clcc_rep.number, arg->clcc_rep.type);
1168 break;
1169 }
1170
1171 case BTC_HF_CNUM_RESPONSE_EVT:
1172 {
1173 btc_hf_cnum_response(&arg->cnum_rep.remote_addr, arg->cnum_rep.number, arg->cnum_rep.type);
1174 break;
1175 }
1176
1177 case BTC_HF_INBAND_RING_EVT:
1178 {
1179 btc_hf_inband_ring(&arg->bsir.remote_addr, arg->bsir.state);
1180 break;
1181 }
1182
1183 case BTC_HF_AC_INCALL_EVT:
1184 {
1185 btc_hf_phone_state_update(&arg->phone.remote_addr, arg->phone.num_active, arg->phone.num_held,
1186 arg->phone.call_state, arg->phone.call_setup_state, arg->phone.number,
1187 arg->phone.call_addr_type);
1188 break;
1189 }
1190
1191 case BTC_HF_RJ_INCALL_EVT:
1192 {
1193 btc_hf_phone_state_update(&arg->phone.remote_addr, arg->phone.num_active, arg->phone.num_held,
1194 arg->phone.call_state, arg->phone.call_setup_state, arg->phone.number,
1195 arg->phone.call_addr_type);
1196 btc_hf_disconnect_audio(&arg->phone.remote_addr);
1197 break;
1198 }
1199
1200 case BTC_HF_OUT_CALL_EVT:
1201 {
1202 btc_hf_connect_audio(&arg->phone.remote_addr);
1203 btc_hf_phone_state_update(&arg->phone.remote_addr, arg->phone.num_active, arg->phone.num_held,
1204 arg->phone.call_state, arg->phone.call_setup_state, arg->phone.number,
1205 arg->phone.call_addr_type);
1206 break;
1207 }
1208
1209 case BTC_HF_END_CALL_EVT:
1210 {
1211 btc_hf_phone_state_update(&arg->phone.remote_addr, arg->phone.num_active, arg->phone.num_held,
1212 arg->phone.call_state, arg->phone.call_setup_state, arg->phone.number,
1213 arg->phone.call_addr_type);
1214 btc_hf_disconnect_audio(&arg->phone.remote_addr);
1215 break;
1216 }
1217
1218 case BTC_HF_REGISTER_DATA_CALLBACK_EVT:
1219 {
1220 btc_hf_reg_data_cb(arg->reg_data_cb.recv, arg->reg_data_cb.send);
1221 }
1222 break;
1223
1224 default:
1225 BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
1226 }
1227 btc_hf_arg_deep_free(msg);
1228 }
1229
btc_hf_cb_handler(btc_msg_t * msg)1230 void btc_hf_cb_handler(btc_msg_t *msg)
1231 {
1232 uint16_t event = msg->act;
1233 tBTA_AG *p_data = (tBTA_AG *)msg->arg;
1234 esp_hf_cb_param_t param;
1235 bdstr_t bdstr;
1236 int idx;
1237
1238 if (p_data == NULL) {
1239 idx = BTC_HF_INVALID_IDX;
1240 } else {
1241 idx = p_data->hdr.handle - 1;
1242 }
1243
1244 BTC_TRACE_DEBUG("%s: event = %s", __FUNCTION__, dump_hf_event(event));
1245 if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) {
1246 BTC_TRACE_ERROR("%s: Invalid index %d", __FUNCTION__, idx);
1247 return;
1248 }
1249
1250 switch (event) {
1251 case BTA_AG_ENABLE_EVT:
1252 case BTA_AG_DISABLE_EVT:
1253 break;
1254
1255 case BTA_AG_REGISTER_EVT:
1256 {
1257 hf_local_param[idx].btc_hf_cb.handle = p_data->reg.hdr.handle;
1258 BTC_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT," "hf_local_param[%d].btc_hf_cb.handle = %d",
1259 __FUNCTION__, idx, hf_local_param[idx].btc_hf_cb.handle);
1260 break;
1261 }
1262
1263 case BTA_AG_OPEN_EVT:
1264 {
1265 if (p_data->open.status == BTA_AG_SUCCESS)
1266 {
1267 bdcpy(hf_local_param[idx].btc_hf_cb.connected_bda.address, p_data->open.bd_addr);
1268 hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_CONNECTED;
1269 hf_local_param[idx].btc_hf_cb.peer_feat = 0;
1270 hf_local_param[idx].btc_hf_cb.chld_feat = 0;
1271 //clear_phone_state();
1272 } else if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_CONNECTING) {
1273 hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
1274 } else {
1275 BTC_TRACE_WARNING("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s", __FUNCTION__,
1276 p_data->open.status, hf_local_param[idx].btc_hf_cb.connection_state,
1277 bdaddr_to_string(&hf_local_param[idx].btc_hf_cb.connected_bda, bdstr, sizeof(bdstr)));
1278 break;
1279 }
1280
1281 do {
1282 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1283 memcpy(param.conn_stat.remote_bda, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
1284 param.conn_stat.state = hf_local_param[idx].btc_hf_cb.connection_state;
1285 param.conn_stat.peer_feat = 0;
1286 param.conn_stat.chld_feat = 0;
1287 btc_hf_cb_to_app(ESP_HF_CONNECTION_STATE_EVT, ¶m);
1288 } while (0);
1289
1290 if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_DISCONNECTED)
1291 bdsetany(hf_local_param[idx].btc_hf_cb.connected_bda.address);
1292
1293 if (p_data->open.status != BTA_AG_SUCCESS)
1294 btc_queue_advance();
1295 break;
1296 }
1297
1298 case BTA_AG_CONN_EVT:
1299 {
1300 clock_gettime(CLOCK_MONOTONIC, &(hf_local_param[idx].btc_hf_cb.connected_timestamp));
1301 BTC_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ", __FUNCTION__, idx);
1302 hf_local_param[idx].btc_hf_cb.peer_feat = p_data->conn.peer_feat;
1303 hf_local_param[idx].btc_hf_cb.chld_feat = p_data->conn.chld_feat;
1304 hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_SLC_CONNECTED;
1305
1306 do {
1307 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1308 param.conn_stat.state = hf_local_param[idx].btc_hf_cb.connection_state;
1309 param.conn_stat.peer_feat = hf_local_param[idx].btc_hf_cb.peer_feat;
1310 param.conn_stat.chld_feat = hf_local_param[idx].btc_hf_cb.chld_feat;
1311 memcpy(param.conn_stat.remote_bda, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
1312 btc_hf_cb_to_app(ESP_HF_CONNECTION_STATE_EVT, ¶m);
1313 } while(0);
1314 hf_local_param[idx].hf_idx = btc_hf_latest_connected_idx();
1315 btc_queue_advance();
1316 break;
1317 }
1318
1319 case BTA_AG_CLOSE_EVT:
1320 {
1321 hf_local_param[idx].btc_hf_cb.connected_timestamp.tv_sec = 0;
1322 hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
1323 BTC_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT," "hf_local_param[%d].btc_hf_cb.handle = %d", __FUNCTION__,
1324 idx, hf_local_param[idx].btc_hf_cb.handle);
1325 do {
1326 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1327 param.conn_stat.state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
1328 param.conn_stat.peer_feat = 0;
1329 param.conn_stat.chld_feat = 0;
1330 memcpy(param.conn_stat.remote_bda, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
1331 btc_hf_cb_to_app(ESP_HF_CONNECTION_STATE_EVT, ¶m);
1332 } while(0);
1333 bdsetany(hf_local_param[idx].btc_hf_cb.connected_bda.address);
1334 clear_phone_state();
1335 hf_local_param[idx].hf_idx = btc_hf_latest_connected_idx();
1336 btc_queue_advance();
1337 break;
1338 }
1339
1340 case BTA_AG_AUDIO_OPEN_EVT:
1341 {
1342 do {
1343 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1344 param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED;
1345 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
1346 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
1347 } while(0);
1348 break;
1349 }
1350
1351 case BTA_AG_AUDIO_MSBC_OPEN_EVT:
1352 {
1353 do {
1354 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1355 param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
1356 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
1357 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
1358 } while (0);
1359 break;
1360 }
1361 case BTA_AG_AUDIO_CLOSE_EVT:
1362 {
1363 do {
1364 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1365 param.audio_stat.state = ESP_HF_AUDIO_STATE_DISCONNECTED;
1366 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
1367 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
1368 } while(0);
1369 break;
1370 }
1371
1372 case BTA_AG_AT_BVRA_EVT:
1373 {
1374 do {
1375 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1376 param.vra_rep.value = p_data->val.num;
1377 btc_hf_cb_to_app(ESP_HF_BVRA_RESPONSE_EVT, ¶m);
1378 if (p_data->val.num) {
1379 btc_hf_connect_audio(&hf_local_param[idx].btc_hf_cb.connected_bda);
1380 } else {
1381 btc_hf_disconnect_audio(&hf_local_param[idx].btc_hf_cb.connected_bda);
1382 }
1383 } while (0);
1384 break;
1385 }
1386
1387 case BTA_AG_SPK_EVT:
1388 case BTA_AG_MIC_EVT:
1389 {
1390 do {
1391 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1392 param.volume_control.type = (event == BTA_AG_SPK_EVT) ? ESP_HF_VOLUME_CONTROL_TARGET_SPK : ESP_HF_VOLUME_CONTROL_TARGET_MIC;
1393 param.volume_control.volume = p_data->val.num;
1394 btc_hf_cb_to_app(ESP_HF_VOLUME_CONTROL_EVT, ¶m);
1395 } while (0);
1396 break;
1397 }
1398
1399 case BTA_AG_AT_UNAT_EVT:
1400 {
1401 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1402 param.unat_rep.unat = p_data->val.str;
1403 btc_hf_cb_to_app(ESP_HF_UNAT_RESPONSE_EVT, ¶m);
1404 break;
1405 }
1406
1407 case BTA_AG_AT_CBC_EVT:
1408 {
1409 btc_hf_cb_to_app(ESP_HF_IND_UPDATE_EVT, NULL);
1410 break;
1411 }
1412
1413 case BTA_AG_AT_CIND_EVT:
1414 {
1415 btc_hf_cind_evt(&p_data->ind);
1416 break;
1417 }
1418
1419 case BTA_AG_AT_COPS_EVT:
1420 {
1421 btc_hf_cb_to_app(ESP_HF_COPS_RESPONSE_EVT, NULL);
1422 break;
1423 }
1424
1425 case BTA_AG_AT_CLCC_EVT:
1426 {
1427 btc_hf_cb_to_app(ESP_HF_CLCC_RESPONSE_EVT, NULL);
1428 break;
1429 }
1430
1431 case BTA_AG_AT_CNUM_EVT:
1432 {
1433 btc_hf_cb_to_app(ESP_HF_CNUM_RESPONSE_EVT, NULL);
1434 break;
1435 }
1436
1437 case BTA_AG_AT_VTS_EVT:
1438 {
1439 do {
1440 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1441 param.vts_rep.code = p_data->val.str;
1442 btc_hf_cb_to_app(ESP_HF_VTS_RESPONSE_EVT, ¶m);
1443 } while(0);
1444 break;
1445 }
1446
1447 case BTA_AG_AT_NREC_EVT:
1448 {
1449 do {
1450 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1451 param.nrec.state = p_data->val.num;
1452 btc_hf_cb_to_app(ESP_HF_NREC_RESPONSE_EVT, ¶m);
1453 } while(0);
1454 break;
1455 }
1456
1457 case BTA_AG_AT_A_EVT:
1458 {
1459 btc_hf_cb_to_app(ESP_HF_ATA_RESPONSE_EVT, NULL);
1460 break;
1461 }
1462
1463 case BTA_AG_AT_CHUP_EVT:
1464 {
1465 btc_hf_cb_to_app(ESP_HF_CHUP_RESPONSE_EVT, NULL);
1466 break;
1467 }
1468
1469 case BTA_AG_AT_BLDN_EVT:
1470 case BTA_AG_AT_D_EVT:
1471 {
1472 do {
1473 if (event == BTA_AG_AT_D_EVT && p_data->val.str) { // dial_number_or_memory
1474 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1475 param.out_call.num_or_loc = osi_malloc((strlen(p_data->val.str) + 1) * sizeof(char));
1476 sprintf(param.out_call.num_or_loc, p_data->val.str);
1477 btc_hf_cb_to_app(ESP_HF_DIAL_EVT, ¶m);
1478 send_indicator_update(BTA_AG_IND_CALLSETUP,BTA_AG_CALLSETUP_OUTGOING);
1479 osi_free(param.out_call.num_or_loc);
1480 } else if (event == BTA_AG_AT_BLDN_EVT) { //dial_last
1481 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1482 btc_hf_cb_to_app(ESP_HF_DIAL_EVT, ¶m);
1483 }
1484 } while(0);
1485 break;
1486 }
1487
1488 case BTA_AG_AT_BINP_EVT:
1489 case BTA_AG_AT_BTRH_EVT:
1490 {
1491 tBTA_AG_RES_DATA ag_res;
1492 memset(&ag_res, 0, sizeof(ag_res));
1493 ag_res.ok_flag = BTA_AG_OK_ERROR;
1494 ag_res.errcode = BTA_AG_ERR_OP_NOT_SUPPORTED;
1495 BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
1496 break;
1497 }
1498
1499 case BTA_AG_AT_BAC_EVT:
1500 {
1501 BTC_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num);
1502 #if (BTM_WBS_INCLUDED == TRUE)
1503 /* If the peer supports mSBC and the BTC prefferred codec is also mSBC, then
1504 ** we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC at the time
1505 ** of SCO connection establishment */
1506 if ((btc_conf_hf_force_wbs == TRUE) && (p_data->val.num & BTA_AG_CODEC_MSBC)) {
1507 BTC_TRACE_DEBUG("%s btc_hf override-Preferred Codec to MSBC", __FUNCTION__);
1508 BTA_AgSetCodec(hf_local_param[idx].btc_hf_cb.handle,BTA_AG_CODEC_MSBC);
1509 }
1510 else {
1511 BTC_TRACE_DEBUG("%s btc_hf override-Preferred Codec to CVSD", __FUNCTION__);
1512 BTA_AgSetCodec(hf_local_param[idx].btc_hf_cb.handle,BTA_AG_CODEC_CVSD);
1513 }
1514 #endif
1515 break;
1516 }
1517 #if (BTM_WBS_INCLUDED == TRUE)
1518 case BTA_AG_WBS_EVT:
1519 {
1520 BTC_TRACE_DEBUG("Set codec status %d codec %d 1=CVSD 2=MSBC", p_data->val.hdr.status, p_data->val.value);
1521 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1522 param.wbs_rep.codec = p_data->val.value;
1523 btc_hf_cb_to_app(ESP_HF_WBS_RESPONSE_EVT, ¶m);
1524 break;
1525 }
1526
1527 case BTA_AG_AT_BCS_EVT:
1528 {
1529 BTC_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num);
1530 memset(¶m, 0, sizeof(esp_hf_cb_param_t));
1531 param.bcs_rep.mode = p_data->val.num;
1532 /* No ESP_HF_WBS_NONE case, becuase HFP 1.6 supported device can send BCS */
1533 btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m);
1534 break;
1535 }
1536 #endif
1537 default:
1538 BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
1539 break;
1540 }
1541 }
1542 #endif // #if (BTC_HF_INCLUDED == TRUE)
1543