1 /****************************************************************************** 2 * 3 * Copyright 2004-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 #define LOG_TAG "bta_ag_cmd" 20 21 #include <cctype> 22 #include <cstdio> 23 #include <cstring> 24 25 #include "bt_common.h" 26 #include "bt_target.h" 27 #include "bt_types.h" 28 #include "bta_ag_api.h" 29 #include "bta_ag_at.h" 30 #include "bta_ag_int.h" 31 #include "bta_api.h" 32 #include "bta_sys.h" 33 #include "osi/include/log.h" 34 #include "osi/include/osi.h" 35 #include "port_api.h" 36 #include "utl.h" 37 38 /***************************************************************************** 39 * Constants 40 ****************************************************************************/ 41 42 /* Ring timeout */ 43 #define BTA_AG_RING_TIMEOUT_MS (5 * 1000) /* 5 seconds */ 44 45 #define BTA_AG_CMD_MAX_VAL 32767 /* Maximum value is signed 16-bit value */ 46 47 /* Invalid Chld command */ 48 #define BTA_AG_INVALID_CHLD 255 49 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 55 56 #define COLON_IDX_4_VGSVGM 4 57 58 /* Local events which will not trigger a higher layer callback */ 59 enum { 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, 66 BTA_AG_LOCAL_EVT_BCC, 67 }; 68 69 /* AT command interpreter table for HSP */ 70 const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] = { 71 {"+CKPD", BTA_AG_AT_CKPD_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 200, 200}, 72 {"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15}, 73 {"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15}, 74 /* End-of-table marker used to stop lookup iteration */ 75 {"", 0, 0, 0, 0, 0}}; 76 77 /* AT command interpreter table for HFP */ 78 const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] = { 79 {"A", BTA_AG_AT_A_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}, 80 {"D", BTA_AG_AT_D_EVT, BTA_AG_AT_NONE | BTA_AG_AT_FREE, BTA_AG_AT_STR, 0, 81 0}, 82 {"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15}, 83 {"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15}, 84 {"+CCWA", BTA_AG_LOCAL_EVT_CCWA, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1}, 85 /* Consider CHLD as str to take care of indexes for ECC */ 86 {"+CHLD", BTA_AG_AT_CHLD_EVT, BTA_AG_AT_SET | BTA_AG_AT_TEST, BTA_AG_AT_STR, 87 0, 4}, 88 {"+CHUP", BTA_AG_AT_CHUP_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}, 89 {"+CIND", BTA_AG_AT_CIND_EVT, BTA_AG_AT_READ | BTA_AG_AT_TEST, 90 BTA_AG_AT_STR, 0, 0}, 91 {"+CLIP", BTA_AG_LOCAL_EVT_CLIP, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1}, 92 {"+CMER", BTA_AG_LOCAL_EVT_CMER, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0}, 93 {"+VTS", BTA_AG_AT_VTS_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0}, 94 {"+BINP", BTA_AG_AT_BINP_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 1, 1}, 95 {"+BLDN", BTA_AG_AT_BLDN_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}, 96 {"+BVRA", BTA_AG_AT_BVRA_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1}, 97 {"+BRSF", BTA_AG_LOCAL_EVT_BRSF, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 98 BTA_AG_CMD_MAX_VAL}, 99 {"+NREC", BTA_AG_AT_NREC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 0}, 100 {"+CNUM", BTA_AG_AT_CNUM_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}, 101 {"+BTRH", BTA_AG_AT_BTRH_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_INT, 102 0, 2}, 103 {"+CLCC", BTA_AG_AT_CLCC_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}, 104 {"+COPS", BTA_AG_AT_COPS_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_STR, 105 0, 0}, 106 {"+CMEE", BTA_AG_LOCAL_EVT_CMEE, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1}, 107 {"+BIA", BTA_AG_AT_BIA_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20}, 108 {"+CBC", BTA_AG_AT_CBC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100}, 109 {"+BCC", BTA_AG_LOCAL_EVT_BCC, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}, 110 {"+BCS", BTA_AG_AT_BCS_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 111 BTA_AG_CMD_MAX_VAL}, 112 {"+BIND", BTA_AG_AT_BIND_EVT, 113 BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0}, 114 {"+BIEV", BTA_AG_AT_BIEV_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0}, 115 {"+BAC", BTA_AG_AT_BAC_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0}, 116 /* End-of-table marker used to stop lookup iteration */ 117 {"", 0, 0, 0, 0, 0}}; 118 119 /* AT result code table element */ 120 typedef struct { 121 const char* result_string; /* AT result string */ 122 size_t result_id; /* Local or BTA result id */ 123 uint8_t arg_type; /* whether argument is int or string */ 124 } tBTA_AG_RESULT; 125 126 /* AT result code argument types */ 127 enum { 128 BTA_AG_RES_FMT_NONE, /* no argument */ 129 BTA_AG_RES_FMT_INT, /* integer argument */ 130 BTA_AG_RES_FMT_STR /* string argument */ 131 }; 132 133 /* Local AT command result codes not defined in bta_ag_api.h */ 134 enum { 135 BTA_AG_LOCAL_RES_FIRST = 0x0100, 136 BTA_AG_LOCAL_RES_OK, 137 BTA_AG_LOCAL_RES_ERROR, 138 BTA_AG_LOCAL_RES_RING, 139 BTA_AG_LOCAL_RES_CLIP, 140 BTA_AG_LOCAL_RES_BRSF, 141 BTA_AG_LOCAL_RES_CMEE, 142 BTA_AG_LOCAL_RES_BCS 143 }; 144 145 /* AT result code constant table */ 146 const tBTA_AG_RESULT bta_ag_result_tbl[] = { 147 {"OK", BTA_AG_LOCAL_RES_OK, BTA_AG_RES_FMT_NONE}, 148 {"ERROR", BTA_AG_LOCAL_RES_ERROR, BTA_AG_RES_FMT_NONE}, 149 {"RING", BTA_AG_LOCAL_RES_RING, BTA_AG_RES_FMT_NONE}, 150 {"+VGS: ", BTA_AG_SPK_RES, BTA_AG_RES_FMT_INT}, 151 {"+VGM: ", BTA_AG_MIC_RES, BTA_AG_RES_FMT_INT}, 152 {"+CCWA: ", BTA_AG_CALL_WAIT_RES, BTA_AG_RES_FMT_STR}, 153 {"+CHLD: ", BTA_AG_IN_CALL_HELD_RES, BTA_AG_RES_FMT_STR}, 154 {"+CIND: ", BTA_AG_CIND_RES, BTA_AG_RES_FMT_STR}, 155 {"+CLIP: ", BTA_AG_LOCAL_RES_CLIP, BTA_AG_RES_FMT_STR}, 156 {"+CIEV: ", BTA_AG_IND_RES, BTA_AG_RES_FMT_STR}, 157 {"+BINP: ", BTA_AG_BINP_RES, BTA_AG_RES_FMT_STR}, 158 {"+BVRA: ", BTA_AG_BVRA_RES, BTA_AG_RES_FMT_INT}, 159 {"+BRSF: ", BTA_AG_LOCAL_RES_BRSF, BTA_AG_RES_FMT_INT}, 160 {"+BSIR: ", BTA_AG_INBAND_RING_RES, BTA_AG_RES_FMT_INT}, 161 {"+CNUM: ", BTA_AG_CNUM_RES, BTA_AG_RES_FMT_STR}, 162 {"+BTRH: ", BTA_AG_BTRH_RES, BTA_AG_RES_FMT_INT}, 163 {"+CLCC: ", BTA_AG_CLCC_RES, BTA_AG_RES_FMT_STR}, 164 {"+COPS: ", BTA_AG_COPS_RES, BTA_AG_RES_FMT_STR}, 165 {"+CME ERROR: ", BTA_AG_LOCAL_RES_CMEE, BTA_AG_RES_FMT_INT}, 166 {"+BCS: ", BTA_AG_LOCAL_RES_BCS, BTA_AG_RES_FMT_INT}, 167 {"+BIND: ", BTA_AG_BIND_RES, BTA_AG_RES_FMT_STR}, 168 {"", BTA_AG_UNAT_RES, BTA_AG_RES_FMT_STR}}; 169 170 static const tBTA_AG_RESULT* bta_ag_result_by_code(size_t code) { 171 for (size_t i = 0; 172 i != sizeof(bta_ag_result_tbl) / sizeof(bta_ag_result_tbl[0]); ++i) { 173 if (code == bta_ag_result_tbl[i].result_id) return &bta_ag_result_tbl[i]; 174 } 175 return nullptr; 176 } 177 178 const tBTA_AG_AT_CMD* bta_ag_at_tbl[BTA_AG_NUM_IDX] = {bta_ag_hsp_cmd, 179 bta_ag_hfp_cmd}; 180 181 typedef struct { 182 size_t result_code; 183 size_t indicator; 184 } tBTA_AG_INDICATOR_MAP; 185 186 /* callsetup indicator value lookup table */ 187 const tBTA_AG_INDICATOR_MAP callsetup_indicator_map[] = { 188 {BTA_AG_IN_CALL_RES, BTA_AG_CALLSETUP_INCOMING}, 189 {BTA_AG_CALL_WAIT_RES, BTA_AG_CALLSETUP_INCOMING}, 190 {BTA_AG_OUT_CALL_ORIG_RES, BTA_AG_CALLSETUP_OUTGOING}, 191 {BTA_AG_OUT_CALL_ALERT_RES, BTA_AG_CALLSETUP_ALERTING}}; 192 193 static size_t bta_ag_indicator_by_result_code(size_t code) { 194 for (size_t i = 0; 195 i != 196 sizeof(callsetup_indicator_map) / sizeof(callsetup_indicator_map[0]); 197 ++i) { 198 if (code == callsetup_indicator_map[i].result_code) 199 return callsetup_indicator_map[i].indicator; 200 } 201 return BTA_AG_CALLSETUP_NONE; 202 } 203 204 /******************************************************************************* 205 * 206 * Function bta_ag_send_result 207 * 208 * Description Send an AT result code. 209 * 210 * 211 * Returns void 212 * 213 ******************************************************************************/ 214 static void bta_ag_send_result(tBTA_AG_SCB* p_scb, size_t code, 215 const char* p_arg, int16_t int_arg) { 216 const tBTA_AG_RESULT* result = bta_ag_result_by_code(code); 217 if (result == nullptr) { 218 LOG_ERROR(LOG_TAG, "%s Unable to lookup result for code %zu", __func__, 219 code); 220 return; 221 } 222 223 char buf[BTA_AG_AT_MAX_LEN + 16] = ""; 224 char* p = buf; 225 226 /* init with \r\n */ 227 *p++ = '\r'; 228 *p++ = '\n'; 229 230 /* copy result code string */ 231 strlcpy(p, result->result_string, sizeof(buf) - 2); 232 233 if (p_scb->conn_service == BTA_AG_HSP) { 234 /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */ 235 switch (code) { 236 case BTA_AG_SPK_RES: 237 case BTA_AG_MIC_RES: 238 if (*(p + COLON_IDX_4_VGSVGM) == ':') { 239 *(p + COLON_IDX_4_VGSVGM) = '='; 240 } 241 break; 242 } 243 } 244 245 p += strlen(result->result_string); 246 247 /* copy argument if any */ 248 if (result->arg_type == BTA_AG_RES_FMT_INT) { 249 p += utl_itoa((uint16_t)int_arg, p); 250 } else if (result->arg_type == BTA_AG_RES_FMT_STR) { 251 strcpy(p, p_arg); 252 p += strlen(p_arg); 253 } 254 255 /* finish with \r\n */ 256 *p++ = '\r'; 257 *p++ = '\n'; 258 259 /* send to RFCOMM */ 260 uint16_t len = 0; 261 PORT_WriteData(p_scb->conn_handle, buf, (uint16_t)(p - buf), &len); 262 } 263 264 /******************************************************************************* 265 * 266 * Function bta_ag_send_ok 267 * 268 * Description Send an OK result code. 269 * 270 * 271 * Returns void 272 * 273 ******************************************************************************/ 274 static void bta_ag_send_ok(tBTA_AG_SCB* p_scb) { 275 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_OK, nullptr, 0); 276 } 277 278 /******************************************************************************* 279 * 280 * Function bta_ag_send_error 281 * 282 * Description Send an ERROR result code. 283 * errcode - used to send verbose errocode 284 * 285 * 286 * Returns void 287 * 288 ******************************************************************************/ 289 static void bta_ag_send_error(tBTA_AG_SCB* p_scb, int16_t errcode) { 290 /* If HFP and extended audio gateway error codes are enabled */ 291 if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled) 292 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CMEE, nullptr, errcode); 293 else 294 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, nullptr, 0); 295 } 296 297 /******************************************************************************* 298 * 299 * Function bta_ag_send_ind 300 * 301 * Description Send an indicator CIEV result code. 302 * 303 * 304 * Returns void 305 * 306 ******************************************************************************/ 307 static void bta_ag_send_ind(tBTA_AG_SCB* p_scb, uint16_t id, uint16_t value, 308 bool on_demand) { 309 char str[12]; 310 char* p = str; 311 312 /* If the indicator is masked out, just return */ 313 /* Mandatory indicators can not be masked out. */ 314 if ((p_scb->bia_masked_out & ((uint32_t)1 << id)) && 315 ((id != BTA_AG_IND_CALL) && (id != BTA_AG_IND_CALLSETUP) && 316 (id != BTA_AG_IND_CALLHELD))) 317 return; 318 319 /* Ensure we do not send duplicate indicators if not requested by app */ 320 /* If it was requested by app, transmit CIEV even if it is duplicate. */ 321 if (id == BTA_AG_IND_CALL) { 322 if ((value == p_scb->call_ind) && (!on_demand)) return; 323 324 p_scb->call_ind = (uint8_t)value; 325 } 326 327 if ((id == BTA_AG_IND_CALLSETUP) && (!on_demand)) { 328 if (value == p_scb->callsetup_ind) return; 329 330 p_scb->callsetup_ind = (uint8_t)value; 331 } 332 333 if ((id == BTA_AG_IND_SERVICE) && (!on_demand)) { 334 if (value == p_scb->service_ind) return; 335 336 p_scb->service_ind = (uint8_t)value; 337 } 338 if ((id == BTA_AG_IND_SIGNAL) && (!on_demand)) { 339 if (value == p_scb->signal_ind) return; 340 341 p_scb->signal_ind = (uint8_t)value; 342 } 343 if ((id == BTA_AG_IND_ROAM) && (!on_demand)) { 344 if (value == p_scb->roam_ind) return; 345 346 p_scb->roam_ind = (uint8_t)value; 347 } 348 if ((id == BTA_AG_IND_BATTCHG) && (!on_demand)) { 349 if (value == p_scb->battchg_ind) return; 350 351 p_scb->battchg_ind = (uint8_t)value; 352 } 353 354 if ((id == BTA_AG_IND_CALLHELD) && (!on_demand)) { 355 /* call swap could result in sending callheld=1 multiple times */ 356 if ((value != 1) && (value == p_scb->callheld_ind)) return; 357 358 p_scb->callheld_ind = (uint8_t)value; 359 } 360 361 if (p_scb->cmer_enabled) { 362 p += utl_itoa(id, p); 363 *p++ = ','; 364 utl_itoa(value, p); 365 bta_ag_send_result(p_scb, BTA_AG_IND_RES, str, 0); 366 } 367 } 368 369 /******************************************************************************* 370 * 371 * Function bta_ag_parse_cmer 372 * 373 * Description Parse AT+CMER parameter string. 374 * 375 * 376 * Returns true if parsed ok, false otherwise. 377 * 378 ******************************************************************************/ 379 static bool bta_ag_parse_cmer(char* p_s, bool* p_enabled) { 380 int16_t n[4] = {-1, -1, -1, -1}; 381 int i; 382 char* p; 383 384 for (i = 0; i < 4; i++) { 385 /* skip to comma delimiter */ 386 for (p = p_s; *p != ',' && *p != 0; p++) 387 ; 388 389 /* get integer value */ 390 *p = 0; 391 n[i] = utl_str2int(p_s); 392 p_s = p + 1; 393 if (p_s == nullptr) { 394 break; 395 } 396 } 397 398 /* process values */ 399 if (n[0] < 0 || n[3] < 0) { 400 return false; 401 } 402 403 if ((n[0] == 3) && ((n[3] == 1) || (n[3] == 0))) { 404 *p_enabled = (bool)n[3]; 405 } 406 407 return true; 408 } 409 410 /******************************************************************************* 411 * 412 * Function bta_ag_parse_chld 413 * 414 * Description Parse AT+CHLD parameter string. 415 * 416 * 417 * Returns Returns idx (1-7), 0 if ECC not enabled or 418 BTA_AG_INVALID_CHLD 419 if idx doesn't exist/1st character of argument is not a 420 digit 421 * 422 ******************************************************************************/ 423 static uint8_t bta_ag_parse_chld(UNUSED_ATTR tBTA_AG_SCB* p_scb, char* p_s) { 424 uint8_t retval = 0; 425 426 if (!isdigit(p_s[0])) { 427 return BTA_AG_INVALID_CHLD; 428 } 429 430 if (p_s[1] != 0) { 431 /* p_idxstr++; point to beginning of call number */ 432 int16_t idx = utl_str2int(&p_s[1]); 433 if (idx != -1 && idx < 255) { 434 retval = (uint8_t)idx; 435 } else { 436 retval = BTA_AG_INVALID_CHLD; 437 } 438 } 439 440 return (retval); 441 } 442 443 /******************************************************************************* 444 * 445 * Function bta_ag_parse_bac 446 * 447 * Description Parse AT+BAC parameter string. 448 * 449 * Returns Returns bitmap of supported codecs. 450 * 451 ******************************************************************************/ 452 static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB* p_scb, char* p_s) { 453 tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE; 454 uint16_t uuid_codec; 455 char* p; 456 457 while (p_s) { 458 /* skip to comma delimiter */ 459 for (p = p_s; *p != ',' && *p != 0; p++) 460 ; 461 462 /* get integer value */ 463 bool cont = false; // Continue processing 464 if (*p != 0) { 465 *p = 0; 466 cont = true; 467 } 468 uuid_codec = utl_str2int(p_s); 469 switch (uuid_codec) { 470 case UUID_CODEC_CVSD: 471 retval |= BTA_AG_CODEC_CVSD; 472 break; 473 case UUID_CODEC_MSBC: 474 retval |= BTA_AG_CODEC_MSBC; 475 break; 476 default: 477 APPL_TRACE_ERROR("Unknown Codec UUID(%d) received", uuid_codec); 478 break; 479 } 480 481 if (cont) 482 p_s = p + 1; 483 else 484 break; 485 } 486 487 return (retval); 488 } 489 490 /******************************************************************************* 491 * 492 * Function bta_ag_process_unat_res 493 * 494 * Description Process the unat response data and remove extra carriage 495 * return and line feed 496 * 497 * 498 * Returns void 499 * 500 ******************************************************************************/ 501 502 static void bta_ag_process_unat_res(char* unat_result) { 503 uint8_t j = 0; 504 uint8_t pairs_of_nl_cr; 505 char trim_data[BTA_AG_AT_MAX_LEN]; 506 507 uint8_t str_leng = strlen(unat_result); 508 509 /* If no extra CR and LF, just return */ 510 if (str_leng < 4) return; 511 512 /* Remove the carriage return and left feed */ 513 while (unat_result[0] == '\r' && unat_result[1] == '\n' && 514 unat_result[str_leng - 2] == '\r' && 515 unat_result[str_leng - 1] == '\n') { 516 pairs_of_nl_cr = 1; 517 for (int i = 0; i < (str_leng - 4 * pairs_of_nl_cr); i++) { 518 trim_data[j++] = unat_result[i + pairs_of_nl_cr * 2]; 519 } 520 /* Add EOF */ 521 trim_data[j] = '\0'; 522 str_leng = str_leng - 4; 523 strlcpy(unat_result, trim_data, str_leng + 1); 524 j = 0; 525 526 if (str_leng < 4) return; 527 } 528 } 529 530 /******************************************************************************* 531 * 532 * Function bta_ag_inband_enabled 533 * 534 * Description Determine whether in-band ring can be used. 535 * 536 * 537 * Returns void 538 * 539 ******************************************************************************/ 540 bool bta_ag_inband_enabled(tBTA_AG_SCB* p_scb) { 541 /* if feature is enabled and no other scbs connected */ 542 return p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb); 543 } 544 545 /******************************************************************************* 546 * 547 * Function bta_ag_send_call_inds 548 * 549 * Description Send call and callsetup indicators. 550 * 551 * 552 * Returns void 553 * 554 ******************************************************************************/ 555 void bta_ag_send_call_inds(tBTA_AG_SCB* p_scb, tBTA_AG_RES result) { 556 uint8_t call; 557 558 /* set new call and callsetup values based on BTA_AgResult */ 559 size_t callsetup = bta_ag_indicator_by_result_code(result); 560 561 if (result == BTA_AG_END_CALL_RES) { 562 call = BTA_AG_CALL_INACTIVE; 563 } else if (result == BTA_AG_IN_CALL_CONN_RES || 564 result == BTA_AG_OUT_CALL_CONN_RES || 565 result == BTA_AG_IN_CALL_HELD_RES) { 566 call = BTA_AG_CALL_ACTIVE; 567 } else { 568 call = p_scb->call_ind; 569 } 570 571 /* Send indicator function tracks if the values have actually changed */ 572 bta_ag_send_ind(p_scb, BTA_AG_IND_CALL, call, false); 573 bta_ag_send_ind(p_scb, BTA_AG_IND_CALLSETUP, callsetup, false); 574 } 575 576 /******************************************************************************* 577 * 578 * Function bta_ag_at_hsp_cback 579 * 580 * Description AT command processing callback for HSP. 581 * 582 * 583 * Returns void 584 * 585 ******************************************************************************/ 586 void bta_ag_at_hsp_cback(tBTA_AG_SCB* p_scb, uint16_t command_id, 587 uint8_t arg_type, char* p_arg, int16_t int_arg) { 588 APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", command_id, arg_type, 589 int_arg, p_arg); 590 591 bta_ag_send_ok(p_scb); 592 593 tBTA_AG_VAL val = {}; 594 val.hdr.handle = bta_ag_scb_to_idx(p_scb); 595 val.hdr.app_id = p_scb->app_id; 596 val.num = (uint16_t)int_arg; 597 strlcpy(val.str, p_arg, sizeof(val.str)); 598 599 /* call callback with event */ 600 (*bta_ag_cb.p_cback)(command_id, (tBTA_AG*)&val); 601 } 602 603 static void remove_spaces(char* str) { 604 char* dest_str = str; 605 606 while (*str) { 607 if (*str == ' ') { 608 str++; 609 } else { 610 *dest_str++ = *str++; 611 } 612 } 613 *dest_str = '\0'; 614 } 615 616 /******************************************************************************* 617 * 618 * Function bta_ag_find_empty_hf_ind) 619 * 620 * Description This function returns the index of an empty HF indicator 621 * structure. 622 * 623 * Returns int : index of the empty HF indicator structure or 624 * -1 if no empty indicator 625 * is available. 626 * 627 ******************************************************************************/ 628 static int bta_ag_find_empty_hf_ind(tBTA_AG_SCB* p_scb) { 629 for (int index = 0; index < BTA_AG_MAX_NUM_PEER_HF_IND; index++) { 630 if (p_scb->peer_hf_indicators[index].ind_id == 0) return index; 631 } 632 633 return -1; 634 } 635 636 /******************************************************************************* 637 * 638 * Function bta_ag_find_hf_ind_by_id 639 * 640 * Description This function returns the index of the HF indicator 641 * structure by the indicator id 642 * 643 * Returns int : index of the HF indicator structure 644 * -1 if the indicator 645 * was not found. 646 * 647 ******************************************************************************/ 648 static int bta_ag_find_hf_ind_by_id(tBTA_AG_HF_IND* p_hf_ind, int size, 649 uint32_t ind_id) { 650 for (int index = 0; index < size; index++) { 651 if (p_hf_ind[index].ind_id == ind_id) return index; 652 } 653 654 return -1; 655 } 656 657 /******************************************************************************* 658 * 659 * Function bta_ag_parse_bind_set 660 * 661 * Description Parse AT+BIND set command and save the indicators 662 * 663 * Returns true if successful 664 * 665 ******************************************************************************/ 666 static bool bta_ag_parse_bind_set(tBTA_AG_SCB* p_scb, tBTA_AG_VAL val) { 667 char* p_token = strtok(val.str, ","); 668 if (p_token == nullptr) return false; 669 670 while (p_token != nullptr) { 671 uint16_t rcv_ind_id = atoi(p_token); 672 int index = bta_ag_find_empty_hf_ind(p_scb); 673 if (index == -1) { 674 APPL_TRACE_WARNING("%s Can't save more indicators", __func__); 675 return false; 676 } 677 678 p_scb->peer_hf_indicators[index].ind_id = rcv_ind_id; 679 APPL_TRACE_DEBUG("%s peer_hf_ind[%d] = %d", __func__, index, rcv_ind_id); 680 681 p_token = strtok(nullptr, ","); 682 } 683 684 return true; 685 } 686 687 /******************************************************************************* 688 * 689 * Function bta_ag_bind_response 690 * 691 * Description Send response for the AT+BIND command (HFP 1.7) received 692 * from the headset based on the argument types. 693 * 694 * Returns Void 695 * 696 ******************************************************************************/ 697 static void bta_ag_bind_response(tBTA_AG_SCB* p_scb, uint8_t arg_type) { 698 char buffer[BTA_AG_AT_MAX_LEN] = ""; 699 700 if (arg_type == BTA_AG_AT_TEST) { 701 int index = 0; 702 buffer[index++] = '('; 703 704 for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++) { 705 if (bta_ag_local_hf_ind_cfg[i + 1].is_supported) { 706 /* Add ',' from second indicator */ 707 if (index > 1) buffer[index++] = ','; 708 snprintf(&buffer[index++], 2, "%d", 709 bta_ag_local_hf_ind_cfg[i + 1].ind_id); 710 } 711 } 712 713 buffer[index++] = ')'; 714 715 bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0); 716 bta_ag_send_ok(p_scb); 717 } else if (arg_type == BTA_AG_AT_READ) { 718 char* p = buffer; 719 720 /* bta_ag_local_hf_ind_cfg[0].ind_id is used as BTA_AG_NUM_LOCAL_HF_IND */ 721 for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++) { 722 if (i == BTA_AG_MAX_NUM_LOCAL_HF_IND) { 723 APPL_TRACE_WARNING("%s No space for more HF indicators", __func__); 724 break; 725 } 726 727 p_scb->local_hf_indicators[i].ind_id = 728 bta_ag_local_hf_ind_cfg[i + 1].ind_id; 729 p_scb->local_hf_indicators[i].is_supported = 730 bta_ag_local_hf_ind_cfg[i + 1].is_supported; 731 p_scb->local_hf_indicators[i].is_enable = 732 bta_ag_local_hf_ind_cfg[i + 1].is_enable; 733 734 int peer_index = bta_ag_find_hf_ind_by_id( 735 p_scb->peer_hf_indicators, BTA_AG_MAX_NUM_PEER_HF_IND, 736 p_scb->local_hf_indicators[i].ind_id); 737 738 /* Check whether local and peer sides support this indicator */ 739 if (p_scb->local_hf_indicators[i].is_supported && peer_index != -1) { 740 /* In the format of ind, state */ 741 p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].ind_id, p); 742 *p++ = ','; 743 p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].is_enable, p); 744 745 bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0); 746 // have to use memset here because assigning to "" will not zero 747 // initialize the rest of the buffer 748 memset(buffer, 0, sizeof(buffer)); 749 p = buffer; 750 } else { 751 /* If indicator is not supported, also set it to disable */ 752 p_scb->local_hf_indicators[i].is_enable = false; 753 } 754 } 755 756 bta_ag_send_ok(p_scb); 757 758 /* If the service level connection wan't already open, now it's open */ 759 if (!p_scb->svc_conn) { 760 bta_ag_svc_conn_open(p_scb, tBTA_AG_DATA::kEmpty); 761 } 762 } 763 } 764 765 /******************************************************************************* 766 * 767 * Function bta_ag_parse_biev_response 768 * 769 * Description Send response for AT+BIEV command (HFP 1.7) received from 770 * the headset based on the argument types. 771 * 772 * Returns true if the response was parsed successfully 773 * 774 ******************************************************************************/ 775 static bool bta_ag_parse_biev_response(tBTA_AG_SCB* p_scb, tBTA_AG_VAL* val) { 776 char* p_token = strtok(val->str, ","); 777 uint16_t rcv_ind_id = atoi(p_token); 778 779 p_token = strtok(nullptr, ","); 780 uint16_t rcv_ind_val = atoi(p_token); 781 782 APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id, 783 rcv_ind_val); 784 785 /* Check whether indicator ID is valid or not */ 786 if (rcv_ind_id > BTA_AG_NUM_LOCAL_HF_IND) { 787 APPL_TRACE_WARNING("%s received invalid indicator id %d", __func__, 788 rcv_ind_id); 789 return false; 790 } 791 792 /* Check this indicator is support or not and enabled or not */ 793 int local_index = bta_ag_find_hf_ind_by_id( 794 p_scb->local_hf_indicators, BTA_AG_MAX_NUM_LOCAL_HF_IND, rcv_ind_id); 795 if (local_index == -1 || 796 !p_scb->local_hf_indicators[local_index].is_supported || 797 !p_scb->local_hf_indicators[local_index].is_enable) { 798 APPL_TRACE_WARNING("%s indicator id %d not supported or disabled", __func__, 799 rcv_ind_id); 800 return false; 801 } 802 803 /* For each indicator ID, check whether the indicator value is in range */ 804 if (rcv_ind_val < bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_min_val || 805 rcv_ind_val > bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_max_val) { 806 APPL_TRACE_WARNING("%s invalid ind_val %d", __func__, rcv_ind_val); 807 return false; 808 } 809 810 val->lidx = rcv_ind_id; 811 val->num = rcv_ind_val; 812 813 return true; 814 } 815 816 /******************************************************************************* 817 * 818 * Function bta_ag_at_hfp_cback 819 * 820 * Description AT command processing callback for HFP. 821 * 822 * 823 * Returns void 824 * 825 ******************************************************************************/ 826 void bta_ag_at_hfp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd, uint8_t arg_type, 827 char* p_arg, int16_t int_arg) { 828 tBTA_AG_VAL val = {}; 829 tBTA_AG_SCB* ag_scb; 830 uint32_t i, ind_id; 831 uint32_t bia_masked_out; 832 if (p_arg == nullptr) { 833 APPL_TRACE_ERROR("%s: p_arg is null, send error and return", __func__); 834 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 835 return; 836 } 837 838 APPL_TRACE_DEBUG("%s: AT command %d, arg_type %d, int_arg %d, arg %s", 839 __func__, cmd, arg_type, int_arg, p_arg); 840 841 val.hdr.handle = bta_ag_scb_to_idx(p_scb); 842 val.hdr.app_id = p_scb->app_id; 843 val.hdr.status = BTA_AG_SUCCESS; 844 val.num = static_cast<uint32_t>(int_arg); 845 val.bd_addr = p_scb->peer_addr; 846 strlcpy(val.str, p_arg, sizeof(val.str)); 847 848 /** 849 * Unless this this is a local event, by default we'll forward 850 * the event code to the application. 851 * If |event| is 0 at the end of this function, the application 852 * callback is NOT invoked. 853 */ 854 tBTA_AG_EVT event = 0; 855 if (cmd < BTA_AG_LOCAL_EVT_FIRST) { 856 event = static_cast<tBTA_AG_EVT>(cmd); 857 } 858 859 switch (cmd) { 860 case BTA_AG_AT_A_EVT: 861 case BTA_AG_SPK_EVT: 862 case BTA_AG_MIC_EVT: 863 case BTA_AG_AT_CHUP_EVT: 864 case BTA_AG_AT_CBC_EVT: 865 /* send OK */ 866 bta_ag_send_ok(p_scb); 867 break; 868 869 case BTA_AG_AT_BLDN_EVT: 870 /* Do not send OK, App will send error or OK depending on 871 ** last dial number enabled or not */ 872 break; 873 874 case BTA_AG_AT_D_EVT: 875 /* Do not send OK for Dial cmds 876 ** Let application decide whether to send OK or ERROR*/ 877 878 /* if mem dial cmd, make sure string contains only digits */ 879 if (val.str[0] == '>') { 880 /* Some car kits may add some unwanted space characters in the 881 ** input string. This workaround will trim the unwanted chars. */ 882 remove_spaces(val.str + 1); 883 884 if (!utl_isintstr(val.str + 1)) { 885 event = 0; 886 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR); 887 } 888 } else if (val.str[0] == 'V') /* ATDV : Dial VoIP Call */ 889 { 890 /* We do not check string. Code will be added later if needed. */ 891 if (!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) && 892 (p_scb->features & BTA_AG_FEAT_VOIP))) { 893 event = 0; 894 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 895 } 896 } 897 /* If dial cmd, make sure string contains only dial digits 898 ** Dial digits are 0-9, A-C, *, #, + */ 899 else { 900 /* Some car kits may add some unwanted space characters in the 901 ** input string. This workaround will trim the unwanted chars. */ 902 remove_spaces(val.str); 903 904 if (!utl_isdialstr(val.str)) { 905 event = 0; 906 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR); 907 } 908 } 909 break; 910 911 case BTA_AG_LOCAL_EVT_CCWA: 912 /* store setting */ 913 p_scb->ccwa_enabled = (bool)int_arg; 914 915 /* send OK */ 916 bta_ag_send_ok(p_scb); 917 break; 918 919 case BTA_AG_AT_CHLD_EVT: 920 if (arg_type == BTA_AG_AT_TEST) { 921 /* don't call callback */ 922 event = 0; 923 924 /* send CHLD string */ 925 /* Form string based on supported 1.5 feature */ 926 if ((p_scb->peer_version >= HFP_VERSION_1_5) && 927 (p_scb->features & BTA_AG_FEAT_ECC) && 928 (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC)) 929 bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES, 930 p_bta_ag_cfg->chld_val_ecc, 0); 931 else 932 bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES, 933 p_bta_ag_cfg->chld_val, 0); 934 935 /* send OK */ 936 bta_ag_send_ok(p_scb); 937 938 /* if service level conn. not already open, now it's open */ 939 bta_ag_svc_conn_open(p_scb, tBTA_AG_DATA::kEmpty); 940 } else { 941 val.idx = bta_ag_parse_chld(p_scb, val.str); 942 943 if (val.idx == BTA_AG_INVALID_CHLD) { 944 event = 0; 945 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 946 break; 947 } 948 if (val.idx && 949 !((p_scb->features & BTA_AG_FEAT_ECC) && 950 (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))) { 951 /* we do not support ECC, but HF is sending us a CHLD with call 952 * index*/ 953 event = 0; 954 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 955 956 } else { 957 /* If it is swap between calls, set call held indicator to 3(out of 958 *valid 0-2) 959 ** Application will set it back to 1 960 ** callheld indicator will be sent across to the peer. */ 961 if (val.str[0] == '2') { 962 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_MAX_NUM_CLIENTS; 963 i++, ag_scb++) { 964 if (ag_scb->in_use) { 965 if ((ag_scb->call_ind == BTA_AG_CALL_ACTIVE) && 966 (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) 967 ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1; 968 } 969 } 970 } 971 } 972 973 /* Do not send OK. Let app decide after parsing the val str */ 974 /* bta_ag_send_ok(p_scb); */ 975 } 976 break; 977 978 case BTA_AG_AT_BIND_EVT: 979 APPL_TRACE_DEBUG("%s BTA_AG_AT_BIND_EVT arg_type: %d", __func__, 980 arg_type); 981 if (arg_type == BTA_AG_AT_SET) { 982 if (bta_ag_parse_bind_set(p_scb, val)) { 983 bta_ag_send_ok(p_scb); 984 } else { 985 event = 0; /* don't call callback */ 986 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX); 987 } 988 } else { 989 bta_ag_bind_response(p_scb, arg_type); 990 991 /* Need not pass this command beyond BTIF.*/ 992 /* Stack handles it internally */ 993 event = 0; /* don't call callback */ 994 } 995 break; 996 997 case BTA_AG_AT_BIEV_EVT: 998 if (bta_ag_parse_biev_response(p_scb, &val)) { 999 bta_ag_send_ok(p_scb); 1000 } else { 1001 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX); 1002 /* don't call callback receiving invalid indicator */ 1003 event = 0; 1004 } 1005 break; 1006 1007 case BTA_AG_AT_CIND_EVT: 1008 if (arg_type == BTA_AG_AT_TEST) { 1009 /* don't call callback */ 1010 event = 0; 1011 1012 /* send CIND string, send OK */ 1013 bta_ag_send_result(p_scb, BTA_AG_CIND_RES, p_bta_ag_cfg->cind_info, 0); 1014 bta_ag_send_ok(p_scb); 1015 } 1016 break; 1017 1018 case BTA_AG_LOCAL_EVT_CLIP: 1019 /* store setting, send OK */ 1020 p_scb->clip_enabled = (bool)int_arg; 1021 bta_ag_send_ok(p_scb); 1022 break; 1023 1024 case BTA_AG_LOCAL_EVT_CMER: 1025 /* if parsed ok store setting, send OK */ 1026 if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled)) { 1027 bta_ag_send_ok(p_scb); 1028 1029 /* if service level conn. not already open and our features and 1030 ** peer features do not have 3-way, service level conn. now open 1031 */ 1032 if (!p_scb->svc_conn && 1033 !((p_scb->features & BTA_AG_FEAT_3WAY) && 1034 (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY))) { 1035 bta_ag_svc_conn_open(p_scb, tBTA_AG_DATA::kEmpty); 1036 } 1037 } else { 1038 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 1039 } 1040 break; 1041 1042 case BTA_AG_AT_VTS_EVT: 1043 /* check argument */ 1044 if (strlen(p_arg) == 1) { 1045 bta_ag_send_ok(p_scb); 1046 } else { 1047 event = 0; 1048 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 1049 } 1050 break; 1051 1052 case BTA_AG_AT_BINP_EVT: 1053 /* if feature not set don't call callback, send ERROR */ 1054 if (!(p_scb->features & BTA_AG_FEAT_VTAG)) { 1055 event = 0; 1056 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1057 } 1058 break; 1059 1060 case BTA_AG_AT_BVRA_EVT: 1061 /* if feature not supported don't call callback, send ERROR. App will send 1062 * OK */ 1063 if (!(p_scb->features & BTA_AG_FEAT_VREC)) { 1064 event = 0; 1065 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1066 } 1067 break; 1068 1069 case BTA_AG_LOCAL_EVT_BRSF: { 1070 /* store peer features */ 1071 p_scb->peer_features = (uint16_t)int_arg; 1072 1073 tBTA_AG_FEAT features = p_scb->features; 1074 if (p_scb->peer_version < HFP_VERSION_1_7) { 1075 features &= HFP_1_6_FEAT_MASK; 1076 } 1077 1078 APPL_TRACE_DEBUG("%s BRSF HF: 0x%x, phone: 0x%x", __func__, 1079 p_scb->peer_features, features); 1080 1081 /* send BRSF, send OK */ 1082 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, nullptr, 1083 (int16_t)features); 1084 bta_ag_send_ok(p_scb); 1085 break; 1086 } 1087 1088 case BTA_AG_AT_NREC_EVT: 1089 /* if feature send OK, else don't call callback, send ERROR */ 1090 if (p_scb->features & BTA_AG_FEAT_ECNR) { 1091 bta_ag_send_ok(p_scb); 1092 } else { 1093 event = 0; 1094 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1095 } 1096 break; 1097 1098 case BTA_AG_AT_BTRH_EVT: 1099 /* if feature send BTRH, send OK:, else don't call callback, send ERROR */ 1100 if (p_scb->features & BTA_AG_FEAT_BTRH) { 1101 /* If set command; send response and notify app */ 1102 if (arg_type == BTA_AG_AT_SET) { 1103 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_MAX_NUM_CLIENTS; 1104 i++, ag_scb++) { 1105 if (ag_scb->in_use) { 1106 bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, nullptr, int_arg); 1107 } 1108 } 1109 bta_ag_send_ok(p_scb); 1110 } else /* Read Command */ 1111 { 1112 val.num = BTA_AG_BTRH_READ; 1113 } 1114 } else { 1115 event = 0; 1116 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1117 } 1118 break; 1119 1120 case BTA_AG_AT_COPS_EVT: 1121 if (arg_type == BTA_AG_AT_SET) { 1122 /* don't call callback */ 1123 event = 0; 1124 1125 /* send OK */ 1126 bta_ag_send_ok(p_scb); 1127 } 1128 break; 1129 1130 case BTA_AG_LOCAL_EVT_CMEE: 1131 if (p_scb->features & BTA_AG_FEAT_EXTERR) { 1132 /* store setting */ 1133 p_scb->cmee_enabled = (bool)int_arg; 1134 1135 /* send OK */ 1136 bta_ag_send_ok(p_scb); 1137 } else { 1138 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1139 } 1140 /* don't call callback */ 1141 event = 0; 1142 break; 1143 1144 case BTA_AG_AT_BIA_EVT: 1145 bia_masked_out = p_scb->bia_masked_out; 1146 1147 /* Parse the indicator mask */ 1148 for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); 1149 i++, ind_id++) { 1150 if (val.str[i] == ',') { 1151 continue; 1152 } 1153 1154 if (val.str[i] == '0') { 1155 bia_masked_out |= ((uint32_t)1 << ind_id); 1156 } else if (val.str[i] == '1') { 1157 bia_masked_out &= ~((uint32_t)1 << ind_id); 1158 } else { 1159 break; 1160 } 1161 1162 i++; 1163 if (val.str[i] != ',') { 1164 break; 1165 } 1166 } 1167 if (val.str[i] == 0) { 1168 p_scb->bia_masked_out = bia_masked_out; 1169 val.num = bia_masked_out; 1170 bta_ag_send_ok(p_scb); 1171 } else { 1172 event = 0; 1173 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX); 1174 } 1175 break; 1176 1177 case BTA_AG_AT_CNUM_EVT: 1178 break; 1179 1180 case BTA_AG_AT_CLCC_EVT: 1181 if (!(p_scb->features & BTA_AG_FEAT_ECS)) { 1182 event = 0; 1183 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1184 } 1185 break; 1186 1187 case BTA_AG_AT_BAC_EVT: 1188 bta_ag_send_ok(p_scb); 1189 p_scb->received_at_bac = true; 1190 1191 /* store available codecs from the peer */ 1192 if ((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && 1193 (p_scb->features & BTA_AG_FEAT_CODEC)) { 1194 p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg); 1195 p_scb->codec_updated = true; 1196 1197 if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC) { 1198 p_scb->sco_codec = UUID_CODEC_MSBC; 1199 APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to MSBC"); 1200 } else { 1201 p_scb->sco_codec = UUID_CODEC_CVSD; 1202 APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to CVSD"); 1203 } 1204 /* The above logic sets the stack preferred codec based on local and 1205 peer codec 1206 capabilities. This can be overridden by the application depending on its 1207 preference 1208 using the bta_ag_setcodec API. We send the peer_codecs to the 1209 application. */ 1210 val.num = p_scb->peer_codecs; 1211 /* Received BAC while in codec negotiation. */ 1212 if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && 1213 (bta_ag_cb.sco.p_curr_scb == p_scb)) { 1214 bta_ag_codec_negotiate(p_scb); 1215 } 1216 } else { 1217 p_scb->peer_codecs = BTA_AG_CODEC_CVSD; 1218 APPL_TRACE_ERROR( 1219 "Unexpected CMD:AT+BAC, Codec Negotiation is not supported"); 1220 } 1221 break; 1222 1223 case BTA_AG_AT_BCS_EVT: { 1224 tBTA_AG_PEER_CODEC codec_type, codec_sent; 1225 bta_ag_send_ok(p_scb); 1226 alarm_cancel(p_scb->codec_negotiation_timer); 1227 1228 switch (int_arg) { 1229 case UUID_CODEC_CVSD: 1230 codec_type = BTA_AG_CODEC_CVSD; 1231 break; 1232 case UUID_CODEC_MSBC: 1233 codec_type = BTA_AG_CODEC_MSBC; 1234 break; 1235 default: 1236 APPL_TRACE_ERROR("Unknown codec_uuid %d", int_arg); 1237 codec_type = 0xFFFF; 1238 break; 1239 } 1240 1241 if (p_scb->codec_fallback) 1242 codec_sent = BTA_AG_CODEC_CVSD; 1243 else 1244 codec_sent = p_scb->sco_codec; 1245 1246 bta_ag_sco_codec_nego(p_scb, codec_type == codec_sent); 1247 1248 /* send final codec info to callback */ 1249 val.num = codec_sent; 1250 break; 1251 } 1252 case BTA_AG_LOCAL_EVT_BCC: { 1253 if (!bta_ag_sco_is_active_device(p_scb->peer_addr)) { 1254 LOG(WARNING) << __func__ << ": AT+BCC rejected as " << p_scb->peer_addr 1255 << " is not the active device"; 1256 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_ALLOWED); 1257 break; 1258 } 1259 bta_ag_send_ok(p_scb); 1260 bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty); 1261 break; 1262 } 1263 default: 1264 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1265 break; 1266 } 1267 1268 /* call callback */ 1269 if (event != 0) { 1270 (*bta_ag_cb.p_cback)(event, (tBTA_AG*)&val); 1271 } 1272 } 1273 1274 /******************************************************************************* 1275 * 1276 * Function bta_ag_at_err_cback 1277 * 1278 * Description AT command parser error callback. 1279 * 1280 * 1281 * Returns void 1282 * 1283 ******************************************************************************/ 1284 void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown, const char* p_arg) { 1285 if (unknown && (!strlen(p_arg))) { 1286 APPL_TRACE_DEBUG("Empty AT cmd string received"); 1287 bta_ag_send_ok(p_scb); 1288 return; 1289 } 1290 1291 tBTA_AG_VAL val = {}; 1292 /* if unknown AT command and configured to pass these to app */ 1293 if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT)) { 1294 val.hdr.handle = bta_ag_scb_to_idx(p_scb); 1295 val.hdr.app_id = p_scb->app_id; 1296 val.hdr.status = BTA_AG_SUCCESS; 1297 val.num = 0; 1298 strlcpy(val.str, p_arg, sizeof(val.str)); 1299 (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG*)&val); 1300 } else { 1301 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1302 } 1303 } 1304 1305 /******************************************************************************* 1306 * 1307 * Function bta_ag_hsp_result 1308 * 1309 * Description Handle API result for HSP connections. 1310 * 1311 * 1312 * Returns void 1313 * 1314 ******************************************************************************/ 1315 void bta_ag_hsp_result(tBTA_AG_SCB* p_scb, const tBTA_AG_API_RESULT& result) { 1316 APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", result.result); 1317 1318 switch (result.result) { 1319 case BTA_AG_SPK_RES: 1320 case BTA_AG_MIC_RES: 1321 bta_ag_send_result(p_scb, result.result, nullptr, result.data.num); 1322 break; 1323 1324 case BTA_AG_IN_CALL_RES: 1325 /* tell sys to stop av if any */ 1326 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1327 1328 /* if sco already opened or no inband ring send ring now */ 1329 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) || 1330 (p_scb->features & BTA_AG_FEAT_NOSCO)) { 1331 bta_ag_send_ring(p_scb, tBTA_AG_DATA::kEmpty); 1332 } else { 1333 /* else open sco, send ring after sco opened */ 1334 /* HSPv1.2: AG shall not send RING if using in-band ring tone. */ 1335 if (p_scb->peer_version >= HSP_VERSION_1_2) { 1336 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 1337 } else { 1338 p_scb->post_sco = BTA_AG_POST_SCO_RING; 1339 } 1340 bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty); 1341 } 1342 break; 1343 1344 case BTA_AG_IN_CALL_CONN_RES: 1345 case BTA_AG_OUT_CALL_ORIG_RES: 1346 /* if incoming call connected stop ring timer */ 1347 if (result.result == BTA_AG_IN_CALL_CONN_RES) { 1348 alarm_cancel(p_scb->ring_timer); 1349 } 1350 1351 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) { 1352 /* if audio connected to this scb AND sco is not opened, open sco */ 1353 if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb) && 1354 !bta_ag_sco_is_open(p_scb)) { 1355 bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty); 1356 } else if (result.data.audio_handle == BTA_AG_HANDLE_NONE && 1357 bta_ag_sco_is_open(p_scb)) { 1358 /* else if no audio at call close sco */ 1359 bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty); 1360 } 1361 } 1362 break; 1363 1364 case BTA_AG_END_CALL_RES: 1365 alarm_cancel(p_scb->ring_timer); 1366 1367 /* close sco */ 1368 if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && 1369 !(p_scb->features & BTA_AG_FEAT_NOSCO)) { 1370 bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty); 1371 } else { 1372 /* if av got suspended by this call, let it resume. */ 1373 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1374 } 1375 break; 1376 1377 case BTA_AG_INBAND_RING_RES: 1378 p_scb->inband_enabled = result.data.state; 1379 APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled); 1380 break; 1381 1382 case BTA_AG_UNAT_RES: 1383 if (result.data.ok_flag != BTA_AG_OK_ERROR) { 1384 if (result.data.str[0] != 0) { 1385 bta_ag_send_result(p_scb, result.result, result.data.str, 0); 1386 } 1387 1388 if (result.data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb); 1389 } else { 1390 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 1391 } 1392 break; 1393 1394 default: 1395 /* ignore all others */ 1396 break; 1397 } 1398 } 1399 1400 /******************************************************************************* 1401 * 1402 * Function bta_ag_hfp_result 1403 * 1404 * Description Handle API result for HFP connections. 1405 * 1406 * 1407 * Returns void 1408 * 1409 ******************************************************************************/ 1410 void bta_ag_hfp_result(tBTA_AG_SCB* p_scb, const tBTA_AG_API_RESULT& result) { 1411 APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", result.result); 1412 1413 switch (result.result) { 1414 case BTA_AG_SPK_RES: 1415 case BTA_AG_MIC_RES: 1416 bta_ag_send_result(p_scb, result.result, nullptr, result.data.num); 1417 break; 1418 1419 case BTA_AG_IN_CALL_RES: { 1420 /* tell sys to stop av if any */ 1421 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1422 1423 /* Store caller id string. 1424 * Append type info at the end. 1425 * Make sure a valid type info is passed. 1426 * Otherwise add 129 as default type */ 1427 uint16_t clip_type = result.data.num; 1428 if ((clip_type < BTA_AG_CLIP_TYPE_MIN) || 1429 (clip_type > BTA_AG_CLIP_TYPE_MAX)) { 1430 if (clip_type != BTA_AG_CLIP_TYPE_VOIP) { 1431 clip_type = BTA_AG_CLIP_TYPE_DEFAULT; 1432 } 1433 } 1434 1435 APPL_TRACE_DEBUG("CLIP type :%d", clip_type); 1436 p_scb->clip[0] = 0; 1437 if (result.data.str[0] != 0) 1438 snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", result.data.str, 1439 clip_type); 1440 1441 /* send callsetup indicator */ 1442 if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END) { 1443 /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO 1444 * close. */ 1445 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL; 1446 } else { 1447 bta_ag_send_call_inds(p_scb, result.result); 1448 1449 /* if sco already opened or no inband ring send ring now */ 1450 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) || 1451 (p_scb->features & BTA_AG_FEAT_NOSCO) || 1452 (result.data.audio_handle != bta_ag_scb_to_idx(p_scb))) { 1453 bta_ag_send_ring(p_scb, tBTA_AG_DATA::kEmpty); 1454 } else { 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::kEmpty); 1458 } 1459 } 1460 break; 1461 } 1462 case BTA_AG_IN_CALL_CONN_RES: 1463 alarm_cancel(p_scb->ring_timer); 1464 1465 /* if sco not opened and we need to open it, send indicators first 1466 ** then open sco. 1467 */ 1468 bta_ag_send_call_inds(p_scb, result.result); 1469 1470 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) { 1471 if (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::kEmpty); 1474 } else if ((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::kEmpty); 1477 } 1478 } 1479 break; 1480 1481 case BTA_AG_IN_CALL_HELD_RES: 1482 alarm_cancel(p_scb->ring_timer); 1483 1484 bta_ag_send_call_inds(p_scb, result.result); 1485 1486 break; 1487 1488 case BTA_AG_OUT_CALL_ORIG_RES: 1489 bta_ag_send_call_inds(p_scb, result.result); 1490 if (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::kEmpty); 1493 } 1494 break; 1495 1496 case BTA_AG_OUT_CALL_ALERT_RES: 1497 /* send indicators */ 1498 bta_ag_send_call_inds(p_scb, result.result); 1499 if (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::kEmpty); 1502 } 1503 break; 1504 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 (result.data.audio_handle == bta_ag_scb_to_idx(p_scb)) { 1510 bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty); 1511 } else if (result.data.audio_handle == BTA_AG_HANDLE_NONE) { 1512 bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty); 1513 } 1514 } 1515 break; 1516 1517 case BTA_AG_OUT_CALL_CONN_RES: 1518 /* send indicators */ 1519 bta_ag_send_call_inds(p_scb, result.result); 1520 1521 /* open or close sco */ 1522 if (!(p_scb->features & BTA_AG_FEAT_NOSCO)) { 1523 if (result.data.audio_handle == bta_ag_scb_to_idx(p_scb)) { 1524 bta_ag_sco_open(p_scb, tBTA_AG_DATA::kEmpty); 1525 } else if (result.data.audio_handle == BTA_AG_HANDLE_NONE) { 1526 bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty); 1527 } 1528 } 1529 break; 1530 1531 case BTA_AG_CALL_CANCEL_RES: 1532 /* send indicators */ 1533 bta_ag_send_call_inds(p_scb, result.result); 1534 break; 1535 1536 case BTA_AG_END_CALL_RES: 1537 alarm_cancel(p_scb->ring_timer); 1538 1539 /* if sco open, close sco then send indicator values */ 1540 if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && 1541 !(p_scb->features & BTA_AG_FEAT_NOSCO)) { 1542 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END; 1543 bta_ag_sco_close(p_scb, tBTA_AG_DATA::kEmpty); 1544 } else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL) { 1545 /* sco closing for outgoing call because of incoming call */ 1546 /* Send only callsetup end indicator after sco close */ 1547 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END; 1548 } else { 1549 bta_ag_send_call_inds(p_scb, result.result); 1550 1551 /* if av got suspended by this call, let it resume. */ 1552 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1553 } 1554 break; 1555 1556 case BTA_AG_INBAND_RING_RES: 1557 p_scb->inband_enabled = result.data.state; 1558 APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled); 1559 bta_ag_send_result(p_scb, result.result, nullptr, result.data.state); 1560 break; 1561 1562 case BTA_AG_CIND_RES: 1563 /* store local values */ 1564 p_scb->call_ind = result.data.str[0] - '0'; 1565 p_scb->callsetup_ind = result.data.str[2] - '0'; 1566 p_scb->service_ind = result.data.str[4] - '0'; 1567 p_scb->signal_ind = result.data.str[6] - '0'; 1568 p_scb->roam_ind = result.data.str[8] - '0'; 1569 p_scb->battchg_ind = result.data.str[10] - '0'; 1570 p_scb->callheld_ind = result.data.str[12] - '0'; 1571 APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind, 1572 p_scb->callsetup_ind); 1573 1574 bta_ag_send_result(p_scb, result.result, result.data.str, 0); 1575 bta_ag_send_ok(p_scb); 1576 break; 1577 1578 case BTA_AG_BINP_RES: 1579 case BTA_AG_CNUM_RES: 1580 case BTA_AG_CLCC_RES: 1581 case BTA_AG_COPS_RES: 1582 if (result.data.ok_flag != BTA_AG_OK_ERROR) { 1583 if (result.data.str[0] != 0) { 1584 bta_ag_send_result(p_scb, result.result, result.data.str, 0); 1585 } 1586 1587 if (result.data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb); 1588 } else { 1589 bta_ag_send_error(p_scb, result.data.errcode); 1590 } 1591 break; 1592 1593 case BTA_AG_UNAT_RES: { 1594 if (result.data.ok_flag != BTA_AG_OK_ERROR) { 1595 if (result.data.str[0] != 0) { 1596 tBTA_AG_API_RESULT result_copy(result); 1597 bta_ag_process_unat_res(result_copy.data.str); 1598 APPL_TRACE_DEBUG("BTA_AG_RES :%s", result_copy.data.str); 1599 bta_ag_send_result(p_scb, result_copy.result, result_copy.data.str, 1600 0); 1601 } 1602 if (result.data.ok_flag == BTA_AG_OK_DONE) { 1603 bta_ag_send_ok(p_scb); 1604 } 1605 } else { 1606 bta_ag_send_error(p_scb, result.data.errcode); 1607 } 1608 break; 1609 } 1610 1611 case BTA_AG_CALL_WAIT_RES: 1612 if (p_scb->ccwa_enabled) { 1613 bta_ag_send_result(p_scb, result.result, result.data.str, 0); 1614 } 1615 bta_ag_send_call_inds(p_scb, result.result); 1616 break; 1617 1618 case BTA_AG_IND_RES: 1619 bta_ag_send_ind(p_scb, result.data.ind.id, result.data.ind.value, false); 1620 break; 1621 1622 case BTA_AG_IND_RES_ON_DEMAND: 1623 bta_ag_send_ind(p_scb, result.data.ind.id, result.data.ind.value, true); 1624 break; 1625 1626 case BTA_AG_BVRA_RES: 1627 bta_ag_send_result(p_scb, result.result, nullptr, result.data.state); 1628 break; 1629 1630 case BTA_AG_BTRH_RES: 1631 if (result.data.ok_flag != BTA_AG_OK_ERROR) { 1632 /* Don't respond to read if not in response & hold state */ 1633 if (result.data.num != BTA_AG_BTRH_NO_RESP) { 1634 bta_ag_send_result(p_scb, result.result, nullptr, result.data.num); 1635 } 1636 1637 /* In case of a response to a read request we need to send OK */ 1638 if (result.data.ok_flag == BTA_AG_OK_DONE) { 1639 bta_ag_send_ok(p_scb); 1640 } 1641 } else { 1642 bta_ag_send_error(p_scb, result.data.errcode); 1643 } 1644 break; 1645 1646 case BTA_AG_BIND_RES: { 1647 /* Find whether ind_id is supported by local device or not */ 1648 int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators, 1649 BTA_AG_MAX_NUM_LOCAL_HF_IND, 1650 result.data.ind.id); 1651 if (local_index == -1) { 1652 APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__, 1653 result.data.ind.id); 1654 return; 1655 } 1656 1657 /* Find whether ind_id is supported by peer device or not */ 1658 int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators, 1659 BTA_AG_MAX_NUM_PEER_HF_IND, 1660 result.data.ind.id); 1661 if (peer_index == -1) { 1662 APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__, 1663 result.data.ind.id); 1664 return; 1665 } else { 1666 /* If the current state is different from the one upper layer request 1667 change current state and send out the result */ 1668 if (p_scb->local_hf_indicators[local_index].is_enable != 1669 result.data.ind.on_demand) { 1670 char buffer[BTA_AG_AT_MAX_LEN] = {0}; 1671 char* p = buffer; 1672 1673 p_scb->local_hf_indicators[local_index].is_enable = 1674 result.data.ind.on_demand; 1675 p += utl_itoa(result.data.ind.id, p); 1676 *p++ = ','; 1677 p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p); 1678 1679 bta_ag_send_result(p_scb, result.result, buffer, 0); 1680 } else { 1681 APPL_TRACE_DEBUG( 1682 "%s HF Indicator %d already %s", result.data.ind.id, 1683 (result.data.ind.on_demand) ? "Enabled" : "Disabled"); 1684 } 1685 } 1686 break; 1687 } 1688 default: 1689 break; 1690 } 1691 } 1692 1693 /******************************************************************************* 1694 * 1695 * Function bta_ag_result 1696 * 1697 * Description Handle API result. 1698 * 1699 * 1700 * Returns void 1701 * 1702 ******************************************************************************/ 1703 void bta_ag_result(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) { 1704 if (p_scb->conn_service == BTA_AG_HSP) { 1705 bta_ag_hsp_result(p_scb, data.api_result); 1706 } else { 1707 bta_ag_hfp_result(p_scb, data.api_result); 1708 } 1709 } 1710 1711 /******************************************************************************* 1712 * 1713 * Function bta_ag_send_bcs 1714 * 1715 * Description Send +BCS AT command to peer. 1716 * 1717 * Returns void 1718 * 1719 ******************************************************************************/ 1720 void bta_ag_send_bcs(tBTA_AG_SCB* p_scb) { 1721 uint16_t codec_uuid; 1722 1723 if (p_scb->codec_fallback) { 1724 codec_uuid = UUID_CODEC_CVSD; 1725 } else { 1726 switch (p_scb->sco_codec) { 1727 case BTA_AG_CODEC_NONE: 1728 codec_uuid = UUID_CODEC_CVSD; 1729 break; 1730 case BTA_AG_CODEC_CVSD: 1731 codec_uuid = UUID_CODEC_CVSD; 1732 break; 1733 case BTA_AG_CODEC_MSBC: 1734 codec_uuid = UUID_CODEC_MSBC; 1735 break; 1736 default: 1737 APPL_TRACE_ERROR("bta_ag_send_bcs: unknown codec %d, use CVSD", 1738 p_scb->sco_codec); 1739 codec_uuid = UUID_CODEC_CVSD; 1740 break; 1741 } 1742 } 1743 1744 /* send +BCS */ 1745 APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid); 1746 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BCS, nullptr, codec_uuid); 1747 } 1748 1749 /******************************************************************************* 1750 * 1751 * Function bta_ag_send_ring 1752 * 1753 * Description Send RING result code to peer. 1754 * 1755 * 1756 * Returns void 1757 * 1758 ******************************************************************************/ 1759 void bta_ag_send_ring(tBTA_AG_SCB* p_scb, 1760 UNUSED_ATTR const tBTA_AG_DATA& data) { 1761 if ((p_scb->conn_service == BTA_AG_HFP) && 1762 p_scb->callsetup_ind != BTA_AG_CALLSETUP_INCOMING) { 1763 LOG(WARNING) << __func__ << ": don't send RING, conn_service=" 1764 << std::to_string(p_scb->conn_service) 1765 << ", callsetup_ind=" << std::to_string(p_scb->callsetup_ind); 1766 return; 1767 } 1768 /* send RING */ 1769 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, nullptr, 0); 1770 1771 /* if HFP and clip enabled and clip data send CLIP */ 1772 if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && 1773 p_scb->clip[0] != 0) { 1774 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CLIP, p_scb->clip, 0); 1775 } 1776 1777 bta_sys_start_timer(p_scb->ring_timer, BTA_AG_RING_TIMEOUT_MS, 1778 BTA_AG_RING_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb)); 1779 } 1780