1 /******************************************************************************
3 * Copyright (C) 2004-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 #define LOG_TAG "bta_ag_cmd"
25 #include "bt_common.h"
26 #include "bt_target.h"
28 #include "bta_ag_api.h"
29 #include "bta_ag_at.h"
30 #include "bta_ag_int.h"
33 #include "osi/include/log.h"
34 #include "osi/include/osi.h"
38 /*****************************************************************************
40 ****************************************************************************/
43 #define BTA_AG_RING_TIMEOUT_MS (5 * 1000) /* 5 seconds */
45 #define BTA_AG_CMD_MAX_VAL 32767 /* Maximum value is signed 16-bit value */
47 /* Invalid Chld command */
48 #define BTA_AG_INVALID_CHLD 255
50 /* clip type constants */
51 #define BTA_AG_CLIP_TYPE_MIN 128
52 #define BTA_AG_CLIP_TYPE_MAX 175
53 #define BTA_AG_CLIP_TYPE_DEFAULT 129
54 #define BTA_AG_CLIP_TYPE_VOIP 255
56 #define COLON_IDX_4_VGSVGM 4
58 /* Local events which will not trigger a higher layer callback */
60 BTA_AG_LOCAL_EVT_FIRST = 0x100,
61 BTA_AG_LOCAL_EVT_CCWA,
62 BTA_AG_LOCAL_EVT_CLIP,
63 BTA_AG_LOCAL_EVT_CMER,
64 BTA_AG_LOCAL_EVT_BRSF,
65 BTA_AG_LOCAL_EVT_CMEE,
70 /* AT command interpreter table for HSP */
71 const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] = {
72 {"+CKPD", BTA_AG_AT_CKPD_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 200, 200},
73 {"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
74 {"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
75 /* End-of-table marker used to stop lookup iteration */
78 /* AT command interpreter table for HFP */
79 const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] = {
80 {"A", BTA_AG_AT_A_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
81 {"D", BTA_AG_AT_D_EVT, BTA_AG_AT_NONE | BTA_AG_AT_FREE, BTA_AG_AT_STR, 0,
83 {"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
84 {"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
85 {"+CCWA", BTA_AG_LOCAL_EVT_CCWA, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
86 /* Consider CHLD as str to take care of indexes for ECC */
87 {"+CHLD", BTA_AG_AT_CHLD_EVT, BTA_AG_AT_SET | BTA_AG_AT_TEST, BTA_AG_AT_STR,
89 {"+CHUP", BTA_AG_AT_CHUP_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
90 {"+CIND", BTA_AG_AT_CIND_EVT, BTA_AG_AT_READ | BTA_AG_AT_TEST,
92 {"+CLIP", BTA_AG_LOCAL_EVT_CLIP, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
93 {"+CMER", BTA_AG_LOCAL_EVT_CMER, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
94 {"+VTS", BTA_AG_AT_VTS_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
95 {"+BINP", BTA_AG_AT_BINP_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 1, 1},
96 {"+BLDN", BTA_AG_AT_BLDN_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
97 {"+BVRA", BTA_AG_AT_BVRA_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
98 {"+BRSF", BTA_AG_LOCAL_EVT_BRSF, BTA_AG_AT_SET, BTA_AG_AT_INT, 0,
100 {"+NREC", BTA_AG_AT_NREC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 0},
101 {"+CNUM", BTA_AG_AT_CNUM_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
102 {"+BTRH", BTA_AG_AT_BTRH_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_INT,
104 {"+CLCC", BTA_AG_AT_CLCC_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
105 {"+COPS", BTA_AG_AT_COPS_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_STR,
107 {"+CMEE", BTA_AG_LOCAL_EVT_CMEE, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
108 {"+BIA", BTA_AG_LOCAL_EVT_BIA, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},
109 {"+CBC", BTA_AG_AT_CBC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100},
110 {"+BCC", BTA_AG_LOCAL_EVT_BCC, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
111 {"+BCS", BTA_AG_AT_BCS_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0,
113 {"+BIND", BTA_AG_AT_BIND_EVT,
114 BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0},
115 {"+BIEV", BTA_AG_AT_BIEV_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
116 {"+BAC", BTA_AG_AT_BAC_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
117 /* End-of-table marker used to stop lookup iteration */
118 {"", 0, 0, 0, 0, 0}};
120 /* AT result code table element */
122 const char* result_string; /* AT result string */
123 size_t result_id; /* Local or BTA result id */
124 uint8_t arg_type; /* whether argument is int or string */
127 /* AT result code argument types */
129 BTA_AG_RES_FMT_NONE, /* no argument */
130 BTA_AG_RES_FMT_INT, /* integer argument */
131 BTA_AG_RES_FMT_STR /* string argument */
134 /* Local AT command result codes not defined in bta_ag_api.h */
136 BTA_AG_LOCAL_RES_FIRST = 0x0100,
138 BTA_AG_LOCAL_RES_ERROR,
139 BTA_AG_LOCAL_RES_RING,
140 BTA_AG_LOCAL_RES_CLIP,
141 BTA_AG_LOCAL_RES_BRSF,
142 BTA_AG_LOCAL_RES_CMEE,
146 /* AT result code constant table */
147 const tBTA_AG_RESULT bta_ag_result_tbl[] = {
148 {"OK", BTA_AG_LOCAL_RES_OK, BTA_AG_RES_FMT_NONE},
149 {"ERROR", BTA_AG_LOCAL_RES_ERROR, BTA_AG_RES_FMT_NONE},
150 {"RING", BTA_AG_LOCAL_RES_RING, BTA_AG_RES_FMT_NONE},
151 {"+VGS: ", BTA_AG_SPK_RES, BTA_AG_RES_FMT_INT},
152 {"+VGM: ", BTA_AG_MIC_RES, BTA_AG_RES_FMT_INT},
153 {"+CCWA: ", BTA_AG_CALL_WAIT_RES, BTA_AG_RES_FMT_STR},
154 {"+CHLD: ", BTA_AG_IN_CALL_HELD_RES, BTA_AG_RES_FMT_STR},
155 {"+CIND: ", BTA_AG_CIND_RES, BTA_AG_RES_FMT_STR},
156 {"+CLIP: ", BTA_AG_LOCAL_RES_CLIP, BTA_AG_RES_FMT_STR},
157 {"+CIEV: ", BTA_AG_IND_RES, BTA_AG_RES_FMT_STR},
158 {"+BINP: ", BTA_AG_BINP_RES, BTA_AG_RES_FMT_STR},
159 {"+BVRA: ", BTA_AG_BVRA_RES, BTA_AG_RES_FMT_INT},
160 {"+BRSF: ", BTA_AG_LOCAL_RES_BRSF, BTA_AG_RES_FMT_INT},
161 {"+BSIR: ", BTA_AG_INBAND_RING_RES, BTA_AG_RES_FMT_INT},
162 {"+CNUM: ", BTA_AG_CNUM_RES, BTA_AG_RES_FMT_STR},
163 {"+BTRH: ", BTA_AG_BTRH_RES, BTA_AG_RES_FMT_INT},
164 {"+CLCC: ", BTA_AG_CLCC_RES, BTA_AG_RES_FMT_STR},
165 {"+COPS: ", BTA_AG_COPS_RES, BTA_AG_RES_FMT_STR},
166 {"+CME ERROR: ", BTA_AG_LOCAL_RES_CMEE, BTA_AG_RES_FMT_INT},
167 {"+BCS: ", BTA_AG_LOCAL_RES_BCS, BTA_AG_RES_FMT_INT},
168 {"+BIND: ", BTA_AG_BIND_RES, BTA_AG_RES_FMT_STR},
169 {"", BTA_AG_UNAT_RES, BTA_AG_RES_FMT_STR}};
171 static const tBTA_AG_RESULT* bta_ag_result_by_code(size_t code) {
173 i != sizeof(bta_ag_result_tbl) / sizeof(bta_ag_result_tbl[0]); ++i) {
174 if (code == bta_ag_result_tbl[i].result_id) return &bta_ag_result_tbl[i];
179 const tBTA_AG_AT_CMD* bta_ag_at_tbl[BTA_AG_NUM_IDX] = {bta_ag_hsp_cmd,
185 } tBTA_AG_INDICATOR_MAP;
187 /* callsetup indicator value lookup table */
188 const tBTA_AG_INDICATOR_MAP callsetup_indicator_map[] = {
189 {BTA_AG_IN_CALL_RES, BTA_AG_CALLSETUP_INCOMING},
190 {BTA_AG_CALL_WAIT_RES, BTA_AG_CALLSETUP_INCOMING},
191 {BTA_AG_OUT_CALL_ORIG_RES, BTA_AG_CALLSETUP_OUTGOING},
192 {BTA_AG_OUT_CALL_ALERT_RES, BTA_AG_CALLSETUP_ALERTING}};
194 static size_t bta_ag_indicator_by_result_code(size_t code) {
197 sizeof(callsetup_indicator_map) / sizeof(callsetup_indicator_map[0]);
199 if (code == callsetup_indicator_map[i].result_code)
200 return callsetup_indicator_map[i].indicator;
202 return BTA_AG_CALLSETUP_NONE;
205 /*******************************************************************************
207 * Function bta_ag_send_result
209 * Description Send an AT result code.
214 ******************************************************************************/
215 static void bta_ag_send_result(tBTA_AG_SCB* p_scb, size_t code,
216 const char* p_arg, int16_t int_arg) {
217 const tBTA_AG_RESULT* result = bta_ag_result_by_code(code);
219 LOG_ERROR(LOG_TAG, "%s Unable to lookup result for code %zu", __func__,
224 char buf[BTA_AG_AT_MAX_LEN + 16];
226 memset(buf, 0, sizeof(buf));
232 /* copy result code string */
233 strlcpy(p, result->result_string, sizeof(buf) - 2);
235 if (p_scb->conn_service == BTA_AG_HSP) {
236 /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */
240 if (*(p + COLON_IDX_4_VGSVGM) == ':') {
241 *(p + COLON_IDX_4_VGSVGM) = '=';
247 p += strlen(result->result_string);
249 /* copy argument if any */
250 if (result->arg_type == BTA_AG_RES_FMT_INT) {
251 p += utl_itoa((uint16_t)int_arg, p);
252 } else if (result->arg_type == BTA_AG_RES_FMT_STR) {
257 /* finish with \r\n */
263 PORT_WriteData(p_scb->conn_handle, buf, (uint16_t)(p - buf), &len);
266 /*******************************************************************************
268 * Function bta_ag_send_ok
270 * Description Send an OK result code.
275 ******************************************************************************/
276 static void bta_ag_send_ok(tBTA_AG_SCB* p_scb) {
277 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_OK, NULL, 0);
280 /*******************************************************************************
282 * Function bta_ag_send_error
284 * Description Send an ERROR result code.
285 * errcode - used to send verbose errocode
290 ******************************************************************************/
291 static void bta_ag_send_error(tBTA_AG_SCB* p_scb, int16_t errcode) {
292 /* If HFP and extended audio gateway error codes are enabled */
293 if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
294 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CMEE, NULL, errcode);
296 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, NULL, 0);
299 /*******************************************************************************
301 * Function bta_ag_send_ind
303 * Description Send an indicator CIEV result code.
308 ******************************************************************************/
309 static void bta_ag_send_ind(tBTA_AG_SCB* p_scb, uint16_t id, uint16_t value,
314 /* If the indicator is masked out, just return */
315 /* Mandatory indicators can not be masked out. */
316 if ((p_scb->bia_masked_out & ((uint32_t)1 << id)) &&
317 ((id != BTA_AG_IND_CALL) && (id != BTA_AG_IND_CALLSETUP) &&
318 (id != BTA_AG_IND_CALLHELD)))
321 /* Ensure we do not send duplicate indicators if not requested by app */
322 /* If it was requested by app, transmit CIEV even if it is duplicate. */
323 if (id == BTA_AG_IND_CALL) {
324 if ((value == p_scb->call_ind) && (on_demand == false)) return;
326 p_scb->call_ind = (uint8_t)value;
329 if ((id == BTA_AG_IND_CALLSETUP) && (on_demand == false)) {
330 if (value == p_scb->callsetup_ind) return;
332 p_scb->callsetup_ind = (uint8_t)value;
335 if ((id == BTA_AG_IND_SERVICE) && (on_demand == false)) {
336 if (value == p_scb->service_ind) return;
338 p_scb->service_ind = (uint8_t)value;
340 if ((id == BTA_AG_IND_SIGNAL) && (on_demand == false)) {
341 if (value == p_scb->signal_ind) return;
343 p_scb->signal_ind = (uint8_t)value;
345 if ((id == BTA_AG_IND_ROAM) && (on_demand == false)) {
346 if (value == p_scb->roam_ind) return;
348 p_scb->roam_ind = (uint8_t)value;
350 if ((id == BTA_AG_IND_BATTCHG) && (on_demand == false)) {
351 if (value == p_scb->battchg_ind) return;
353 p_scb->battchg_ind = (uint8_t)value;
356 if ((id == BTA_AG_IND_CALLHELD) && (on_demand == false)) {
357 /* call swap could result in sending callheld=1 multiple times */
358 if ((value != 1) && (value == p_scb->callheld_ind)) return;
360 p_scb->callheld_ind = (uint8_t)value;
363 if (p_scb->cmer_enabled) {
364 p += utl_itoa(id, p);
367 bta_ag_send_result(p_scb, BTA_AG_IND_RES, str, 0);
371 /*******************************************************************************
373 * Function bta_ag_parse_cmer
375 * Description Parse AT+CMER parameter string.
378 * Returns true if parsed ok, false otherwise.
380 ******************************************************************************/
381 static bool bta_ag_parse_cmer(char* p_s, bool* p_enabled) {
382 int16_t n[4] = {-1, -1, -1, -1};
386 for (i = 0; i < 4; i++) {
387 /* skip to comma delimiter */
388 for (p = p_s; *p != ',' && *p != 0; p++)
391 /* get integer value */
393 n[i] = utl_str2int(p_s);
401 if (n[0] < 0 || n[3] < 0) {
405 if ((n[0] == 3) && ((n[3] == 1) || (n[3] == 0))) {
406 *p_enabled = (bool)n[3];
412 /*******************************************************************************
414 * Function bta_ag_parse_chld
416 * Description Parse AT+CHLD parameter string.
419 * Returns Returns idx (1-7), 0 if ECC not enabled or
421 if idx doesn't exist/1st character of argument is not a
424 ******************************************************************************/
425 static uint8_t bta_ag_parse_chld(UNUSED_ATTR tBTA_AG_SCB* p_scb, char* p_s) {
429 if (!isdigit(p_s[0])) {
430 return BTA_AG_INVALID_CHLD;
434 /* p_idxstr++; point to beginning of call number */
435 idx = utl_str2int(&p_s[1]);
436 if (idx != -1 && idx < 255) {
437 retval = (uint8_t)idx;
439 retval = BTA_AG_INVALID_CHLD;
446 /*******************************************************************************
448 * Function bta_ag_parse_bac
450 * Description Parse AT+BAC parameter string.
452 * Returns Returns bitmap of supported codecs.
454 ******************************************************************************/
455 static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB* p_scb, char* p_s) {
456 tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE;
458 bool cont = false; /* Continue processing */
462 /* skip to comma delimiter */
463 for (p = p_s; *p != ',' && *p != 0; p++)
466 /* get integre value */
473 uuid_codec = utl_str2int(p_s);
474 switch (uuid_codec) {
475 case UUID_CODEC_CVSD:
476 retval |= BTA_AG_CODEC_CVSD;
478 case UUID_CODEC_MSBC:
479 retval |= BTA_AG_CODEC_MSBC;
482 APPL_TRACE_ERROR("Unknown Codec UUID(%d) received", uuid_codec);
495 /*******************************************************************************
497 * Function bta_ag_process_unat_res
499 * Description Process the unat response data and remove extra carriage
500 * return and line feed
505 ******************************************************************************/
507 static void bta_ag_process_unat_res(char* unat_result) {
511 uint8_t pairs_of_nl_cr;
512 char trim_data[BTA_AG_AT_MAX_LEN];
514 str_leng = strlen(unat_result);
516 /* If no extra CR and LF, just return */
517 if (str_leng < 4) return;
519 /* Remove the carriage return and left feed */
520 while (unat_result[0] == '\r' && unat_result[1] == '\n' &&
521 unat_result[str_leng - 2] == '\r' &&
522 unat_result[str_leng - 1] == '\n') {
524 for (i = 0; i < (str_leng - 4 * pairs_of_nl_cr); i++) {
525 trim_data[j++] = unat_result[i + pairs_of_nl_cr * 2];
529 str_leng = str_leng - 4;
530 strlcpy(unat_result, trim_data, str_leng + 1);
534 if (str_leng < 4) return;
539 /*******************************************************************************
541 * Function bta_ag_inband_enabled
543 * Description Determine whether in-band ring can be used.
548 ******************************************************************************/
549 bool bta_ag_inband_enabled(tBTA_AG_SCB* p_scb) {
550 /* if feature is enabled and no other scbs connected */
551 if (p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb)) {
558 /*******************************************************************************
560 * Function bta_ag_send_call_inds
562 * Description Send call and callsetup indicators.
567 ******************************************************************************/
568 void bta_ag_send_call_inds(tBTA_AG_SCB* p_scb, tBTA_AG_RES result) {
569 uint8_t call = p_scb->call_ind;
571 /* set new call and callsetup values based on BTA_AgResult */
572 size_t callsetup = bta_ag_indicator_by_result_code(result);
574 if (result == BTA_AG_END_CALL_RES) {
575 call = BTA_AG_CALL_INACTIVE;
576 } else if (result == BTA_AG_IN_CALL_CONN_RES ||
577 result == BTA_AG_OUT_CALL_CONN_RES ||
578 result == BTA_AG_IN_CALL_HELD_RES) {
579 call = BTA_AG_CALL_ACTIVE;
581 call = p_scb->call_ind;
584 /* Send indicator function tracks if the values have actually changed */
585 bta_ag_send_ind(p_scb, BTA_AG_IND_CALL, call, false);
586 bta_ag_send_ind(p_scb, BTA_AG_IND_CALLSETUP, callsetup, false);
589 /*******************************************************************************
591 * Function bta_ag_at_hsp_cback
593 * Description AT command processing callback for HSP.
598 ******************************************************************************/
599 void bta_ag_at_hsp_cback(tBTA_AG_SCB* p_scb, uint16_t command_id,
600 uint8_t arg_type, char* p_arg, int16_t int_arg) {
601 APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", command_id, arg_type,
604 bta_ag_send_ok(p_scb);
607 val.hdr.handle = bta_ag_scb_to_idx(p_scb);
608 val.hdr.app_id = p_scb->app_id;
609 val.num = (uint16_t)int_arg;
610 strlcpy(val.str, p_arg, sizeof(val.str));
612 /* call callback with event */
613 (*bta_ag_cb.p_cback)(command_id, (tBTA_AG*)&val);
616 static void remove_spaces(char* str) {
617 char* dest_str = str;
623 *dest_str++ = *str++;
629 /*******************************************************************************
631 * Function bta_ag_find_empty_hf_ind)
633 * Description This function returns the index of an empty HF indicator
636 * Returns int : index of the empty HF indicator structure or
637 * -1 if no empty indicator
640 ******************************************************************************/
641 static int bta_ag_find_empty_hf_ind(tBTA_AG_SCB* p_scb) {
642 for (int index = 0; index < BTA_AG_MAX_NUM_PEER_HF_IND; index++) {
643 if (p_scb->peer_hf_indicators[index].ind_id == 0) return index;
649 /*******************************************************************************
651 * Function bta_ag_find_hf_ind_by_id
653 * Description This function returns the index of the HF indicator
654 * structure by the indicator id
656 * Returns int : index of the HF indicator structure
657 * -1 if the indicator
660 ******************************************************************************/
661 static int bta_ag_find_hf_ind_by_id(tBTA_AG_HF_IND* p_hf_ind, int size,
663 for (int index = 0; index < size; index++) {
664 if (p_hf_ind[index].ind_id == ind_id) return index;
670 /*******************************************************************************
672 * Function bta_ag_parse_bind_set
674 * Description Parse AT+BIND set command and save the indicators
676 * Returns true if successful
678 ******************************************************************************/
679 static bool bta_ag_parse_bind_set(tBTA_AG_SCB* p_scb, tBTA_AG_VAL val) {
680 char* p_token = strtok(val.str, ",");
681 if (p_token == NULL) return false;
683 while (p_token != NULL) {
684 uint16_t rcv_ind_id = atoi(p_token);
685 int index = bta_ag_find_empty_hf_ind(p_scb);
687 APPL_TRACE_WARNING("%s Can't save more indicators", __func__);
691 p_scb->peer_hf_indicators[index].ind_id = rcv_ind_id;
692 APPL_TRACE_DEBUG("%s peer_hf_ind[%d] = %d", __func__, index, rcv_ind_id);
694 p_token = strtok(NULL, ",");
700 /*******************************************************************************
702 * Function bta_ag_bind_response
704 * Description Send response for the AT+BIND command (HFP 1.7) received
705 * from the headset based on the argument types.
709 ******************************************************************************/
710 static void bta_ag_bind_response(tBTA_AG_SCB* p_scb, uint8_t arg_type) {
711 char buffer[BTA_AG_AT_MAX_LEN];
712 memset(buffer, 0, BTA_AG_AT_MAX_LEN);
714 if (arg_type == BTA_AG_AT_TEST) {
716 buffer[index++] = '(';
718 for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++) {
719 if (bta_ag_local_hf_ind_cfg[i + 1].is_supported) {
720 /* Add ',' from second indicator */
721 if (index > 1) buffer[index++] = ',';
722 snprintf(&buffer[index++], 2, "%d",
723 bta_ag_local_hf_ind_cfg[i + 1].ind_id);
727 buffer[index++] = ')';
729 bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
730 bta_ag_send_ok(p_scb);
731 } else if (arg_type == BTA_AG_AT_READ) {
734 /* bta_ag_local_hf_ind_cfg[0].ind_id is used as BTA_AG_NUM_LOCAL_HF_IND */
735 for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++) {
736 if (i == BTA_AG_MAX_NUM_LOCAL_HF_IND) {
737 APPL_TRACE_WARNING("%s No space for more HF indicators", __func__);
741 p_scb->local_hf_indicators[i].ind_id =
742 bta_ag_local_hf_ind_cfg[i + 1].ind_id;
743 p_scb->local_hf_indicators[i].is_supported =
744 bta_ag_local_hf_ind_cfg[i + 1].is_supported;
745 p_scb->local_hf_indicators[i].is_enable =
746 bta_ag_local_hf_ind_cfg[i + 1].is_enable;
748 int peer_index = bta_ag_find_hf_ind_by_id(
749 p_scb->peer_hf_indicators, BTA_AG_MAX_NUM_PEER_HF_IND,
750 p_scb->local_hf_indicators[i].ind_id);
752 /* Check whether local and peer sides support this indicator */
753 if (p_scb->local_hf_indicators[i].is_supported == true &&
755 /* In the format of ind, state */
756 p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].ind_id, p);
758 p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].is_enable, p);
760 bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
762 memset(buffer, 0, sizeof(buffer));
765 /* If indicator is not supported, also set it to disable */
766 p_scb->local_hf_indicators[i].is_enable = false;
770 bta_ag_send_ok(p_scb);
772 /* If the service level connection wan't already open, now it's open */
773 if (!p_scb->svc_conn) bta_ag_svc_conn_open(p_scb, NULL);
777 /*******************************************************************************
779 * Function bta_ag_parse_biev_response
781 * Description Send response for AT+BIEV command (HFP 1.7) received from
782 * the headset based on the argument types.
784 * Returns true if the response was parsed successfully
786 ******************************************************************************/
787 static bool bta_ag_parse_biev_response(tBTA_AG_SCB* p_scb, tBTA_AG_VAL* val) {
788 char* p_token = strtok(val->str, ",");
789 uint16_t rcv_ind_id = atoi(p_token);
791 p_token = strtok(NULL, ",");
792 uint16_t rcv_ind_val = atoi(p_token);
794 APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id,
797 /* Check whether indicator ID is valid or not */
798 if (rcv_ind_id > BTA_AG_NUM_LOCAL_HF_IND) {
799 APPL_TRACE_WARNING("%s received invalid indicator id %d", __func__,
804 /* Check this indicator is support or not and enabled or not */
805 int local_index = bta_ag_find_hf_ind_by_id(
806 p_scb->local_hf_indicators, BTA_AG_MAX_NUM_LOCAL_HF_IND, rcv_ind_id);
807 if (local_index == -1 ||
808 p_scb->local_hf_indicators[local_index].is_supported != true ||
809 p_scb->local_hf_indicators[local_index].is_enable != true) {
810 APPL_TRACE_WARNING("%s indicator id %d not supported or disabled", __func__,
815 /* For each indicator ID, check whether the indicator value is in range */
816 if (rcv_ind_val < bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_min_val ||
817 rcv_ind_val > bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_max_val) {
818 APPL_TRACE_WARNING("%s invalid ind_val %d", __func__, rcv_ind_val);
822 val->lidx = rcv_ind_id;
823 val->num = rcv_ind_val;
828 /*******************************************************************************
830 * Function bta_ag_at_hfp_cback
832 * Description AT command processing callback for HFP.
837 ******************************************************************************/
838 void bta_ag_at_hfp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd, uint8_t arg_type,
839 char* p_arg, int16_t int_arg) {
843 uint32_t bia_masked_out;
845 APPL_TRACE_ERROR("%s: p_arg is null, send error and return", __func__);
846 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
850 APPL_TRACE_DEBUG("%s: AT command %d, arg_type %d, int_arg %d, arg %s",
851 __func__, cmd, arg_type, int_arg, p_arg);
853 memset(&val, 0, sizeof(tBTA_AG_VAL));
854 val.hdr.handle = bta_ag_scb_to_idx(p_scb);
855 val.hdr.app_id = p_scb->app_id;
856 val.hdr.status = BTA_AG_SUCCESS;
858 val.bd_addr = p_scb->peer_addr;
859 strlcpy(val.str, p_arg, sizeof(val.str));
862 * Unless this this is a local event, by default we'll forward
863 * the event code to the application.
864 * If |event| is 0 at the end of this function, the application
865 * callback is NOT invoked.
867 tBTA_AG_EVT event = 0;
868 if (cmd < BTA_AG_LOCAL_EVT_FIRST) event = cmd;
871 case BTA_AG_AT_A_EVT:
874 case BTA_AG_AT_CHUP_EVT:
875 case BTA_AG_AT_CBC_EVT:
877 bta_ag_send_ok(p_scb);
880 case BTA_AG_AT_BLDN_EVT:
881 /* Do not send OK, App will send error or OK depending on
882 ** last dial number enabled or not */
885 case BTA_AG_AT_D_EVT:
886 /* Do not send OK for Dial cmds
887 ** Let application decide whether to send OK or ERROR*/
889 /* if mem dial cmd, make sure string contains only digits */
890 if (val.str[0] == '>') {
891 /* Some car kits may add some unwanted space characters in the
892 ** input string. This workaround will trim the unwanted chars. */
893 remove_spaces(val.str + 1);
895 if (!utl_isintstr(val.str + 1)) {
897 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
899 } else if (val.str[0] == 'V') /* ATDV : Dial VoIP Call */
901 /* We do not check string. Code will be added later if needed. */
902 if (!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) &&
903 (p_scb->features & BTA_AG_FEAT_VOIP))) {
905 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
908 /* If dial cmd, make sure string contains only dial digits
909 ** Dial digits are 0-9, A-C, *, #, + */
911 /* Some car kits may add some unwanted space characters in the
912 ** input string. This workaround will trim the unwanted chars. */
913 remove_spaces(val.str);
915 if (!utl_isdialstr(val.str)) {
917 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
922 case BTA_AG_LOCAL_EVT_CCWA:
924 p_scb->ccwa_enabled = (bool)int_arg;
927 bta_ag_send_ok(p_scb);
930 case BTA_AG_AT_CHLD_EVT:
931 if (arg_type == BTA_AG_AT_TEST) {
932 /* don't call callback */
935 /* send CHLD string */
936 /* Form string based on supported 1.5 feature */
937 if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
938 (p_scb->features & BTA_AG_FEAT_ECC) &&
939 (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
940 bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES,
941 p_bta_ag_cfg->chld_val_ecc, 0);
943 bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES,
944 p_bta_ag_cfg->chld_val, 0);
947 bta_ag_send_ok(p_scb);
949 /* if service level conn. not already open, now it's open */
950 bta_ag_svc_conn_open(p_scb, NULL);
952 val.idx = bta_ag_parse_chld(p_scb, val.str);
954 if (val.idx == BTA_AG_INVALID_CHLD) {
956 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
960 !((p_scb->features & BTA_AG_FEAT_ECC) &&
961 (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))) {
962 /* we do not support ECC, but HF is sending us a CHLD with call
965 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
968 /* If it is swap between calls, set call held indicator to 3(out of
970 ** Application will set it back to 1
971 ** callheld indicator will be sent across to the peer. */
972 if (val.str[0] == '2') {
973 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB;
975 if (ag_scb->in_use) {
976 if ((ag_scb->call_ind == BTA_AG_CALL_ACTIVE) &&
977 (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
978 ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1;
984 /* Do not send OK. Let app decide after parsing the val str */
985 /* bta_ag_send_ok(p_scb); */
989 case BTA_AG_AT_BIND_EVT:
990 APPL_TRACE_DEBUG("%s BTA_AG_AT_BIND_EVT arg_type: %d", __func__,
992 if (arg_type == BTA_AG_AT_SET) {
993 if (bta_ag_parse_bind_set(p_scb, val)) {
994 bta_ag_send_ok(p_scb);
996 event = 0; /* don't call callback */
997 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
1000 bta_ag_bind_response(p_scb, arg_type);
1002 /* Need not pass this command beyond BTIF.*/
1003 /* Stack handles it internally */
1004 event = 0; /* don't call callback */
1008 case BTA_AG_AT_BIEV_EVT:
1009 if (bta_ag_parse_biev_response(p_scb, &val)) {
1010 bta_ag_send_ok(p_scb);
1012 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
1013 /* don't call callback receiving invalid indicator */
1018 case BTA_AG_AT_CIND_EVT:
1019 if (arg_type == BTA_AG_AT_TEST) {
1020 /* don't call callback */
1023 /* send CIND string, send OK */
1024 bta_ag_send_result(p_scb, BTA_AG_CIND_RES, p_bta_ag_cfg->cind_info, 0);
1025 bta_ag_send_ok(p_scb);
1029 case BTA_AG_LOCAL_EVT_CLIP:
1030 /* store setting, send OK */
1031 p_scb->clip_enabled = (bool)int_arg;
1032 bta_ag_send_ok(p_scb);
1035 case BTA_AG_LOCAL_EVT_CMER:
1036 /* if parsed ok store setting, send OK */
1037 if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled)) {
1038 bta_ag_send_ok(p_scb);
1040 /* if service level conn. not already open and our features and
1041 ** peer features do not have 3-way, service level conn. now open
1043 if (!p_scb->svc_conn &&
1044 !((p_scb->features & BTA_AG_FEAT_3WAY) &&
1045 (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY))) {
1046 bta_ag_svc_conn_open(p_scb, NULL);
1049 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1053 case BTA_AG_AT_VTS_EVT:
1054 /* check argument */
1055 if (strlen(p_arg) == 1) {
1056 bta_ag_send_ok(p_scb);
1059 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1063 case BTA_AG_AT_BINP_EVT:
1064 /* if feature not set don't call callback, send ERROR */
1065 if (!(p_scb->features & BTA_AG_FEAT_VTAG)) {
1067 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1071 case BTA_AG_AT_BVRA_EVT:
1072 /* if feature not supported don't call callback, send ERROR. App will send
1074 if (!(p_scb->features & BTA_AG_FEAT_VREC)) {
1076 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1080 case BTA_AG_LOCAL_EVT_BRSF: {
1081 /* store peer features */
1082 p_scb->peer_features = (uint16_t)int_arg;
1084 tBTA_AG_FEAT features = p_scb->features;
1085 if (p_scb->peer_version < HFP_VERSION_1_7) {
1086 features &= HFP_1_6_FEAT_MASK;
1089 APPL_TRACE_DEBUG("%s BRSF HF: 0x%x, phone: 0x%x", __func__,
1090 p_scb->peer_features, features);
1092 /* send BRSF, send OK */
1093 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, NULL, (int16_t)features);
1094 bta_ag_send_ok(p_scb);
1098 case BTA_AG_AT_NREC_EVT:
1099 /* if feature send OK, else don't call callback, send ERROR */
1100 if (p_scb->features & BTA_AG_FEAT_ECNR) {
1101 bta_ag_send_ok(p_scb);
1104 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1108 case BTA_AG_AT_BTRH_EVT:
1109 /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
1110 if (p_scb->features & BTA_AG_FEAT_BTRH) {
1111 /* If set command; send response and notify app */
1112 if (arg_type == BTA_AG_AT_SET) {
1113 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB;
1115 if (ag_scb->in_use) {
1116 bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, NULL, int_arg);
1119 bta_ag_send_ok(p_scb);
1120 } else /* Read Command */
1122 val.num = BTA_AG_BTRH_READ;
1126 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1130 case BTA_AG_AT_COPS_EVT:
1131 if (arg_type == BTA_AG_AT_SET) {
1132 /* don't call callback */
1136 bta_ag_send_ok(p_scb);
1140 case BTA_AG_LOCAL_EVT_CMEE:
1141 if (p_scb->features & BTA_AG_FEAT_EXTERR) {
1143 p_scb->cmee_enabled = (bool)int_arg;
1146 bta_ag_send_ok(p_scb);
1148 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1150 /* don't call callback */
1154 case BTA_AG_LOCAL_EVT_BIA:
1155 /* don't call callback */
1158 bia_masked_out = p_scb->bia_masked_out;
1160 /* Parse the indicator mask */
1161 for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20);
1163 if (val.str[i] == ',') continue;
1165 if (val.str[i] == '0')
1166 bia_masked_out |= ((uint32_t)1 << ind_id);
1167 else if (val.str[i] == '1')
1168 bia_masked_out &= ~((uint32_t)1 << ind_id);
1173 if ((val.str[i] == 0) || (val.str[i] != ',')) break;
1175 if (val.str[i] == 0) {
1176 p_scb->bia_masked_out = bia_masked_out;
1177 bta_ag_send_ok(p_scb);
1179 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
1182 case BTA_AG_AT_CNUM_EVT:
1185 case BTA_AG_AT_CLCC_EVT:
1186 if (!(p_scb->features & BTA_AG_FEAT_ECS)) {
1188 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1192 case BTA_AG_AT_BAC_EVT:
1193 bta_ag_send_ok(p_scb);
1195 /* store available codecs from the peer */
1196 if ((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) &&
1197 (p_scb->features & BTA_AG_FEAT_CODEC)) {
1198 p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
1199 p_scb->codec_updated = true;
1201 if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC) {
1202 p_scb->sco_codec = UUID_CODEC_MSBC;
1203 APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to MSBC");
1205 p_scb->sco_codec = UUID_CODEC_CVSD;
1206 APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to CVSD");
1208 /* The above logic sets the stack preferred codec based on local and
1210 capabilities. This can be overridden by the application depending on its
1212 using the bta_ag_setcodec API. We send the peer_codecs to the
1214 val.num = p_scb->peer_codecs;
1215 /* Received BAC while in codec negotiation. */
1216 if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) &&
1217 (bta_ag_cb.sco.p_curr_scb == p_scb)) {
1218 bta_ag_codec_negotiate(p_scb);
1221 p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
1223 "Unexpected CMD:AT+BAC, Codec Negotiation is not supported");
1227 case BTA_AG_AT_BCS_EVT: {
1228 tBTA_AG_PEER_CODEC codec_type, codec_sent;
1229 bta_ag_send_ok(p_scb);
1230 alarm_cancel(p_scb->codec_negotiation_timer);
1233 case UUID_CODEC_CVSD:
1234 codec_type = BTA_AG_CODEC_CVSD;
1236 case UUID_CODEC_MSBC:
1237 codec_type = BTA_AG_CODEC_MSBC;
1240 APPL_TRACE_ERROR("Unknown codec_uuid %d", int_arg);
1241 codec_type = 0xFFFF;
1245 if (p_scb->codec_fallback)
1246 codec_sent = BTA_AG_CODEC_CVSD;
1248 codec_sent = p_scb->sco_codec;
1250 if (codec_type == codec_sent)
1251 bta_ag_sco_codec_nego(p_scb, true);
1253 bta_ag_sco_codec_nego(p_scb, false);
1255 /* send final codec info to callback */
1256 val.num = codec_sent;
1259 case BTA_AG_LOCAL_EVT_BCC:
1260 bta_ag_send_ok(p_scb);
1261 bta_ag_sco_open(p_scb, NULL);
1265 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1271 (*bta_ag_cb.p_cback)(event, (tBTA_AG*)&val);
1275 /*******************************************************************************
1277 * Function bta_ag_at_err_cback
1279 * Description AT command parser error callback.
1284 ******************************************************************************/
1285 void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown, char* p_arg) {
1288 if (unknown && (!strlen(p_arg))) {
1289 APPL_TRACE_DEBUG("Empty AT cmd string received");
1290 bta_ag_send_ok(p_scb);
1294 /* if unknown AT command and configured to pass these to app */
1295 if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT)) {
1296 val.hdr.handle = bta_ag_scb_to_idx(p_scb);
1297 val.hdr.app_id = p_scb->app_id;
1298 val.hdr.status = BTA_AG_SUCCESS;
1300 strlcpy(val.str, p_arg, sizeof(val.str));
1301 (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG*)&val);
1303 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1307 /*******************************************************************************
1309 * Function bta_ag_hsp_result
1311 * Description Handle API result for HSP connections.
1316 ******************************************************************************/
1317 void bta_ag_hsp_result(tBTA_AG_SCB* p_scb, tBTA_AG_API_RESULT* p_result) {
1318 APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result);
1320 switch (p_result->result) {
1321 case BTA_AG_SPK_RES:
1322 case BTA_AG_MIC_RES:
1323 bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
1326 case BTA_AG_IN_CALL_RES:
1327 /* tell sys to stop av if any */
1328 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1330 /* if sco already opened or no inband ring send ring now */
1331 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
1332 (p_scb->features & BTA_AG_FEAT_NOSCO)) {
1333 bta_ag_send_ring(p_scb, (tBTA_AG_DATA*)p_result);
1335 /* else open sco, send ring after sco opened */
1336 /* HSPv1.2: AG shall not send RING if using in-band ring tone. */
1337 if (p_scb->peer_version >= HSP_VERSION_1_2) {
1338 p_scb->post_sco = BTA_AG_POST_SCO_NONE;
1340 p_scb->post_sco = BTA_AG_POST_SCO_RING;
1342 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1346 case BTA_AG_IN_CALL_CONN_RES:
1347 case BTA_AG_OUT_CALL_ORIG_RES:
1348 /* if incoming call connected stop ring timer */
1349 if (p_result->result == BTA_AG_IN_CALL_CONN_RES) {
1350 alarm_cancel(p_scb->ring_timer);
1353 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1354 /* if audio connected to this scb AND sco is not opened, open sco */
1355 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1356 !bta_ag_sco_is_open(p_scb)) {
1357 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1359 /* else if no audio at call close sco */
1360 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
1361 bta_ag_sco_is_open(p_scb)) {
1362 bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
1367 case BTA_AG_END_CALL_RES:
1368 alarm_cancel(p_scb->ring_timer);
1371 if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) &&
1372 !(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1373 bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
1375 /* if av got suspended by this call, let it resume. */
1376 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1380 case BTA_AG_INBAND_RING_RES:
1381 p_scb->inband_enabled = p_result->data.state;
1382 APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
1385 case BTA_AG_UNAT_RES:
1386 if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
1387 if (p_result->data.str[0] != 0) {
1388 bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
1391 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
1393 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1398 /* ignore all others */
1403 /*******************************************************************************
1405 * Function bta_ag_hfp_result
1407 * Description Handle API result for HFP connections.
1412 ******************************************************************************/
1413 void bta_ag_hfp_result(tBTA_AG_SCB* p_scb, tBTA_AG_API_RESULT* p_result) {
1414 APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
1416 switch (p_result->result) {
1417 case BTA_AG_SPK_RES:
1418 case BTA_AG_MIC_RES:
1419 bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
1422 case BTA_AG_IN_CALL_RES:
1423 /* tell sys to stop av if any */
1424 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1426 /* store caller id string.
1427 * append type info at the end.
1428 * make sure a valid type info is passed.
1429 * otherwise add 129 as default type */
1430 if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) ||
1431 (p_result->data.num > BTA_AG_CLIP_TYPE_MAX)) {
1432 if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
1433 p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
1436 APPL_TRACE_DEBUG("CLIP type :%d", p_result->data.num);
1438 if (p_result->data.str[0] != 0)
1439 snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", p_result->data.str,
1440 p_result->data.num);
1442 /* send callsetup indicator */
1443 if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END) {
1444 /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO
1446 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
1448 bta_ag_send_call_inds(p_scb, p_result->result);
1450 /* if sco already opened or no inband ring send ring now */
1451 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
1452 (p_scb->features & BTA_AG_FEAT_NOSCO)) {
1453 bta_ag_send_ring(p_scb, (tBTA_AG_DATA*)p_result);
1455 /* else open sco, send ring after sco opened */
1456 p_scb->post_sco = BTA_AG_POST_SCO_RING;
1457 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1462 case BTA_AG_IN_CALL_CONN_RES:
1463 alarm_cancel(p_scb->ring_timer);
1465 /* if sco not opened and we need to open it, send indicators first
1468 bta_ag_send_call_inds(p_scb, p_result->result);
1470 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1471 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1472 !bta_ag_sco_is_open(p_scb)) {
1473 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1474 } else if ((p_result->data.audio_handle == BTA_AG_HANDLE_NONE) &&
1475 bta_ag_sco_is_open(p_scb)) {
1476 bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
1481 case BTA_AG_IN_CALL_HELD_RES:
1482 alarm_cancel(p_scb->ring_timer);
1484 bta_ag_send_call_inds(p_scb, p_result->result);
1488 case BTA_AG_OUT_CALL_ORIG_RES:
1489 bta_ag_send_call_inds(p_scb, p_result->result);
1490 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1491 !(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1492 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1496 case BTA_AG_OUT_CALL_ALERT_RES:
1497 /* send indicators */
1498 bta_ag_send_call_inds(p_scb, p_result->result);
1499 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1500 !(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1501 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1505 case BTA_AG_MULTI_CALL_RES:
1506 /* open SCO at SLC for this three way call */
1507 APPL_TRACE_DEBUG("Headset Connected in three way call");
1508 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1509 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1510 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1511 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
1512 bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
1516 case BTA_AG_OUT_CALL_CONN_RES:
1517 /* send indicators */
1518 bta_ag_send_call_inds(p_scb, p_result->result);
1520 /* open or close sco */
1521 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1522 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb)) {
1523 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result);
1524 } else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE) {
1525 bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
1530 case BTA_AG_CALL_CANCEL_RES:
1531 /* send indicators */
1532 bta_ag_send_call_inds(p_scb, p_result->result);
1535 case BTA_AG_END_CALL_RES:
1536 alarm_cancel(p_scb->ring_timer);
1538 /* if sco open, close sco then send indicator values */
1539 if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) &&
1540 !(p_scb->features & BTA_AG_FEAT_NOSCO)) {
1541 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
1542 bta_ag_sco_close(p_scb, (tBTA_AG_DATA*)p_result);
1543 } else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL) {
1544 /* sco closing for outgoing call because of incoming call */
1545 /* Send only callsetup end indicator after sco close */
1546 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
1548 bta_ag_send_call_inds(p_scb, p_result->result);
1550 /* if av got suspended by this call, let it resume. */
1551 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1555 case BTA_AG_INBAND_RING_RES:
1556 p_scb->inband_enabled = p_result->data.state;
1557 APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
1558 bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
1561 case BTA_AG_CIND_RES:
1562 /* store local values */
1563 p_scb->call_ind = p_result->data.str[0] - '0';
1564 p_scb->callsetup_ind = p_result->data.str[2] - '0';
1565 p_scb->service_ind = p_result->data.str[4] - '0';
1566 p_scb->signal_ind = p_result->data.str[6] - '0';
1567 p_scb->roam_ind = p_result->data.str[8] - '0';
1568 p_scb->battchg_ind = p_result->data.str[10] - '0';
1569 p_scb->callheld_ind = p_result->data.str[12] - '0';
1570 APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind,
1571 p_scb->callsetup_ind);
1573 bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
1574 bta_ag_send_ok(p_scb);
1577 case BTA_AG_BINP_RES:
1578 case BTA_AG_CNUM_RES:
1579 case BTA_AG_CLCC_RES:
1580 case BTA_AG_COPS_RES:
1581 if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
1582 if (p_result->data.str[0] != 0) {
1583 bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
1586 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
1588 bta_ag_send_error(p_scb, p_result->data.errcode);
1592 case BTA_AG_UNAT_RES:
1593 if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
1594 if (p_result->data.str[0] != 0) {
1595 bta_ag_process_unat_res(p_result->data.str);
1596 APPL_TRACE_DEBUG("BTA_AG_RES :%s", p_result->data.str);
1597 bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
1600 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
1602 bta_ag_send_error(p_scb, p_result->data.errcode);
1606 case BTA_AG_CALL_WAIT_RES:
1607 if (p_scb->ccwa_enabled) {
1608 bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
1610 bta_ag_send_call_inds(p_scb, p_result->result);
1613 case BTA_AG_IND_RES:
1614 bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value,
1618 case BTA_AG_BVRA_RES:
1619 bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
1622 case BTA_AG_BTRH_RES:
1623 if (p_result->data.ok_flag != BTA_AG_OK_ERROR) {
1624 /* Don't respond to read if not in response & hold state */
1625 if (p_result->data.num != BTA_AG_BTRH_NO_RESP) {
1626 bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
1629 /* In case of a response to a read request we need to send OK */
1630 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb);
1632 bta_ag_send_error(p_scb, p_result->data.errcode);
1636 case BTA_AG_BIND_RES: {
1637 /* Find whether ind_id is supported by local device or not */
1638 int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators,
1639 BTA_AG_MAX_NUM_LOCAL_HF_IND,
1640 p_result->data.ind.id);
1641 if (local_index == -1) {
1642 APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
1643 p_result->data.ind.id);
1647 /* Find whether ind_id is supported by peer device or not */
1648 int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators,
1649 BTA_AG_MAX_NUM_PEER_HF_IND,
1650 p_result->data.ind.id);
1651 if (peer_index == -1) {
1652 APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
1653 p_result->data.ind.id);
1656 /* If the current state is different from the one upper layer request
1657 change current state and send out the result */
1658 if (p_scb->local_hf_indicators[local_index].is_enable !=
1659 p_result->data.ind.on_demand) {
1660 char buffer[BTA_AG_AT_MAX_LEN] = {0};
1663 p_scb->local_hf_indicators[local_index].is_enable =
1664 p_result->data.ind.on_demand;
1665 p += utl_itoa(p_result->data.ind.id, p);
1667 p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p);
1669 bta_ag_send_result(p_scb, p_result->result, buffer, 0);
1672 "%s HF Indicator %d already %s", p_result->data.ind.id,
1673 (p_result->data.ind.on_demand == true) ? "Enabled" : "Disabled");
1684 /*******************************************************************************
1686 * Function bta_ag_result
1688 * Description Handle API result.
1693 ******************************************************************************/
1694 void bta_ag_result(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
1695 if (p_scb->conn_service == BTA_AG_HSP) {
1696 bta_ag_hsp_result(p_scb, &p_data->api_result);
1698 bta_ag_hfp_result(p_scb, &p_data->api_result);
1702 /*******************************************************************************
1704 * Function bta_ag_send_bcs
1706 * Description Send +BCS AT command to peer.
1710 ******************************************************************************/
1711 void bta_ag_send_bcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
1712 uint16_t codec_uuid;
1714 if (p_scb->codec_fallback) {
1715 codec_uuid = UUID_CODEC_CVSD;
1717 switch (p_scb->sco_codec) {
1718 case BTA_AG_CODEC_NONE:
1719 codec_uuid = UUID_CODEC_CVSD;
1721 case BTA_AG_CODEC_CVSD:
1722 codec_uuid = UUID_CODEC_CVSD;
1724 case BTA_AG_CODEC_MSBC:
1725 codec_uuid = UUID_CODEC_MSBC;
1728 APPL_TRACE_ERROR("bta_ag_send_bcs: unknown codec %d, use CVSD",
1730 codec_uuid = UUID_CODEC_CVSD;
1736 APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid);
1737 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BCS, NULL, codec_uuid);
1740 /*******************************************************************************
1742 * Function bta_ag_send_ring
1744 * Description Send RING result code to peer.
1749 ******************************************************************************/
1750 void bta_ag_send_ring(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1752 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, NULL, 0);
1754 /* if HFP and clip enabled and clip data send CLIP */
1755 if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled &&
1756 p_scb->clip[0] != 0) {
1757 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CLIP, p_scb->clip, 0);
1760 bta_sys_start_timer(p_scb->ring_timer, BTA_AG_RING_TIMEOUT_MS,
1761 BTA_AG_RING_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));