1 /****************************************************************************** 2 * 3 * Copyright (c) 2014 The Android Open Source Project 4 * Copyright (C) 2003-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 #include <string.h> 20 #include <stdio.h> 21 #include <errno.h> 22 #include "bta_hf_client_api.h" 23 #include "bta_hf_client_int.h" 24 #include "port_api.h" 25 26 /* Uncomment to enable AT traffic dumping */ 27 /* #define BTA_HF_CLIENT_AT_DUMP 1 */ 28 29 /* minimum length of AT event */ 30 #define BTA_HF_CLIENT_AT_EVENT_MIN_LEN 3 31 32 /* timeout for AT response */ 33 #define BTA_HF_CLIENT_AT_TIMEOUT 29989 34 35 /* timeout for AT hold timer */ 36 #define BTA_HF_CLIENT_AT_HOLD_TIMEOUT 41 37 38 /****************************************************************************** 39 ** 40 ** DATA TYPES AND CONTAINERS 41 ** 42 *******************************************************************************/ 43 /* BRSF: store received values here */ 44 extern tBTA_HF_CLIENT_CB bta_hf_client_cb; 45 46 /****************************************************************************** 47 ** SUPPORTED EVENT MESSAGES 48 *******************************************************************************/ 49 50 /* CIND: supported indicator names */ 51 #define BTA_HF_CLIENT_INDICATOR_BATTERYCHG "battchg" 52 #define BTA_HF_CLIENT_INDICATOR_SIGNAL "signal" 53 #define BTA_HF_CLIENT_INDICATOR_SERVICE "service" 54 #define BTA_HF_CLIENT_INDICATOR_CALL "call" 55 #define BTA_HF_CLIENT_INDICATOR_ROAM "roam" 56 #define BTA_HF_CLIENT_INDICATOR_CALLSETUP "callsetup" 57 #define BTA_HF_CLIENT_INDICATOR_CALLHELD "callheld" 58 59 /* CIND: represents each indicators boundaries */ 60 typedef struct 61 { 62 char* name; 63 UINT8 min; 64 UINT8 max; 65 UINT8 namelen; 66 } tBTA_HF_CLIENT_INDICATOR; 67 68 #define BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT 7 69 70 /* CIND: storage room for indicators value range and their statuses */ 71 static const tBTA_HF_CLIENT_INDICATOR bta_hf_client_indicators[BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT] = 72 { 73 /* name | min | max | name length - used by parser */ 74 {BTA_HF_CLIENT_INDICATOR_BATTERYCHG, 0, 5, sizeof(BTA_HF_CLIENT_INDICATOR_BATTERYCHG)}, 75 {BTA_HF_CLIENT_INDICATOR_SIGNAL, 0, 5, sizeof(BTA_HF_CLIENT_INDICATOR_SIGNAL)}, 76 {BTA_HF_CLIENT_INDICATOR_SERVICE, 0, 1, sizeof(BTA_HF_CLIENT_INDICATOR_SERVICE)}, 77 {BTA_HF_CLIENT_INDICATOR_CALL, 0, 1, sizeof(BTA_HF_CLIENT_INDICATOR_CALL)}, 78 {BTA_HF_CLIENT_INDICATOR_ROAM, 0, 1, sizeof(BTA_HF_CLIENT_INDICATOR_ROAM)}, 79 {BTA_HF_CLIENT_INDICATOR_CALLSETUP, 0, 3, sizeof(BTA_HF_CLIENT_INDICATOR_CALLSETUP)}, 80 {BTA_HF_CLIENT_INDICATOR_CALLHELD, 0, 2, sizeof(BTA_HF_CLIENT_INDICATOR_CALLHELD)} 81 }; 82 83 /* +VGM/+VGS - gain min/max values */ 84 #define BTA_HF_CLIENT_VGS_MIN 0 85 #define BTA_HF_CLIENT_VGS_MAX 15 86 #define BTA_HF_CLIENT_VGM_MIN 0 87 #define BTA_HF_CLIENT_VGM_MAX 15 88 89 UINT32 service_index = 0; 90 BOOLEAN service_availability = TRUE; 91 /* helper functions for handling AT commands queueing */ 92 93 static void bta_hf_client_clear_queued_at(void) 94 { 95 tBTA_HF_CLIENT_AT_QCMD *cur = bta_hf_client_cb.scb.at_cb.queued_cmd; 96 tBTA_HF_CLIENT_AT_QCMD *next; 97 98 while (cur != NULL) { 99 next = cur->next; 100 GKI_freebuf(cur); 101 cur = next; 102 } 103 104 bta_hf_client_cb.scb.at_cb.queued_cmd = NULL; 105 } 106 107 static void bta_hf_client_queue_at(tBTA_HF_CLIENT_AT_CMD cmd, const char *buf, UINT16 buf_len) 108 { 109 tBTA_HF_CLIENT_AT_QCMD *new_cmd; 110 111 APPL_TRACE_DEBUG("%s", __FUNCTION__); 112 113 if ((new_cmd = (tBTA_HF_CLIENT_AT_QCMD *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_AT_QCMD))) != NULL) 114 { 115 new_cmd->cmd = cmd; 116 new_cmd->buf_len = buf_len; 117 new_cmd->next = NULL; 118 memcpy(new_cmd->buf, buf, buf_len); 119 120 if (bta_hf_client_cb.scb.at_cb.queued_cmd != NULL) 121 { 122 tBTA_HF_CLIENT_AT_QCMD *qcmd = bta_hf_client_cb.scb.at_cb.queued_cmd; 123 124 while (qcmd->next != NULL) 125 qcmd = qcmd->next; 126 127 qcmd->next = new_cmd; 128 } 129 else 130 { 131 bta_hf_client_cb.scb.at_cb.queued_cmd = new_cmd; 132 } 133 } 134 } 135 136 static void bta_hf_client_at_resp_timer_cback (TIMER_LIST_ENT *p_tle) 137 { 138 if (p_tle) 139 { 140 bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE; 141 142 APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting"); 143 144 bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); 145 } 146 } 147 148 static void bta_hf_client_stop_at_resp_timer(void) 149 { 150 if (bta_hf_client_cb.scb.at_cb.resp_timer_on) 151 { 152 bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE; 153 bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.resp_timer); 154 } 155 } 156 157 static void bta_hf_client_start_at_resp_timer(void) 158 { 159 if (bta_hf_client_cb.scb.at_cb.resp_timer_on) 160 { 161 bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.resp_timer); 162 } 163 164 bta_hf_client_cb.scb.at_cb.resp_timer.p_cback = (TIMER_CBACK*)&bta_hf_client_at_resp_timer_cback; 165 bta_sys_start_timer(&bta_hf_client_cb.scb.at_cb.resp_timer, 0, BTA_HF_CLIENT_AT_TIMEOUT); 166 bta_hf_client_cb.scb.at_cb.resp_timer_on = TRUE; 167 } 168 169 static void bta_hf_client_send_at(tBTA_HF_CLIENT_AT_CMD cmd, char *buf, UINT16 buf_len) 170 { 171 if ((bta_hf_client_cb.scb.at_cb.current_cmd == BTA_HF_CLIENT_AT_NONE || 172 bta_hf_client_cb.scb.svc_conn == FALSE) && 173 bta_hf_client_cb.scb.at_cb.hold_timer_on == FALSE) 174 { 175 UINT16 len; 176 177 #ifdef BTA_HF_CLIENT_AT_DUMP 178 APPL_TRACE_DEBUG("%s %.*s", __FUNCTION__, buf_len - 1, buf); 179 #endif 180 181 bta_hf_client_cb.scb.at_cb.current_cmd = cmd; 182 PORT_WriteData(bta_hf_client_cb.scb.conn_handle, buf, buf_len, &len); 183 184 bta_hf_client_start_at_resp_timer(); 185 186 return; 187 } 188 189 bta_hf_client_queue_at(cmd, buf, buf_len); 190 } 191 192 static void bta_hf_client_send_queued_at(void) 193 { 194 tBTA_HF_CLIENT_AT_QCMD *cur = bta_hf_client_cb.scb.at_cb.queued_cmd; 195 tBTA_HF_CLIENT_AT_QCMD *next; 196 197 APPL_TRACE_DEBUG("%s", __FUNCTION__); 198 199 if (cur != NULL) 200 { 201 next = cur->next; 202 203 bta_hf_client_send_at(cur->cmd, cur->buf, cur->buf_len); 204 205 GKI_freebuf(cur); 206 207 bta_hf_client_cb.scb.at_cb.queued_cmd = next; 208 } 209 } 210 211 static void bta_hf_client_at_hold_timer_cback(TIMER_LIST_ENT *p_tle) 212 { 213 APPL_TRACE_DEBUG("%s", __FUNCTION__); 214 215 if (p_tle) 216 { 217 bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE; 218 bta_hf_client_send_queued_at(); 219 } 220 } 221 222 static void bta_hf_client_stop_at_hold_timer(void) 223 { 224 APPL_TRACE_DEBUG("%s", __FUNCTION__); 225 226 if (bta_hf_client_cb.scb.at_cb.hold_timer_on) 227 { 228 bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE; 229 bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.hold_timer); 230 } 231 } 232 233 static void bta_hf_client_start_at_hold_timer(void) 234 { 235 TIMER_LIST_ENT *timer = &bta_hf_client_cb.scb.at_cb.hold_timer; 236 237 APPL_TRACE_DEBUG("%s", __FUNCTION__); 238 239 if (bta_hf_client_cb.scb.at_cb.hold_timer_on) 240 { 241 bta_sys_stop_timer (timer); 242 } 243 244 timer->p_cback = (TIMER_CBACK*)&bta_hf_client_at_hold_timer_cback; 245 bta_sys_start_timer(timer, 0, BTA_HF_CLIENT_AT_HOLD_TIMEOUT); 246 bta_hf_client_cb.scb.at_cb.hold_timer_on = TRUE; 247 } 248 249 /****************************************************************************** 250 ** 251 ** COMMON AT EVENT HANDLING FUNCTIONS 252 ** 253 ** Receives data (strings, ints, etc.) from the parser and processes this data. 254 ** No buffer parsing is being done here. 255 *******************************************************************************/ 256 257 static void bta_hf_client_handle_ok() 258 { 259 APPL_TRACE_DEBUG("%s", __FUNCTION__); 260 261 bta_hf_client_stop_at_resp_timer(); 262 263 if (!bta_hf_client_cb.scb.svc_conn) 264 { 265 bta_hf_client_slc_seq(FALSE); 266 return; 267 } 268 269 switch(bta_hf_client_cb.scb.at_cb.current_cmd) 270 { 271 case BTA_HF_CLIENT_AT_BIA: 272 case BTA_HF_CLIENT_AT_BCC: 273 break; 274 case BTA_HF_CLIENT_AT_BCS: 275 bta_hf_client_start_at_hold_timer(); 276 bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; 277 return; 278 case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq 279 if (bta_hf_client_cb.scb.send_at_reply == FALSE) 280 { 281 bta_hf_client_cb.scb.send_at_reply = TRUE; 282 } 283 break; 284 case BTA_HF_CLIENT_AT_NONE: 285 bta_hf_client_stop_at_hold_timer(); 286 break; 287 default: 288 if (bta_hf_client_cb.scb.send_at_reply) 289 { 290 bta_hf_client_at_result(BTA_HF_CLIENT_AT_RESULT_OK, 0); 291 } 292 break; 293 } 294 295 bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; 296 297 bta_hf_client_send_queued_at(); 298 } 299 300 static void bta_hf_client_handle_error(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme) 301 { 302 APPL_TRACE_DEBUG("%s %u %u", __FUNCTION__, type, cme); 303 304 bta_hf_client_stop_at_resp_timer(); 305 306 if (!bta_hf_client_cb.scb.svc_conn) 307 { 308 bta_hf_client_slc_seq(TRUE); 309 return; 310 } 311 312 switch(bta_hf_client_cb.scb.at_cb.current_cmd) 313 { 314 case BTA_HF_CLIENT_AT_BIA: 315 break; 316 case BTA_HF_CLIENT_AT_BCC: 317 case BTA_HF_CLIENT_AT_BCS: 318 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); 319 break; 320 case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq 321 if (bta_hf_client_cb.scb.send_at_reply == FALSE) 322 { 323 bta_hf_client_cb.scb.send_at_reply = TRUE; 324 } 325 break; 326 default: 327 if (bta_hf_client_cb.scb.send_at_reply) 328 { 329 bta_hf_client_at_result(type, cme); 330 } 331 break; 332 } 333 334 bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; 335 336 bta_hf_client_send_queued_at(); 337 } 338 339 static void bta_hf_client_handle_ring() 340 { 341 APPL_TRACE_DEBUG("%s", __FUNCTION__); 342 bta_hf_client_evt_val(BTA_HF_CLIENT_RING_INDICATION,0); 343 } 344 345 static void bta_hf_client_handle_brsf(UINT32 value) 346 { 347 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, value); 348 bta_hf_client_cb.scb.peer_features = value; 349 } 350 351 /* handles a single indicator descriptor - registers it for value changing events */ 352 static void bta_hf_client_handle_cind_list_item(char *name, UINT32 min, UINT32 max, UINT32 index) 353 { 354 355 UINT8 i = 0; 356 357 APPL_TRACE_DEBUG("%s %lu.%s <%lu:%lu>", __FUNCTION__, index, name, min, max); 358 359 /* look for a matching indicator on list of supported ones */ 360 for(i = 0; i < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT; i++) 361 { 362 if (strcmp(name,BTA_HF_CLIENT_INDICATOR_SERVICE) == 0) 363 { 364 service_index = index; 365 } 366 /* look for a match - search one sign further than indicators name to check for string end */ 367 /* It will distinguish 'callheld' which could be matched by strncmp as 'call'. */ 368 if (strncmp(name, bta_hf_client_indicators[i].name, bta_hf_client_indicators[i].namelen) != 0) 369 continue; 370 371 /* index - enumerates value position in the incoming sequence */ 372 /* if name matches one of the known indicators, add its incoming position */ 373 /* to lookup table for easy value->indicator matching later, when only values come */ 374 bta_hf_client_cb.scb.at_cb.indicator_lookup[index] = i; 375 376 return; 377 } 378 } 379 380 static void bta_hf_client_handle_cind_value(UINT32 index, UINT32 value) 381 { 382 APPL_TRACE_DEBUG("%s index: %u value: %u", __FUNCTION__, index, value); 383 384 if (index >= BTA_HF_CLIENT_AT_INDICATOR_COUNT) 385 { 386 return; 387 } 388 389 if (service_index == index) 390 { 391 if (value == 0) 392 { 393 service_availability = FALSE; 394 } 395 else 396 { 397 service_availability = TRUE; 398 } 399 } 400 if (bta_hf_client_cb.scb.at_cb.indicator_lookup[index] == -1) 401 { 402 return; 403 } 404 405 /* get the real array index from lookup table */ 406 index = bta_hf_client_cb.scb.at_cb.indicator_lookup[index]; 407 408 /* Ignore out of range values */ 409 if(value > bta_hf_client_indicators[index].max || 410 value < bta_hf_client_indicators[index].min) 411 { 412 return; 413 } 414 415 /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */ 416 bta_hf_client_ind(index, value); 417 } 418 419 static void bta_hf_client_handle_chld(UINT32 mask) 420 { 421 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, mask); 422 423 bta_hf_client_cb.scb.chld_features |= mask; 424 } 425 426 static void bta_hf_client_handle_ciev(UINT32 index, UINT32 value) 427 { 428 INT8 realind = -1; 429 430 APPL_TRACE_DEBUG("%s index: %u value: %u", __FUNCTION__, index, value); 431 432 if(index == 0 || index >= BTA_HF_CLIENT_AT_INDICATOR_COUNT) 433 { 434 return; 435 } 436 437 realind = bta_hf_client_cb.scb.at_cb.indicator_lookup[index - 1]; 438 439 if(realind >= 0 && realind < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT) 440 { 441 /* get the real in-array index from lookup table by index it comes at */ 442 /* if there is no bug it should automatically be correctly calculated */ 443 if(value > bta_hf_client_indicators[realind].max || value < bta_hf_client_indicators[realind].min) 444 { 445 return; 446 } 447 448 /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */ 449 bta_hf_client_ind(realind, value); 450 } 451 } 452 453 static void bta_hf_client_handle_bcs(UINT32 codec) 454 { 455 APPL_TRACE_DEBUG("%s %u", __FUNCTION__, codec); 456 457 if (codec == BTM_SCO_CODEC_CVSD || 458 (codec == BTM_SCO_CODEC_MSBC && bta_hf_client_cb.msbc_enabled == TRUE)) 459 { 460 bta_hf_client_cb.scb.negotiated_codec = codec; 461 bta_hf_client_send_at_bcs(codec); 462 } 463 else 464 { 465 bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; 466 bta_hf_client_send_at_bac(); 467 } 468 } 469 470 static void bta_hf_client_handle_bsir(UINT32 provided) 471 { 472 APPL_TRACE_DEBUG("%s %u", __FUNCTION__, provided); 473 474 bta_hf_client_evt_val(BTA_HF_CLIENT_BSIR_EVT, provided); 475 } 476 477 static void bta_hf_client_handle_cmeerror(UINT32 code) 478 { 479 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_CME, code); 480 } 481 482 static void bta_hf_client_handle_vgm(UINT32 value) 483 { 484 APPL_TRACE_DEBUG("%s %lu", __FUNCTION__, value); 485 486 if(value <= BTA_HF_CLIENT_VGM_MAX) 487 { 488 bta_hf_client_evt_val(BTA_HF_CLIENT_MIC_EVT, value); 489 } 490 } 491 492 static void bta_hf_client_handle_vgs(UINT32 value) 493 { 494 APPL_TRACE_DEBUG("%s %lu", __FUNCTION__, value); 495 496 if(value <= BTA_HF_CLIENT_VGS_MAX) 497 { 498 bta_hf_client_evt_val(BTA_HF_CLIENT_SPK_EVT, value); 499 } 500 } 501 502 static void bta_hf_client_handle_bvra(UINT32 value) 503 { 504 APPL_TRACE_DEBUG("%s %lu", __FUNCTION__, value); 505 506 if (value > 1) 507 { 508 return; 509 } 510 511 bta_hf_client_evt_val(BTA_HF_CLIENT_VOICE_REC_EVT, value); 512 } 513 514 static void bta_hf_client_handle_clip(char *numstr, UINT32 type) 515 { 516 APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, type, numstr); 517 518 bta_hf_client_clip(numstr); 519 } 520 521 static void bta_hf_client_handle_ccwa(char *numstr, UINT32 type) 522 { 523 APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, type, numstr); 524 525 bta_hf_client_ccwa(numstr); 526 } 527 528 static void bta_hf_client_handle_cops(char *opstr, UINT32 mode) 529 { 530 APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, mode, opstr); 531 532 bta_hf_client_operator_name(opstr); 533 } 534 535 static void bta_hf_client_handle_binp(char *numstr) 536 { 537 APPL_TRACE_DEBUG("%s %s", __FUNCTION__, numstr); 538 539 bta_hf_client_binp(numstr); 540 } 541 542 static void bta_hf_client_handle_clcc(UINT16 idx, UINT16 dir, UINT16 status, UINT16 mode, UINT16 mpty, char *numstr, UINT16 type) 543 { 544 APPL_TRACE_DEBUG("%s idx: %u dir: %u status: %u mode: %u mpty: %u", 545 __FUNCTION__, idx, dir, status, mode, mpty); 546 547 if (numstr) 548 { 549 APPL_TRACE_DEBUG("%s number: %s type: %u", __FUNCTION__, numstr, type); 550 } 551 552 bta_hf_client_clcc(idx, dir, status, mpty, numstr); 553 } 554 555 static void bta_hf_client_handle_cnum( char *numstr, UINT16 type, UINT16 service) 556 { 557 APPL_TRACE_DEBUG("%s number: %s type: %u service: %u", __FUNCTION__, numstr, type, service); 558 559 /* TODO: should number be modified according to type? */ 560 bta_hf_client_cnum(numstr, service); 561 } 562 563 static void bta_hf_client_handle_btrh( UINT16 code) 564 { 565 APPL_TRACE_DEBUG("%s %lu", __FUNCTION__, code); 566 567 bta_hf_client_evt_val(BTA_HF_CLIENT_BTRH_EVT, code); 568 } 569 570 /****************************************************************************** 571 ** 572 ** COMMON AT EVENTS PARSING FUNCTIONS 573 ** 574 *******************************************************************************/ 575 576 /* Check if prefix match and skip spaces if any */ 577 #define AT_CHECK_EVENT(buf, event) \ 578 if (strncmp("\r\n"event, buf,sizeof("\r\n"event) - 1) != 0) return buf; \ 579 buf += sizeof("\r\n"event) - 1; \ 580 while (*buf == ' ') buf++; 581 582 /* check for <cr><lf> and forward buffer if match */ 583 #define AT_CHECK_RN(buf) \ 584 if (strncmp("\r\n", buf, sizeof("\r\n") - 1) != 0) { \ 585 APPL_TRACE_DEBUG("%s missing end <cr><lf>", __FUNCTION__); \ 586 return NULL;} \ 587 buf += sizeof("\r\n") - 1; 588 589 /* skip rest of AT string up to <cr> */ 590 #define AT_SKIP_REST(buf) while(*buf != '\r') buf++; 591 592 static char *bta_hf_client_parse_ok(char *buffer) 593 { 594 AT_CHECK_EVENT(buffer, "OK"); 595 AT_CHECK_RN(buffer); 596 597 bta_hf_client_handle_ok(); 598 599 return buffer; 600 } 601 602 static char *bta_hf_client_parse_error(char *buffer) 603 { 604 AT_CHECK_EVENT(buffer, "ERROR"); 605 AT_CHECK_RN(buffer); 606 607 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_ERROR, 0); 608 609 return buffer; 610 } 611 612 static char *bta_hf_client_parse_ring(char *buffer) 613 { 614 AT_CHECK_EVENT(buffer, "RING"); 615 AT_CHECK_RN(buffer); 616 617 bta_hf_client_handle_ring(); 618 619 return buffer; 620 } 621 622 /* generic uint32 parser */ 623 static char *bta_hf_client_parse_uint32(char *buffer, void (*handler_callback)(UINT32)) 624 { 625 UINT32 value; 626 int res; 627 int offset; 628 629 res = sscanf(buffer, "%u%n", &value, &offset); 630 if (res < 1) 631 { 632 return NULL; 633 } 634 635 buffer += offset; 636 637 AT_CHECK_RN(buffer); 638 639 handler_callback(value); 640 return buffer; 641 } 642 643 static char *bta_hf_client_parse_brsf(char *buffer) 644 { 645 AT_CHECK_EVENT(buffer, "+BRSF:"); 646 647 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_brsf); 648 } 649 650 static char *bta_hf_client_parse_cind_values(char *buffer) 651 { 652 /* value and its position */ 653 UINT16 index = 0; 654 UINT32 value = 0; 655 656 int offset; 657 int res; 658 659 while((res = sscanf(buffer, "%u%n", &value, &offset)) > 0) 660 { 661 /* decides if its valid index and value, if yes stores it */ 662 bta_hf_client_handle_cind_value(index, value); 663 664 buffer += offset; 665 666 /* check if more values are present */ 667 if (*buffer != ',') 668 { 669 break; 670 } 671 672 index++; 673 buffer++; 674 } 675 676 if (res > 0) 677 { 678 AT_CHECK_RN(buffer); 679 return buffer; 680 } 681 682 return NULL; 683 } 684 685 static char *bta_hf_client_parse_cind_list(char *buffer) 686 { 687 int offset; 688 char name[129]; 689 UINT32 min, max; 690 UINT32 index = 0; 691 int res; 692 693 while ((res = sscanf(buffer, "(\"%128[^\"]\",(%u%*[-,]%u))%n", name, &min, &max, &offset)) > 2) 694 { 695 bta_hf_client_handle_cind_list_item(name, min, max, index); 696 buffer += offset; 697 index++; 698 699 if (*buffer != ',') 700 { 701 break; 702 } 703 704 buffer++; 705 } 706 707 if (res > 2) 708 { 709 AT_CHECK_RN(buffer); 710 return buffer; 711 } 712 713 return NULL; 714 } 715 716 static char *bta_hf_client_parse_cind(char *buffer) 717 { 718 AT_CHECK_EVENT(buffer, "+CIND:"); 719 720 if(*buffer == '(') 721 return bta_hf_client_parse_cind_list(buffer); 722 723 return bta_hf_client_parse_cind_values(buffer); 724 } 725 726 static char *bta_hf_client_parse_chld(char *buffer) 727 { 728 AT_CHECK_EVENT(buffer, "+CHLD:"); 729 730 if (*buffer != '(') 731 { 732 return NULL; 733 } 734 735 buffer++; 736 737 while(*buffer != '\0') 738 { 739 if(strncmp("0",buffer, 1) == 0) 740 { 741 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL); 742 buffer++; 743 } 744 else if(strncmp("1x",buffer, 2) == 0) 745 { 746 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL_X); 747 buffer += 2; 748 } 749 else if(strncmp("1",buffer, 1) == 0) 750 { 751 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL_ACC); 752 buffer++; 753 } 754 else if(strncmp("2x",buffer, 2) == 0) 755 { 756 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_PRIV_X); 757 buffer += 2; 758 } 759 else if(strncmp("2",buffer, 1) == 0) 760 { 761 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_HOLD_ACC); 762 buffer++; 763 } 764 else if(strncmp("3",buffer, 1) == 0) 765 { 766 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_MERGE); 767 buffer++; 768 } 769 else if(strncmp("4",buffer, 1) == 0) 770 { 771 bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_MERGE_DETACH); 772 buffer++; 773 } 774 else 775 { 776 return NULL; 777 } 778 779 if (*buffer == ',') 780 { 781 buffer++; 782 continue; 783 } 784 785 if (*buffer == ')') 786 { 787 buffer++; 788 break; 789 } 790 791 return NULL; 792 } 793 794 AT_CHECK_RN(buffer); 795 796 return buffer; 797 } 798 799 static char *bta_hf_client_parse_ciev(char *buffer) 800 { 801 UINT32 index, value; 802 int res; 803 int offset; 804 805 AT_CHECK_EVENT(buffer, "+CIEV:"); 806 807 res = sscanf(buffer, "%u,%u%n", &index, &value, &offset); 808 if(res < 2) 809 { 810 return NULL; 811 } 812 813 buffer += offset; 814 815 AT_CHECK_RN(buffer); 816 817 bta_hf_client_handle_ciev(index, value); 818 return buffer; 819 } 820 821 static char *bta_hf_client_parse_bcs(char *buffer) 822 { 823 AT_CHECK_EVENT(buffer, "+BCS:"); 824 825 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bcs); 826 } 827 828 static char *bta_hf_client_parse_bsir(char *buffer) 829 { 830 AT_CHECK_EVENT(buffer, "+BSIR:"); 831 832 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bsir); 833 } 834 835 static char *bta_hf_client_parse_cmeerror(char *buffer) 836 { 837 AT_CHECK_EVENT(buffer, "+CME ERROR:"); 838 839 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_cmeerror); 840 } 841 842 static char *bta_hf_client_parse_vgm(char *buffer) 843 { 844 AT_CHECK_EVENT(buffer, "+VGM:"); 845 846 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgm); 847 } 848 849 static char *bta_hf_client_parse_vgme(char *buffer) 850 { 851 AT_CHECK_EVENT(buffer, "+VGM="); 852 853 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgm); 854 } 855 856 static char *bta_hf_client_parse_vgs(char *buffer) 857 { 858 AT_CHECK_EVENT(buffer, "+VGS:"); 859 860 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgs); 861 } 862 863 static char *bta_hf_client_parse_vgse(char *buffer) 864 { 865 AT_CHECK_EVENT(buffer, "+VGS="); 866 867 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgs); 868 } 869 870 static char *bta_hf_client_parse_bvra(char *buffer) 871 { 872 AT_CHECK_EVENT(buffer, "+BVRA:"); 873 874 return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bvra); 875 } 876 877 static char *bta_hf_client_parse_clip(char *buffer) 878 { 879 /* spec forces 32 chars, plus \0 here */ 880 char number[33]; 881 UINT32 type = 0; 882 int res; 883 int offset; 884 885 AT_CHECK_EVENT(buffer, "+CLIP:"); 886 887 /* there might be something more after %lu but HFP doesn't care */ 888 res = sscanf(buffer, "\"%32[^\"]\",%u%n", number, &type, &offset); 889 if(res < 2) 890 { 891 return NULL; 892 } 893 894 buffer += offset; 895 896 AT_SKIP_REST(buffer); 897 898 AT_CHECK_RN(buffer); 899 900 bta_hf_client_handle_clip(number, type); 901 return buffer; 902 } 903 904 /* in HFP context there is no difference between ccwa and clip */ 905 static char *bta_hf_client_parse_ccwa(char *buffer) 906 { 907 /* ac to spec 32 chars max, plus \0 here */ 908 char number[33]; 909 UINT32 type = 0; 910 int res ; 911 int offset; 912 913 AT_CHECK_EVENT(buffer, "+CCWA:"); 914 915 /* there might be something more after %lu but HFP doesn't care */ 916 res = sscanf(buffer, "\"%32[^\"]\",%u%n", number, &type, &offset); 917 if(res < 2) 918 { 919 return NULL; 920 } 921 922 buffer += offset; 923 924 AT_SKIP_REST(buffer); 925 926 AT_CHECK_RN(buffer); 927 928 bta_hf_client_handle_ccwa(number, type); 929 return buffer; 930 } 931 932 static char *bta_hf_client_parse_cops(char *buffer) 933 { 934 UINT8 mode; 935 /* spec forces 16 chars max, plus \0 here */ 936 char opstr[17]; 937 int res; 938 int offset; 939 940 AT_CHECK_EVENT(buffer, "+COPS:"); 941 942 /* TODO: Not sure if operator string actually can contain escaped " char inside */ 943 res = sscanf(buffer, "%hhi,0,\"%16[^\"]\"%n", &mode, opstr, &offset); 944 if(res < 2) 945 { 946 return NULL; 947 } 948 949 buffer += offset; 950 951 AT_SKIP_REST(buffer); 952 953 AT_CHECK_RN(buffer); 954 955 bta_hf_client_handle_cops(opstr, mode); 956 return buffer; 957 } 958 959 static char *bta_hf_client_parse_binp(char *buffer) 960 { 961 /* HFP only supports phone number as BINP data */ 962 /* phone number is 32 chars plus one for \0*/ 963 char numstr[33]; 964 int res; 965 int offset; 966 967 AT_CHECK_EVENT(buffer, "+BINP:"); 968 969 res = sscanf(buffer, "\"%32[^\"]\"\r\n%n", numstr, &offset); 970 if(res < 1) 971 { 972 return NULL; 973 } 974 975 buffer += offset; 976 977 /* some phones might sent type as well, just skip it */ 978 AT_SKIP_REST(buffer); 979 980 AT_CHECK_RN(buffer); 981 982 bta_hf_client_handle_binp(numstr); 983 return buffer; 984 } 985 986 static char *bta_hf_client_parse_clcc(char *buffer) 987 { 988 UINT16 idx, dir, status, mode, mpty; 989 char numstr[33]; /* spec forces 32 chars, plus one for \0*/ 990 UINT16 type; 991 int res; 992 int offset; 993 994 AT_CHECK_EVENT(buffer, "+CLCC:"); 995 996 res = sscanf(buffer, "%hu,%hu,%hu,%hu,%hu%n", 997 &idx, &dir, &status, &mode, &mpty, &offset); 998 if (res < 5) 999 { 1000 return NULL; 1001 } 1002 1003 buffer += offset; 1004 1005 /* check optional part */ 1006 if (*buffer == ',') 1007 { 1008 int res2; 1009 1010 res2 = sscanf(buffer, ",\"%32[^\"]\",%hu%n", numstr, &type, &offset); 1011 if (res2 < 0) 1012 { 1013 return NULL; 1014 } 1015 1016 if (res2 == 0) 1017 { 1018 res2 = sscanf(buffer, ",\"\",%hu%n", &type, &offset); 1019 if (res < 0) 1020 { 1021 return NULL; 1022 } 1023 1024 /* numstr is not matched in second attempt, correct this */ 1025 res2++; 1026 numstr[0] = '\0'; 1027 } 1028 1029 if (res2 < 2) 1030 { 1031 return NULL; 1032 } 1033 1034 res += res2; 1035 buffer += offset; 1036 } 1037 1038 AT_CHECK_RN(buffer); 1039 1040 if(res > 6) 1041 { 1042 /* we also have last two optional parameters */ 1043 bta_hf_client_handle_clcc(idx, dir, status, mode, mpty, numstr, type); 1044 } 1045 else 1046 { 1047 /* we didn't get the last two parameters */ 1048 bta_hf_client_handle_clcc(idx, dir, status, mode, mpty, NULL, 0); 1049 } 1050 1051 return buffer; 1052 } 1053 1054 static char *bta_hf_client_parse_cnum(char *buffer) 1055 { 1056 char numstr[33]; /* spec forces 32 chars, plus one for \0*/ 1057 UINT16 type; 1058 UINT16 service = 0; /* 0 in case this optional parameter is not being sent */ 1059 int res; 1060 int offset; 1061 1062 AT_CHECK_EVENT(buffer, "+CNUM:"); 1063 1064 res = sscanf(buffer, ",\"%32[^\"]\",%hu,,%hu%n", numstr, &type, &service, &offset); 1065 if(res < 0) 1066 { 1067 return NULL; 1068 } 1069 1070 if (res == 0) 1071 { 1072 res = sscanf(buffer, ",\"\",%hu,,%hu%n", &type, &service, &offset); 1073 if (res < 0) 1074 { 1075 return NULL; 1076 } 1077 1078 /* numstr is not matched in second attempt, correct this */ 1079 res++; 1080 numstr[0] = '\0'; 1081 } 1082 1083 if (res < 3) 1084 { 1085 return NULL; 1086 } 1087 1088 buffer += offset; 1089 1090 AT_CHECK_RN(buffer); 1091 1092 /* service is optional */ 1093 if(res == 2) 1094 { 1095 bta_hf_client_handle_cnum(numstr, type, service); 1096 return buffer; 1097 } 1098 1099 if (service != 4 && service != 5) 1100 { 1101 return NULL; 1102 } 1103 1104 bta_hf_client_handle_cnum(numstr, type, service); 1105 return buffer; 1106 } 1107 1108 static char *bta_hf_client_parse_btrh(char *buffer) 1109 { 1110 UINT16 code = 0; 1111 int res; 1112 int offset; 1113 1114 AT_CHECK_EVENT(buffer, "+BTRH:"); 1115 1116 res = sscanf(buffer, "%hu%n", &code, &offset); 1117 if(res < 1) 1118 { 1119 return NULL; 1120 } 1121 1122 buffer += offset; 1123 1124 AT_CHECK_RN(buffer); 1125 1126 bta_hf_client_handle_btrh(code); 1127 return buffer; 1128 } 1129 1130 static char *bta_hf_client_parse_busy(char *buffer) 1131 { 1132 AT_CHECK_EVENT(buffer, "BUSY"); 1133 AT_CHECK_RN(buffer); 1134 1135 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_BUSY, 0); 1136 1137 return buffer; 1138 } 1139 1140 static char *bta_hf_client_parse_delayed(char *buffer) 1141 { 1142 AT_CHECK_EVENT(buffer, "DELAYED"); 1143 AT_CHECK_RN(buffer); 1144 1145 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_DELAY, 0); 1146 1147 return buffer; 1148 } 1149 1150 static char *bta_hf_client_parse_no_carrier(char *buffer) 1151 { 1152 AT_CHECK_EVENT(buffer, "NO CARRIER"); 1153 AT_CHECK_RN(buffer); 1154 1155 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_NO_CARRIER, 0); 1156 1157 return buffer; 1158 } 1159 1160 static char *bta_hf_client_parse_no_answer(char *buffer) 1161 { 1162 AT_CHECK_EVENT(buffer, "NO ANSWER"); 1163 AT_CHECK_RN(buffer); 1164 1165 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_NO_ANSWER, 0); 1166 1167 return buffer; 1168 } 1169 1170 static char *bta_hf_client_parse_blacklisted(char *buffer) 1171 { 1172 AT_CHECK_EVENT(buffer, "BLACKLISTED"); 1173 AT_CHECK_RN(buffer); 1174 1175 bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_BLACKLISTED, 0); 1176 1177 return buffer; 1178 } 1179 1180 static char *bta_hf_client_skip_unknown(char *buffer) 1181 { 1182 char *start; 1183 char *tmp; 1184 1185 tmp = strstr(buffer, "\r\n"); 1186 if (tmp == NULL) 1187 { 1188 return NULL; 1189 } 1190 1191 buffer += 2; 1192 start = buffer; 1193 1194 tmp = strstr(buffer, "\r\n"); 1195 if (tmp == NULL) 1196 { 1197 return NULL; 1198 } 1199 1200 buffer = tmp + 2; 1201 1202 APPL_TRACE_DEBUG("%s %.*s", __FUNCTION__, buffer - start - 2, start); 1203 1204 return buffer; 1205 } 1206 1207 1208 /****************************************************************************** 1209 ** SUPPORTED EVENT MESSAGES 1210 *******************************************************************************/ 1211 1212 /* returned values are as follow: 1213 * != NULL && != buf : match and parsed ok 1214 * == NULL : match but parse failed 1215 * != NULL && == buf : no match 1216 */ 1217 typedef char* (*tBTA_HF_CLIENT_PARSER_CALLBACK)(char*); 1218 1219 static const tBTA_HF_CLIENT_PARSER_CALLBACK bta_hf_client_parser_cb[] = 1220 { 1221 bta_hf_client_parse_ok, 1222 bta_hf_client_parse_error, 1223 bta_hf_client_parse_ring, 1224 bta_hf_client_parse_brsf, 1225 bta_hf_client_parse_cind, 1226 bta_hf_client_parse_ciev, 1227 bta_hf_client_parse_chld, 1228 bta_hf_client_parse_bcs, 1229 bta_hf_client_parse_bsir, 1230 bta_hf_client_parse_cmeerror, 1231 bta_hf_client_parse_vgm, 1232 bta_hf_client_parse_vgme, 1233 bta_hf_client_parse_vgs, 1234 bta_hf_client_parse_vgse, 1235 bta_hf_client_parse_bvra, 1236 bta_hf_client_parse_clip, 1237 bta_hf_client_parse_ccwa, 1238 bta_hf_client_parse_cops, 1239 bta_hf_client_parse_binp, 1240 bta_hf_client_parse_clcc, 1241 bta_hf_client_parse_cnum, 1242 bta_hf_client_parse_btrh, 1243 bta_hf_client_parse_busy, 1244 bta_hf_client_parse_delayed, 1245 bta_hf_client_parse_no_carrier, 1246 bta_hf_client_parse_no_answer, 1247 bta_hf_client_parse_blacklisted, 1248 bta_hf_client_skip_unknown 1249 }; 1250 1251 /* calculate supported event list length */ 1252 static const UINT16 bta_hf_client_psraser_cb_count = 1253 sizeof(bta_hf_client_parser_cb) / sizeof(bta_hf_client_parser_cb[0]); 1254 1255 #ifdef BTA_HF_CLIENT_AT_DUMP 1256 static void bta_hf_client_dump_at(void) 1257 { 1258 char dump[(4 * BTA_HF_CLIENT_AT_PARSER_MAX_LEN) + 1]; 1259 char *p1, *p2; 1260 1261 p1 = bta_hf_client_cb.scb.at_cb.buf; 1262 p2 = dump; 1263 1264 while (*p1 != '\0') 1265 { 1266 if (*p1 == '\r') 1267 { 1268 strlcpy(p2, "<cr>", 4); 1269 p2 += 4; 1270 } 1271 else if (*p1 == '\n') 1272 { 1273 strlcpy(p2, "<lf>", 4); 1274 p2 += 4; 1275 } 1276 else 1277 { 1278 *p2 = *p1; 1279 p2++; 1280 } 1281 p1++; 1282 } 1283 1284 *p2 = '\0'; 1285 1286 APPL_TRACE_DEBUG("%s %s", __FUNCTION__, dump); 1287 } 1288 #endif 1289 1290 static void bta_hf_client_at_parse_start(void) 1291 { 1292 char *buf = bta_hf_client_cb.scb.at_cb.buf; 1293 1294 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1295 1296 #ifdef BTA_HF_CLIENT_AT_DUMP 1297 bta_hf_client_dump_at(); 1298 #endif 1299 1300 while(*buf != '\0') 1301 { 1302 int i; 1303 char *tmp = NULL; 1304 1305 for(i = 0; i < bta_hf_client_psraser_cb_count; i++) 1306 { 1307 tmp = bta_hf_client_parser_cb[i](buf); 1308 if (tmp == NULL) 1309 { 1310 APPL_TRACE_ERROR("HFPCient: AT event/reply parsing failed, skipping"); 1311 tmp = bta_hf_client_skip_unknown(buf); 1312 break; 1313 } 1314 1315 /* matched or unknown skipped, if unknown failed tmp is NULL so 1316 this is also handled */ 1317 if (tmp != buf) 1318 { 1319 buf = tmp; 1320 break; 1321 } 1322 } 1323 1324 /* could not skip unknown (received garbage?)... disconnect */ 1325 if (tmp == NULL) 1326 { 1327 APPL_TRACE_ERROR("HFPCient: could not skip unknown AT event, disconnecting"); 1328 bta_hf_client_at_reset(); 1329 bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); 1330 return; 1331 } 1332 1333 buf = tmp; 1334 } 1335 } 1336 1337 static BOOLEAN bta_hf_client_check_at_complete(void) 1338 { 1339 BOOLEAN ret = FALSE; 1340 tBTA_HF_CLIENT_AT_CB *at_cb = &bta_hf_client_cb.scb.at_cb; 1341 1342 if (at_cb->offset >= BTA_HF_CLIENT_AT_EVENT_MIN_LEN) 1343 { 1344 if (at_cb->buf[at_cb->offset - 2] == '\r' && at_cb->buf[at_cb->offset - 1] == '\n') 1345 { 1346 ret = TRUE; 1347 } 1348 } 1349 1350 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, ret); 1351 1352 return ret; 1353 } 1354 1355 static void bta_hf_client_at_clear_buf(void) 1356 { 1357 memset(bta_hf_client_cb.scb.at_cb.buf, 0, sizeof(bta_hf_client_cb.scb.at_cb.buf)); 1358 bta_hf_client_cb.scb.at_cb.offset = 0; 1359 } 1360 1361 /****************************************************************************** 1362 ** 1363 ** MAIN PARSING FUNCTION 1364 ** 1365 ** 1366 *******************************************************************************/ 1367 void bta_hf_client_at_parse(char *buf, unsigned int len) 1368 { 1369 APPL_TRACE_DEBUG("%s offset: %u len: %u", __FUNCTION__, bta_hf_client_cb.scb.at_cb.offset, len); 1370 1371 if (len + bta_hf_client_cb.scb.at_cb.offset > BTA_HF_CLIENT_AT_PARSER_MAX_LEN) 1372 { 1373 char tmp_buff[BTA_HF_CLIENT_AT_PARSER_MAX_LEN]; 1374 unsigned int tmp = bta_hf_client_cb.scb.at_cb.offset; 1375 unsigned int space_left = BTA_HF_CLIENT_AT_PARSER_MAX_LEN - bta_hf_client_cb.scb.at_cb.offset; 1376 1377 APPL_TRACE_DEBUG("%s overrun, trying to recover", __FUNCTION__); 1378 1379 /* fill up parser buffer */ 1380 memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, space_left); 1381 len -= space_left; 1382 buf += space_left; 1383 bta_hf_client_cb.scb.at_cb.offset += space_left; 1384 1385 /* find end of last complete command before proceeding */ 1386 while(bta_hf_client_check_at_complete() == FALSE) 1387 { 1388 if (bta_hf_client_cb.scb.at_cb.offset == 0) { 1389 APPL_TRACE_ERROR("HFPClient: AT parser buffer overrun, disconnecting"); 1390 1391 bta_hf_client_at_reset(); 1392 bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); 1393 return; 1394 } 1395 1396 bta_hf_client_cb.scb.at_cb.offset--; 1397 } 1398 1399 /* cut buffer to complete AT event and keep cut data */ 1400 tmp += space_left - bta_hf_client_cb.scb.at_cb.offset; 1401 memcpy(tmp_buff, bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, tmp); 1402 bta_hf_client_cb.scb.at_cb.buf[bta_hf_client_cb.scb.at_cb.offset] = '\0'; 1403 1404 /* parse */ 1405 bta_hf_client_at_parse_start(); 1406 bta_hf_client_at_clear_buf(); 1407 1408 /* recover cut data */ 1409 memcpy(bta_hf_client_cb.scb.at_cb.buf, tmp_buff, tmp); 1410 bta_hf_client_cb.scb.at_cb.offset += tmp; 1411 } 1412 1413 memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, len); 1414 bta_hf_client_cb.scb.at_cb.offset += len; 1415 1416 /* If last event is complete, parsing can be started */ 1417 if (bta_hf_client_check_at_complete() == TRUE) 1418 { 1419 bta_hf_client_at_parse_start(); 1420 bta_hf_client_at_clear_buf(); 1421 } 1422 } 1423 1424 void bta_hf_client_send_at_brsf(void) 1425 { 1426 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1427 int at_len; 1428 1429 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1430 1431 at_len = snprintf(buf, sizeof(buf), "AT+BRSF=%u\r", bta_hf_client_cb.scb.features); 1432 1433 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BRSF , buf, at_len); 1434 } 1435 1436 void bta_hf_client_send_at_bac(void) 1437 { 1438 char *buf; 1439 1440 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1441 1442 if (bta_hf_client_cb.msbc_enabled) 1443 { 1444 buf = "AT+BAC=1,2\r"; 1445 } 1446 else 1447 { 1448 buf = "AT+BAC=1\r"; 1449 } 1450 1451 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BAC, buf, strlen(buf)); 1452 } 1453 1454 void bta_hf_client_send_at_bcs(UINT32 codec) 1455 { 1456 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1457 int at_len; 1458 1459 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1460 1461 at_len = snprintf(buf, sizeof(buf), "AT+BCS=%u\r", codec); 1462 1463 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BCS, buf, at_len); 1464 } 1465 1466 void bta_hf_client_send_at_cind(BOOLEAN status) 1467 { 1468 char *buf; 1469 tBTA_HF_CLIENT_AT_CMD cmd; 1470 1471 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1472 1473 if (status) 1474 { 1475 buf = "AT+CIND?\r"; 1476 cmd = BTA_HF_CLIENT_AT_CIND_STATUS; 1477 } 1478 else 1479 { 1480 buf = "AT+CIND=?\r"; 1481 cmd = BTA_HF_CLIENT_AT_CIND; 1482 } 1483 1484 bta_hf_client_send_at(cmd, buf, strlen(buf)); 1485 } 1486 1487 void bta_hf_client_send_at_cmer(BOOLEAN activate) 1488 { 1489 char *buf; 1490 1491 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1492 1493 if (activate) 1494 buf = "AT+CMER=3,0,0,1\r"; 1495 else 1496 buf = "AT+CMER=3,0,0,0\r"; 1497 1498 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CMER, buf, strlen(buf)); 1499 } 1500 1501 void bta_hf_client_send_at_chld(char cmd, UINT32 idx) 1502 { 1503 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1504 int at_len; 1505 1506 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1507 1508 if (idx > 0) 1509 at_len = snprintf(buf, sizeof(buf), "AT+CHLD=%c%u\r", cmd, idx); 1510 else 1511 at_len = snprintf(buf, sizeof(buf), "AT+CHLD=%c\r", cmd); 1512 1513 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CHLD, buf, at_len); 1514 } 1515 1516 void bta_hf_client_send_at_clip(BOOLEAN activate) 1517 { 1518 char *buf; 1519 1520 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1521 1522 if (activate) 1523 buf = "AT+CLIP=1\r"; 1524 else 1525 buf = "AT+CLIP=0\r"; 1526 1527 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CLIP, buf, strlen(buf)); 1528 } 1529 1530 void bta_hf_client_send_at_ccwa(BOOLEAN activate) 1531 { 1532 char *buf; 1533 1534 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1535 1536 if (activate) 1537 buf = "AT+CCWA=1\r"; 1538 else 1539 buf = "AT+CCWA=0\r"; 1540 1541 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CCWA, buf, strlen(buf)); 1542 } 1543 1544 1545 void bta_hf_client_send_at_cmee(BOOLEAN activate) 1546 { 1547 char *buf; 1548 1549 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1550 1551 if (activate) 1552 buf = "AT+CMEE=1\r"; 1553 else 1554 buf = "AT+CMEE=0\r"; 1555 1556 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CMEE, buf, strlen(buf)); 1557 } 1558 1559 void bta_hf_client_send_at_cops(BOOLEAN query) 1560 { 1561 char *buf; 1562 1563 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1564 1565 if (!service_availability) 1566 { 1567 APPL_TRACE_DEBUG("Skip AT+COPS no service"); 1568 return; 1569 } 1570 if (query) 1571 buf = "AT+COPS?\r"; 1572 else 1573 buf = "AT+COPS=3,0\r"; 1574 1575 bta_hf_client_send_at(BTA_HF_CLIENT_AT_COPS, buf, strlen(buf)); 1576 } 1577 1578 void bta_hf_client_send_at_clcc(void) 1579 { 1580 char *buf; 1581 1582 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1583 1584 buf = "AT+CLCC\r"; 1585 1586 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CLCC, buf, strlen(buf)); 1587 } 1588 1589 void bta_hf_client_send_at_bvra(BOOLEAN enable) 1590 { 1591 char *buf; 1592 1593 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1594 1595 if (enable) 1596 buf = "AT+BVRA=1\r"; 1597 else 1598 buf = "AT+BVRA=0\r"; 1599 1600 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BVRA, buf, strlen(buf)); 1601 } 1602 1603 void bta_hf_client_send_at_vgs(UINT32 volume) 1604 { 1605 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1606 int at_len; 1607 1608 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1609 1610 at_len = snprintf(buf, sizeof(buf), "AT+VGS=%u\r", volume); 1611 1612 bta_hf_client_send_at(BTA_HF_CLIENT_AT_VGS, buf, at_len); 1613 } 1614 1615 void bta_hf_client_send_at_vgm(UINT32 volume) 1616 { 1617 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1618 int at_len; 1619 1620 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1621 1622 at_len = snprintf(buf, sizeof(buf), "AT+VGM=%u\r", volume); 1623 1624 bta_hf_client_send_at(BTA_HF_CLIENT_AT_VGM, buf, at_len); 1625 } 1626 1627 void bta_hf_client_send_at_atd(char *number, UINT32 memory) 1628 { 1629 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1630 int at_len; 1631 1632 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1633 1634 if (number[0] != '\0') 1635 { 1636 at_len = snprintf(buf, sizeof(buf), "ATD%s;\r", number); 1637 } 1638 else 1639 { 1640 at_len = snprintf(buf, sizeof(buf), "ATD>%u;\r", memory); 1641 } 1642 1643 bta_hf_client_send_at(BTA_HF_CLIENT_AT_ATD, buf, at_len); 1644 } 1645 1646 void bta_hf_client_send_at_bldn(void) 1647 { 1648 char *buf; 1649 1650 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1651 1652 buf = "AT+BLDN\r"; 1653 1654 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BLDN, buf, strlen(buf)); 1655 } 1656 1657 void bta_hf_client_send_at_ata(void) 1658 { 1659 char *buf; 1660 1661 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1662 1663 buf = "ATA\r"; 1664 1665 bta_hf_client_send_at(BTA_HF_CLIENT_AT_ATA, buf, strlen(buf)); 1666 } 1667 1668 void bta_hf_client_send_at_chup(void) 1669 { 1670 char *buf; 1671 1672 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1673 1674 buf = "AT+CHUP\r"; 1675 1676 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CHUP, buf, strlen(buf)); 1677 } 1678 1679 void bta_hf_client_send_at_btrh(BOOLEAN query, UINT32 val) 1680 { 1681 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1682 int at_len; 1683 1684 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1685 1686 if (query == TRUE) 1687 { 1688 at_len = snprintf(buf, sizeof(buf), "AT+BTRH?\r"); 1689 } 1690 else 1691 { 1692 at_len = snprintf(buf, sizeof(buf), "AT+BTRH=%u\r", val); 1693 } 1694 1695 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BTRH, buf, at_len); 1696 } 1697 1698 void bta_hf_client_send_at_vts(char code) 1699 { 1700 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1701 int at_len; 1702 1703 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1704 1705 at_len = snprintf(buf, sizeof(buf), "AT+VTS=%c\r", code); 1706 1707 bta_hf_client_send_at(BTA_HF_CLIENT_AT_VTS, buf, at_len); 1708 } 1709 1710 void bta_hf_client_send_at_bcc(void) 1711 { 1712 char *buf; 1713 1714 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1715 1716 buf = "AT+BCC\r"; 1717 1718 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BCC, buf, strlen(buf)); 1719 } 1720 1721 void bta_hf_client_send_at_cnum(void) 1722 { 1723 char *buf; 1724 1725 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1726 1727 if (!service_availability) 1728 { 1729 APPL_TRACE_DEBUG("Skip AT+CNUM no Service"); 1730 return; 1731 } 1732 buf = "AT+CNUM\r"; 1733 1734 bta_hf_client_send_at(BTA_HF_CLIENT_AT_CNUM, buf, strlen(buf)); 1735 } 1736 1737 void bta_hf_client_send_at_nrec(void) 1738 { 1739 char *buf; 1740 1741 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1742 1743 if (!(bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_ECNR)) 1744 { 1745 APPL_TRACE_DEBUG("Remote does not support NREC."); 1746 return; 1747 } 1748 1749 buf = "AT+NREC=0\r"; 1750 1751 bta_hf_client_send_at(BTA_HF_CLIENT_AT_NREC, buf, strlen(buf)); 1752 } 1753 1754 void bta_hf_client_send_at_binp(UINT32 action) 1755 { 1756 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1757 int at_len; 1758 1759 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1760 1761 at_len = snprintf(buf, sizeof(buf), "AT+BINP=%u\r", action); 1762 1763 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BINP, buf, at_len); 1764 } 1765 1766 void bta_hf_client_send_at_bia(void) 1767 { 1768 char buf[BTA_HF_CLIENT_AT_MAX_LEN]; 1769 int at_len; 1770 int i; 1771 1772 APPL_TRACE_DEBUG("%s", __FUNCTION__); 1773 if (bta_hf_client_cb.scb.peer_version < HFP_VERSION_1_6) 1774 { 1775 APPL_TRACE_DEBUG("Remote does not Support AT+BIA"); 1776 return; 1777 } 1778 1779 at_len = snprintf(buf, sizeof(buf), "AT+BIA="); 1780 1781 for(i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) 1782 { 1783 int sup = bta_hf_client_cb.scb.at_cb.indicator_lookup[i] == -1 ? 0 : 1; 1784 1785 at_len += snprintf(buf + at_len, sizeof(buf) - at_len, "%u,", sup); 1786 } 1787 1788 buf[at_len - 1] = '\r'; 1789 1790 bta_hf_client_send_at(BTA_HF_CLIENT_AT_BIA, buf, at_len); 1791 } 1792 1793 void bta_hf_client_at_init(void) 1794 { 1795 memset(&bta_hf_client_cb.scb.at_cb, 0, sizeof(tBTA_HF_CLIENT_AT_CB)); 1796 bta_hf_client_at_reset(); 1797 } 1798 1799 void bta_hf_client_at_reset(void) 1800 { 1801 int i; 1802 1803 bta_hf_client_stop_at_resp_timer(); 1804 bta_hf_client_stop_at_hold_timer(); 1805 1806 bta_hf_client_clear_queued_at(); 1807 1808 bta_hf_client_at_clear_buf(); 1809 1810 for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) 1811 { 1812 bta_hf_client_cb.scb.at_cb.indicator_lookup[i] = -1; 1813 } 1814 1815 bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; 1816 } 1817