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