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