1 /****************************************************************************** 2 * 3 * Copyright (C) 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 <ctype.h> 22 #include <stdio.h> 23 #include <string.h> 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_BIA, 67 BTA_AG_LOCAL_EVT_BCC, 68 }; 69 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 */ 76 {"", 0, 0, 0, 0, 0}}; 77 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, 82 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, 88 0, 4}, 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, 91 BTA_AG_AT_STR, 0, 0}, 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, 99 BTA_AG_CMD_MAX_VAL}, 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, 103 0, 2}, 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, 106 0, 0}, 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, 112 BTA_AG_CMD_MAX_VAL}, 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}}; 119 120 /* AT result code table element */ 121 typedef struct { 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 */ 125 } tBTA_AG_RESULT; 126 127 /* AT result code argument types */ 128 enum { 129 BTA_AG_RES_FMT_NONE, /* no argument */ 130 BTA_AG_RES_FMT_INT, /* integer argument */ 131 BTA_AG_RES_FMT_STR /* string argument */ 132 }; 133 134 /* Local AT command result codes not defined in bta_ag_api.h */ 135 enum { 136 BTA_AG_LOCAL_RES_FIRST = 0x0100, 137 BTA_AG_LOCAL_RES_OK, 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, 143 BTA_AG_LOCAL_RES_BCS 144 }; 145 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}}; 170 171 static const tBTA_AG_RESULT* bta_ag_result_by_code(size_t code) { 172 for (size_t i = 0; 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]; 175 } 176 return 0; 177 } 178 179 const tBTA_AG_AT_CMD* bta_ag_at_tbl[BTA_AG_NUM_IDX] = {bta_ag_hsp_cmd, 180 bta_ag_hfp_cmd}; 181 182 typedef struct { 183 size_t result_code; 184 size_t indicator; 185 } tBTA_AG_INDICATOR_MAP; 186 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}}; 193 194 static size_t bta_ag_indicator_by_result_code(size_t code) { 195 for (size_t i = 0; 196 i != 197 sizeof(callsetup_indicator_map) / sizeof(callsetup_indicator_map[0]); 198 ++i) { 199 if (code == callsetup_indicator_map[i].result_code) 200 return callsetup_indicator_map[i].indicator; 201 } 202 return BTA_AG_CALLSETUP_NONE; 203 } 204 205 /******************************************************************************* 206 * 207 * Function bta_ag_send_result 208 * 209 * Description Send an AT result code. 210 * 211 * 212 * Returns void 213 * 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); 218 if (result == 0) { 219 LOG_ERROR(LOG_TAG, "%s Unable to lookup result for code %zu", __func__, 220 code); 221 return; 222 } 223 224 char buf[BTA_AG_AT_MAX_LEN + 16]; 225 char* p = buf; 226 memset(buf, 0, sizeof(buf)); 227 228 /* init with \r\n */ 229 *p++ = '\r'; 230 *p++ = '\n'; 231 232 /* copy result code string */ 233 strlcpy(p, result->result_string, sizeof(buf) - 2); 234 235 if (p_scb->conn_service == BTA_AG_HSP) { 236 /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */ 237 switch (code) { 238 case BTA_AG_SPK_RES: 239 case BTA_AG_MIC_RES: 240 if (*(p + COLON_IDX_4_VGSVGM) == ':') { 241 *(p + COLON_IDX_4_VGSVGM) = '='; 242 } 243 break; 244 } 245 } 246 247 p += strlen(result->result_string); 248 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) { 253 strcpy(p, p_arg); 254 p += strlen(p_arg); 255 } 256 257 /* finish with \r\n */ 258 *p++ = '\r'; 259 *p++ = '\n'; 260 261 /* send to RFCOMM */ 262 uint16_t len = 0; 263 PORT_WriteData(p_scb->conn_handle, buf, (uint16_t)(p - buf), &len); 264 } 265 266 /******************************************************************************* 267 * 268 * Function bta_ag_send_ok 269 * 270 * Description Send an OK result code. 271 * 272 * 273 * Returns void 274 * 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); 278 } 279 280 /******************************************************************************* 281 * 282 * Function bta_ag_send_error 283 * 284 * Description Send an ERROR result code. 285 * errcode - used to send verbose errocode 286 * 287 * 288 * Returns void 289 * 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); 295 else 296 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, NULL, 0); 297 } 298 299 /******************************************************************************* 300 * 301 * Function bta_ag_send_ind 302 * 303 * Description Send an indicator CIEV result code. 304 * 305 * 306 * Returns void 307 * 308 ******************************************************************************/ 309 static void bta_ag_send_ind(tBTA_AG_SCB* p_scb, uint16_t id, uint16_t value, 310 bool on_demand) { 311 char str[12]; 312 char* p = str; 313 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))) 319 return; 320 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; 325 326 p_scb->call_ind = (uint8_t)value; 327 } 328 329 if ((id == BTA_AG_IND_CALLSETUP) && (on_demand == false)) { 330 if (value == p_scb->callsetup_ind) return; 331 332 p_scb->callsetup_ind = (uint8_t)value; 333 } 334 335 if ((id == BTA_AG_IND_SERVICE) && (on_demand == false)) { 336 if (value == p_scb->service_ind) return; 337 338 p_scb->service_ind = (uint8_t)value; 339 } 340 if ((id == BTA_AG_IND_SIGNAL) && (on_demand == false)) { 341 if (value == p_scb->signal_ind) return; 342 343 p_scb->signal_ind = (uint8_t)value; 344 } 345 if ((id == BTA_AG_IND_ROAM) && (on_demand == false)) { 346 if (value == p_scb->roam_ind) return; 347 348 p_scb->roam_ind = (uint8_t)value; 349 } 350 if ((id == BTA_AG_IND_BATTCHG) && (on_demand == false)) { 351 if (value == p_scb->battchg_ind) return; 352 353 p_scb->battchg_ind = (uint8_t)value; 354 } 355 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; 359 360 p_scb->callheld_ind = (uint8_t)value; 361 } 362 363 if (p_scb->cmer_enabled) { 364 p += utl_itoa(id, p); 365 *p++ = ','; 366 utl_itoa(value, p); 367 bta_ag_send_result(p_scb, BTA_AG_IND_RES, str, 0); 368 } 369 } 370 371 /******************************************************************************* 372 * 373 * Function bta_ag_parse_cmer 374 * 375 * Description Parse AT+CMER parameter string. 376 * 377 * 378 * Returns true if parsed ok, false otherwise. 379 * 380 ******************************************************************************/ 381 static bool bta_ag_parse_cmer(char* p_s, bool* p_enabled) { 382 int16_t n[4] = {-1, -1, -1, -1}; 383 int i; 384 char* p; 385 386 for (i = 0; i < 4; i++) { 387 /* skip to comma delimiter */ 388 for (p = p_s; *p != ',' && *p != 0; p++) 389 ; 390 391 /* get integer value */ 392 *p = 0; 393 n[i] = utl_str2int(p_s); 394 p_s = p + 1; 395 if (p_s == 0) { 396 break; 397 } 398 } 399 400 /* process values */ 401 if (n[0] < 0 || n[3] < 0) { 402 return false; 403 } 404 405 if ((n[0] == 3) && ((n[3] == 1) || (n[3] == 0))) { 406 *p_enabled = (bool)n[3]; 407 } 408 409 return true; 410 } 411 412 /******************************************************************************* 413 * 414 * Function bta_ag_parse_chld 415 * 416 * Description Parse AT+CHLD parameter string. 417 * 418 * 419 * Returns Returns idx (1-7), 0 if ECC not enabled or 420 BTA_AG_INVALID_CHLD 421 if idx doesn't exist/1st character of argument is not a 422 digit 423 * 424 ******************************************************************************/ 425 static uint8_t bta_ag_parse_chld(UNUSED_ATTR tBTA_AG_SCB* p_scb, char* p_s) { 426 uint8_t retval = 0; 427 int16_t idx = -1; 428 429 if (!isdigit(p_s[0])) { 430 return BTA_AG_INVALID_CHLD; 431 } 432 433 if (p_s[1] != 0) { 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; 438 } else { 439 retval = BTA_AG_INVALID_CHLD; 440 } 441 } 442 443 return (retval); 444 } 445 446 /******************************************************************************* 447 * 448 * Function bta_ag_parse_bac 449 * 450 * Description Parse AT+BAC parameter string. 451 * 452 * Returns Returns bitmap of supported codecs. 453 * 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; 457 uint16_t uuid_codec; 458 bool cont = false; /* Continue processing */ 459 char* p; 460 461 while (p_s) { 462 /* skip to comma delimiter */ 463 for (p = p_s; *p != ',' && *p != 0; p++) 464 ; 465 466 /* get integre value */ 467 if (*p != 0) { 468 *p = 0; 469 cont = true; 470 } else 471 cont = false; 472 473 uuid_codec = utl_str2int(p_s); 474 switch (uuid_codec) { 475 case UUID_CODEC_CVSD: 476 retval |= BTA_AG_CODEC_CVSD; 477 break; 478 case UUID_CODEC_MSBC: 479 retval |= BTA_AG_CODEC_MSBC; 480 break; 481 default: 482 APPL_TRACE_ERROR("Unknown Codec UUID(%d) received", uuid_codec); 483 break; 484 } 485 486 if (cont) 487 p_s = p + 1; 488 else 489 break; 490 } 491 492 return (retval); 493 } 494 495 /******************************************************************************* 496 * 497 * Function bta_ag_process_unat_res 498 * 499 * Description Process the unat response data and remove extra carriage 500 * return and line feed 501 * 502 * 503 * Returns void 504 * 505 ******************************************************************************/ 506 507 static void bta_ag_process_unat_res(char* unat_result) { 508 uint8_t str_leng; 509 uint8_t i = 0; 510 uint8_t j = 0; 511 uint8_t pairs_of_nl_cr; 512 char trim_data[BTA_AG_AT_MAX_LEN]; 513 514 str_leng = strlen(unat_result); 515 516 /* If no extra CR and LF, just return */ 517 if (str_leng < 4) return; 518 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') { 523 pairs_of_nl_cr = 1; 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]; 526 } 527 /* Add EOF */ 528 trim_data[j] = '\0'; 529 str_leng = str_leng - 4; 530 strlcpy(unat_result, trim_data, str_leng + 1); 531 i = 0; 532 j = 0; 533 534 if (str_leng < 4) return; 535 } 536 return; 537 } 538 539 /******************************************************************************* 540 * 541 * Function bta_ag_inband_enabled 542 * 543 * Description Determine whether in-band ring can be used. 544 * 545 * 546 * Returns void 547 * 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)) { 552 return true; 553 } else { 554 return false; 555 } 556 } 557 558 /******************************************************************************* 559 * 560 * Function bta_ag_send_call_inds 561 * 562 * Description Send call and callsetup indicators. 563 * 564 * 565 * Returns void 566 * 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; 570 571 /* set new call and callsetup values based on BTA_AgResult */ 572 size_t callsetup = bta_ag_indicator_by_result_code(result); 573 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; 580 } else { 581 call = p_scb->call_ind; 582 } 583 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); 587 } 588 589 /******************************************************************************* 590 * 591 * Function bta_ag_at_hsp_cback 592 * 593 * Description AT command processing callback for HSP. 594 * 595 * 596 * Returns void 597 * 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, 602 int_arg, p_arg); 603 604 bta_ag_send_ok(p_scb); 605 606 tBTA_AG_VAL val; 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)); 611 612 /* call callback with event */ 613 (*bta_ag_cb.p_cback)(command_id, (tBTA_AG*)&val); 614 } 615 616 static void remove_spaces(char* str) { 617 char* dest_str = str; 618 619 while (*str) { 620 if (*str == ' ') { 621 str++; 622 } else { 623 *dest_str++ = *str++; 624 } 625 } 626 *dest_str = '\0'; 627 } 628 629 /******************************************************************************* 630 * 631 * Function bta_ag_find_empty_hf_ind) 632 * 633 * Description This function returns the index of an empty HF indicator 634 * structure. 635 * 636 * Returns int : index of the empty HF indicator structure or 637 * -1 if no empty indicator 638 * is available. 639 * 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; 644 } 645 646 return -1; 647 } 648 649 /******************************************************************************* 650 * 651 * Function bta_ag_find_hf_ind_by_id 652 * 653 * Description This function returns the index of the HF indicator 654 * structure by the indicator id 655 * 656 * Returns int : index of the HF indicator structure 657 * -1 if the indicator 658 * was not found. 659 * 660 ******************************************************************************/ 661 static int bta_ag_find_hf_ind_by_id(tBTA_AG_HF_IND* p_hf_ind, int size, 662 uint32_t ind_id) { 663 for (int index = 0; index < size; index++) { 664 if (p_hf_ind[index].ind_id == ind_id) return index; 665 } 666 667 return -1; 668 } 669 670 /******************************************************************************* 671 * 672 * Function bta_ag_parse_bind_set 673 * 674 * Description Parse AT+BIND set command and save the indicators 675 * 676 * Returns true if successful 677 * 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; 682 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); 686 if (index == -1) { 687 APPL_TRACE_WARNING("%s Can't save more indicators", __func__); 688 return false; 689 } 690 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); 693 694 p_token = strtok(NULL, ","); 695 } 696 697 return true; 698 } 699 700 /******************************************************************************* 701 * 702 * Function bta_ag_bind_response 703 * 704 * Description Send response for the AT+BIND command (HFP 1.7) received 705 * from the headset based on the argument types. 706 * 707 * Returns Void 708 * 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); 713 714 if (arg_type == BTA_AG_AT_TEST) { 715 int index = 0; 716 buffer[index++] = '('; 717 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); 724 } 725 } 726 727 buffer[index++] = ')'; 728 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) { 732 char* p = buffer; 733 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__); 738 break; 739 } 740 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; 747 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); 751 752 /* Check whether local and peer sides support this indicator */ 753 if (p_scb->local_hf_indicators[i].is_supported == true && 754 peer_index != -1) { 755 /* In the format of ind, state */ 756 p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].ind_id, p); 757 *p++ = ','; 758 p += utl_itoa((uint16_t)p_scb->local_hf_indicators[i].is_enable, p); 759 760 bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0); 761 762 memset(buffer, 0, sizeof(buffer)); 763 p = buffer; 764 } else { 765 /* If indicator is not supported, also set it to disable */ 766 p_scb->local_hf_indicators[i].is_enable = false; 767 } 768 } 769 770 bta_ag_send_ok(p_scb); 771 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); 774 } 775 } 776 777 /******************************************************************************* 778 * 779 * Function bta_ag_parse_biev_response 780 * 781 * Description Send response for AT+BIEV command (HFP 1.7) received from 782 * the headset based on the argument types. 783 * 784 * Returns true if the response was parsed successfully 785 * 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); 790 791 p_token = strtok(NULL, ","); 792 uint16_t rcv_ind_val = atoi(p_token); 793 794 APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id, 795 rcv_ind_val); 796 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__, 800 rcv_ind_id); 801 return false; 802 } 803 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__, 811 rcv_ind_id); 812 return false; 813 } 814 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); 819 return false; 820 } 821 822 val->lidx = rcv_ind_id; 823 val->num = rcv_ind_val; 824 825 return true; 826 } 827 828 /******************************************************************************* 829 * 830 * Function bta_ag_at_hfp_cback 831 * 832 * Description AT command processing callback for HFP. 833 * 834 * 835 * Returns void 836 * 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) { 840 tBTA_AG_VAL val; 841 tBTA_AG_SCB* ag_scb; 842 uint32_t i, ind_id; 843 uint32_t bia_masked_out; 844 if (p_arg == NULL) { 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); 847 return; 848 } 849 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); 852 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; 857 val.num = int_arg; 858 val.bd_addr = p_scb->peer_addr; 859 strlcpy(val.str, p_arg, sizeof(val.str)); 860 861 /** 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. 866 */ 867 tBTA_AG_EVT event = 0; 868 if (cmd < BTA_AG_LOCAL_EVT_FIRST) event = cmd; 869 870 switch (cmd) { 871 case BTA_AG_AT_A_EVT: 872 case BTA_AG_SPK_EVT: 873 case BTA_AG_MIC_EVT: 874 case BTA_AG_AT_CHUP_EVT: 875 case BTA_AG_AT_CBC_EVT: 876 /* send OK */ 877 bta_ag_send_ok(p_scb); 878 break; 879 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 */ 883 break; 884 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*/ 888 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); 894 895 if (!utl_isintstr(val.str + 1)) { 896 event = 0; 897 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR); 898 } 899 } else if (val.str[0] == 'V') /* ATDV : Dial VoIP Call */ 900 { 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))) { 904 event = 0; 905 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 906 } 907 } 908 /* If dial cmd, make sure string contains only dial digits 909 ** Dial digits are 0-9, A-C, *, #, + */ 910 else { 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); 914 915 if (!utl_isdialstr(val.str)) { 916 event = 0; 917 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR); 918 } 919 } 920 break; 921 922 case BTA_AG_LOCAL_EVT_CCWA: 923 /* store setting */ 924 p_scb->ccwa_enabled = (bool)int_arg; 925 926 /* send OK */ 927 bta_ag_send_ok(p_scb); 928 break; 929 930 case BTA_AG_AT_CHLD_EVT: 931 if (arg_type == BTA_AG_AT_TEST) { 932 /* don't call callback */ 933 event = 0; 934 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); 942 else 943 bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES, 944 p_bta_ag_cfg->chld_val, 0); 945 946 /* send OK */ 947 bta_ag_send_ok(p_scb); 948 949 /* if service level conn. not already open, now it's open */ 950 bta_ag_svc_conn_open(p_scb, NULL); 951 } else { 952 val.idx = bta_ag_parse_chld(p_scb, val.str); 953 954 if (val.idx == BTA_AG_INVALID_CHLD) { 955 event = 0; 956 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 957 break; 958 } 959 if (val.idx && 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 963 * index*/ 964 event = 0; 965 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 966 967 } else { 968 /* If it is swap between calls, set call held indicator to 3(out of 969 *valid 0-2) 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; 974 i++, ag_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; 979 } 980 } 981 } 982 } 983 984 /* Do not send OK. Let app decide after parsing the val str */ 985 /* bta_ag_send_ok(p_scb); */ 986 } 987 break; 988 989 case BTA_AG_AT_BIND_EVT: 990 APPL_TRACE_DEBUG("%s BTA_AG_AT_BIND_EVT arg_type: %d", __func__, 991 arg_type); 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); 995 } else { 996 event = 0; /* don't call callback */ 997 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX); 998 } 999 } else { 1000 bta_ag_bind_response(p_scb, arg_type); 1001 1002 /* Need not pass this command beyond BTIF.*/ 1003 /* Stack handles it internally */ 1004 event = 0; /* don't call callback */ 1005 } 1006 break; 1007 1008 case BTA_AG_AT_BIEV_EVT: 1009 if (bta_ag_parse_biev_response(p_scb, &val)) { 1010 bta_ag_send_ok(p_scb); 1011 } else { 1012 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX); 1013 /* don't call callback receiving invalid indicator */ 1014 event = 0; 1015 } 1016 break; 1017 1018 case BTA_AG_AT_CIND_EVT: 1019 if (arg_type == BTA_AG_AT_TEST) { 1020 /* don't call callback */ 1021 event = 0; 1022 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); 1026 } 1027 break; 1028 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); 1033 break; 1034 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); 1039 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 1042 */ 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); 1047 } 1048 } else { 1049 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 1050 } 1051 break; 1052 1053 case BTA_AG_AT_VTS_EVT: 1054 /* check argument */ 1055 if (strlen(p_arg) == 1) { 1056 bta_ag_send_ok(p_scb); 1057 } else { 1058 event = 0; 1059 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 1060 } 1061 break; 1062 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)) { 1066 event = 0; 1067 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1068 } 1069 break; 1070 1071 case BTA_AG_AT_BVRA_EVT: 1072 /* if feature not supported don't call callback, send ERROR. App will send 1073 * OK */ 1074 if (!(p_scb->features & BTA_AG_FEAT_VREC)) { 1075 event = 0; 1076 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1077 } 1078 break; 1079 1080 case BTA_AG_LOCAL_EVT_BRSF: { 1081 /* store peer features */ 1082 p_scb->peer_features = (uint16_t)int_arg; 1083 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; 1087 } 1088 1089 APPL_TRACE_DEBUG("%s BRSF HF: 0x%x, phone: 0x%x", __func__, 1090 p_scb->peer_features, features); 1091 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); 1095 break; 1096 } 1097 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); 1102 } else { 1103 event = 0; 1104 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1105 } 1106 break; 1107 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; 1114 i++, ag_scb++) { 1115 if (ag_scb->in_use) { 1116 bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, NULL, int_arg); 1117 } 1118 } 1119 bta_ag_send_ok(p_scb); 1120 } else /* Read Command */ 1121 { 1122 val.num = BTA_AG_BTRH_READ; 1123 } 1124 } else { 1125 event = 0; 1126 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1127 } 1128 break; 1129 1130 case BTA_AG_AT_COPS_EVT: 1131 if (arg_type == BTA_AG_AT_SET) { 1132 /* don't call callback */ 1133 event = 0; 1134 1135 /* send OK */ 1136 bta_ag_send_ok(p_scb); 1137 } 1138 break; 1139 1140 case BTA_AG_LOCAL_EVT_CMEE: 1141 if (p_scb->features & BTA_AG_FEAT_EXTERR) { 1142 /* store setting */ 1143 p_scb->cmee_enabled = (bool)int_arg; 1144 1145 /* send OK */ 1146 bta_ag_send_ok(p_scb); 1147 } else { 1148 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1149 } 1150 /* don't call callback */ 1151 event = 0; 1152 break; 1153 1154 case BTA_AG_LOCAL_EVT_BIA: 1155 /* don't call callback */ 1156 event = 0; 1157 1158 bia_masked_out = p_scb->bia_masked_out; 1159 1160 /* Parse the indicator mask */ 1161 for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); 1162 i++, ind_id++) { 1163 if (val.str[i] == ',') continue; 1164 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); 1169 else 1170 break; 1171 1172 i++; 1173 if ((val.str[i] == 0) || (val.str[i] != ',')) break; 1174 } 1175 if (val.str[i] == 0) { 1176 p_scb->bia_masked_out = bia_masked_out; 1177 bta_ag_send_ok(p_scb); 1178 } else 1179 bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX); 1180 break; 1181 1182 case BTA_AG_AT_CNUM_EVT: 1183 break; 1184 1185 case BTA_AG_AT_CLCC_EVT: 1186 if (!(p_scb->features & BTA_AG_FEAT_ECS)) { 1187 event = 0; 1188 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1189 } 1190 break; 1191 1192 case BTA_AG_AT_BAC_EVT: 1193 bta_ag_send_ok(p_scb); 1194 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; 1200 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"); 1204 } else { 1205 p_scb->sco_codec = UUID_CODEC_CVSD; 1206 APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to CVSD"); 1207 } 1208 /* The above logic sets the stack preferred codec based on local and 1209 peer codec 1210 capabilities. This can be overridden by the application depending on its 1211 preference 1212 using the bta_ag_setcodec API. We send the peer_codecs to the 1213 application. */ 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); 1219 } 1220 } else { 1221 p_scb->peer_codecs = BTA_AG_CODEC_CVSD; 1222 APPL_TRACE_ERROR( 1223 "Unexpected CMD:AT+BAC, Codec Negotiation is not supported"); 1224 } 1225 break; 1226 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); 1231 1232 switch (int_arg) { 1233 case UUID_CODEC_CVSD: 1234 codec_type = BTA_AG_CODEC_CVSD; 1235 break; 1236 case UUID_CODEC_MSBC: 1237 codec_type = BTA_AG_CODEC_MSBC; 1238 break; 1239 default: 1240 APPL_TRACE_ERROR("Unknown codec_uuid %d", int_arg); 1241 codec_type = 0xFFFF; 1242 break; 1243 } 1244 1245 if (p_scb->codec_fallback) 1246 codec_sent = BTA_AG_CODEC_CVSD; 1247 else 1248 codec_sent = p_scb->sco_codec; 1249 1250 if (codec_type == codec_sent) 1251 bta_ag_sco_codec_nego(p_scb, true); 1252 else 1253 bta_ag_sco_codec_nego(p_scb, false); 1254 1255 /* send final codec info to callback */ 1256 val.num = codec_sent; 1257 break; 1258 } 1259 case BTA_AG_LOCAL_EVT_BCC: 1260 bta_ag_send_ok(p_scb); 1261 bta_ag_sco_open(p_scb, NULL); 1262 break; 1263 1264 default: 1265 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1266 break; 1267 } 1268 1269 /* call callback */ 1270 if (event != 0) { 1271 (*bta_ag_cb.p_cback)(event, (tBTA_AG*)&val); 1272 } 1273 } 1274 1275 /******************************************************************************* 1276 * 1277 * Function bta_ag_at_err_cback 1278 * 1279 * Description AT command parser error callback. 1280 * 1281 * 1282 * Returns void 1283 * 1284 ******************************************************************************/ 1285 void bta_ag_at_err_cback(tBTA_AG_SCB* p_scb, bool unknown, char* p_arg) { 1286 tBTA_AG_VAL val; 1287 1288 if (unknown && (!strlen(p_arg))) { 1289 APPL_TRACE_DEBUG("Empty AT cmd string received"); 1290 bta_ag_send_ok(p_scb); 1291 return; 1292 } 1293 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; 1299 val.num = 0; 1300 strlcpy(val.str, p_arg, sizeof(val.str)); 1301 (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG*)&val); 1302 } else { 1303 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); 1304 } 1305 } 1306 1307 /******************************************************************************* 1308 * 1309 * Function bta_ag_hsp_result 1310 * 1311 * Description Handle API result for HSP connections. 1312 * 1313 * 1314 * Returns void 1315 * 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); 1319 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); 1324 break; 1325 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); 1329 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); 1334 } else { 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; 1339 } else { 1340 p_scb->post_sco = BTA_AG_POST_SCO_RING; 1341 } 1342 bta_ag_sco_open(p_scb, (tBTA_AG_DATA*)p_result); 1343 } 1344 break; 1345 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); 1351 } 1352 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); 1358 } 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); 1363 } 1364 } 1365 break; 1366 1367 case BTA_AG_END_CALL_RES: 1368 alarm_cancel(p_scb->ring_timer); 1369 1370 /* close sco */ 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); 1374 } else { 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); 1377 } 1378 break; 1379 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); 1383 break; 1384 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); 1389 } 1390 1391 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb); 1392 } else { 1393 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR); 1394 } 1395 break; 1396 1397 default: 1398 /* ignore all others */ 1399 break; 1400 } 1401 } 1402 1403 /******************************************************************************* 1404 * 1405 * Function bta_ag_hfp_result 1406 * 1407 * Description Handle API result for HFP connections. 1408 * 1409 * 1410 * Returns void 1411 * 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); 1415 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); 1420 break; 1421 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); 1425 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; 1434 } 1435 1436 APPL_TRACE_DEBUG("CLIP type :%d", p_result->data.num); 1437 p_scb->clip[0] = 0; 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); 1441 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 1445 * close. */ 1446 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL; 1447 } else { 1448 bta_ag_send_call_inds(p_scb, p_result->result); 1449 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); 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*)p_result); 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, p_result->result); 1469 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); 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, p_result->result); 1485 1486 break; 1487 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); 1493 } 1494 break; 1495 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); 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 (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); 1513 } 1514 break; 1515 1516 case BTA_AG_OUT_CALL_CONN_RES: 1517 /* send indicators */ 1518 bta_ag_send_call_inds(p_scb, p_result->result); 1519 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); 1526 } 1527 } 1528 break; 1529 1530 case BTA_AG_CALL_CANCEL_RES: 1531 /* send indicators */ 1532 bta_ag_send_call_inds(p_scb, p_result->result); 1533 break; 1534 1535 case BTA_AG_END_CALL_RES: 1536 alarm_cancel(p_scb->ring_timer); 1537 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; 1547 } else { 1548 bta_ag_send_call_inds(p_scb, p_result->result); 1549 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); 1552 } 1553 break; 1554 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); 1559 break; 1560 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); 1572 1573 bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0); 1574 bta_ag_send_ok(p_scb); 1575 break; 1576 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); 1584 } 1585 1586 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb); 1587 } else { 1588 bta_ag_send_error(p_scb, p_result->data.errcode); 1589 } 1590 break; 1591 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); 1598 } 1599 1600 if (p_result->data.ok_flag == BTA_AG_OK_DONE) bta_ag_send_ok(p_scb); 1601 } else { 1602 bta_ag_send_error(p_scb, p_result->data.errcode); 1603 } 1604 break; 1605 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); 1609 } 1610 bta_ag_send_call_inds(p_scb, p_result->result); 1611 break; 1612 1613 case BTA_AG_IND_RES: 1614 bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value, 1615 false); 1616 break; 1617 1618 case BTA_AG_BVRA_RES: 1619 bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state); 1620 break; 1621 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); 1627 } 1628 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); 1631 } else { 1632 bta_ag_send_error(p_scb, p_result->data.errcode); 1633 } 1634 break; 1635 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); 1644 return; 1645 } 1646 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); 1654 return; 1655 } else { 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}; 1661 char* p = buffer; 1662 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); 1666 *p++ = ','; 1667 p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p); 1668 1669 bta_ag_send_result(p_scb, p_result->result, buffer, 0); 1670 } else { 1671 APPL_TRACE_DEBUG( 1672 "%s HF Indicator %d already %s", p_result->data.ind.id, 1673 (p_result->data.ind.on_demand == true) ? "Enabled" : "Disabled"); 1674 } 1675 } 1676 break; 1677 } 1678 1679 default: 1680 break; 1681 } 1682 } 1683 1684 /******************************************************************************* 1685 * 1686 * Function bta_ag_result 1687 * 1688 * Description Handle API result. 1689 * 1690 * 1691 * Returns void 1692 * 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); 1697 } else { 1698 bta_ag_hfp_result(p_scb, &p_data->api_result); 1699 } 1700 } 1701 1702 /******************************************************************************* 1703 * 1704 * Function bta_ag_send_bcs 1705 * 1706 * Description Send +BCS AT command to peer. 1707 * 1708 * Returns void 1709 * 1710 ******************************************************************************/ 1711 void bta_ag_send_bcs(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) { 1712 uint16_t codec_uuid; 1713 1714 if (p_scb->codec_fallback) { 1715 codec_uuid = UUID_CODEC_CVSD; 1716 } else { 1717 switch (p_scb->sco_codec) { 1718 case BTA_AG_CODEC_NONE: 1719 codec_uuid = UUID_CODEC_CVSD; 1720 break; 1721 case BTA_AG_CODEC_CVSD: 1722 codec_uuid = UUID_CODEC_CVSD; 1723 break; 1724 case BTA_AG_CODEC_MSBC: 1725 codec_uuid = UUID_CODEC_MSBC; 1726 break; 1727 default: 1728 APPL_TRACE_ERROR("bta_ag_send_bcs: unknown codec %d, use CVSD", 1729 p_scb->sco_codec); 1730 codec_uuid = UUID_CODEC_CVSD; 1731 break; 1732 } 1733 } 1734 1735 /* send +BCS */ 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); 1738 } 1739 1740 /******************************************************************************* 1741 * 1742 * Function bta_ag_send_ring 1743 * 1744 * Description Send RING result code to peer. 1745 * 1746 * 1747 * Returns void 1748 * 1749 ******************************************************************************/ 1750 void bta_ag_send_ring(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) { 1751 /* send RING */ 1752 bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, NULL, 0); 1753 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); 1758 } 1759 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)); 1762 } 1763