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