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