Home | History | Annotate | Download | only in hf_client
      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