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