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