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