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