Home | History | Annotate | Download | only in ag
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2004-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains functions for processing AT commands and results.
     22  *
     23  ******************************************************************************/
     24 #include <ctype.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 
     28 #include "bt_target.h"
     29 #include "bt_types.h"
     30 #include "bta_ag_api.h"
     31 #include "bta_ag_at.h"
     32 #include "bta_ag_int.h"
     33 #include "bta_api.h"
     34 #include "bta_sys.h"
     35 #include "gki.h"
     36 #include "port_api.h"
     37 #include "utl.h"
     38 
     39 
     40 /*****************************************************************************
     41 **  Constants
     42 *****************************************************************************/
     43 
     44 /* ring timeout */
     45 #define BTA_AG_RING_TOUT        5000
     46 
     47 #define BTA_AG_CMD_MAX_VAL      32767  /* Maximum value is signed 16-bit value */
     48 
     49 /* Invalid Chld command */
     50 #define BTA_AG_INVALID_CHLD        255
     51 
     52 /* clip type constants */
     53 #define BTA_AG_CLIP_TYPE_MIN        128
     54 #define BTA_AG_CLIP_TYPE_MAX        175
     55 #define BTA_AG_CLIP_TYPE_DEFAULT    129
     56 #define BTA_AG_CLIP_TYPE_VOIP       255
     57 
     58 #if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
     59 #define BTA_AG_AT_MULTI_LEN            2
     60 #define AT_SET_RES_CB(res_cb, c, p, i) {res_cb.code = c; res_cb.p_arg = p; res_cb.int_arg = i;}
     61 
     62 /* type for AT result code block */
     63 typedef struct
     64 {
     65     UINT8 code;
     66     char *p_arg;
     67     INT16 int_arg;
     68 } tBTA_AG_RESULT_CB;
     69 
     70 /* type for multiple AT result codes block */
     71 typedef struct
     72 {
     73     UINT8 num_result;
     74     tBTA_AG_RESULT_CB res_cb[BTA_AG_AT_MULTI_LEN];
     75 } tBTA_AG_MULTI_RESULT_CB;
     76 #endif
     77 
     78 /* enumeration of HSP AT commands matches HSP command interpreter table */
     79 enum
     80 {
     81     BTA_AG_HS_CMD_CKPD,
     82     BTA_AG_HS_CMD_VGS,
     83     BTA_AG_HS_CMD_VGM
     84 };
     85 
     86 /* enumeration of HFP AT commands matches HFP command interpreter table */
     87 enum
     88 {
     89     BTA_AG_HF_CMD_A,
     90     BTA_AG_HF_CMD_D,
     91     BTA_AG_HF_CMD_VGS,
     92     BTA_AG_HF_CMD_VGM,
     93     BTA_AG_HF_CMD_CCWA,
     94     BTA_AG_HF_CMD_CHLD,
     95     BTA_AG_HF_CMD_CHUP,
     96     BTA_AG_HF_CMD_CIND,
     97     BTA_AG_HF_CMD_CLIP,
     98     BTA_AG_HF_CMD_CMER,
     99     BTA_AG_HF_CMD_VTS,
    100     BTA_AG_HF_CMD_BINP,
    101     BTA_AG_HF_CMD_BLDN,
    102     BTA_AG_HF_CMD_BVRA,
    103     BTA_AG_HF_CMD_BRSF,
    104     BTA_AG_HF_CMD_NREC,
    105     BTA_AG_HF_CMD_CNUM,
    106     BTA_AG_HF_CMD_BTRH,
    107     BTA_AG_HF_CMD_CLCC,
    108     BTA_AG_HF_CMD_COPS,
    109     BTA_AG_HF_CMD_CMEE,
    110     BTA_AG_HF_CMD_BIA,
    111     BTA_AG_HF_CMD_CBC,
    112     BTA_AG_HF_CMD_BCC,
    113     BTA_AG_HF_CMD_BCS,
    114     BTA_AG_HF_CMD_BAC
    115 };
    116 
    117 /* AT command interpreter table for HSP */
    118 const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] =
    119 {
    120     {"+CKPD",   BTA_AG_AT_SET,                      BTA_AG_AT_INT, 200, 200},
    121     {"+VGS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
    122     {"+VGM",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
    123     {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
    124 };
    125 
    126 /* AT command interpreter table for HFP */
    127 const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] =
    128 {
    129     {"A",       BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
    130     {"D",       (BTA_AG_AT_NONE | BTA_AG_AT_FREE),  BTA_AG_AT_STR,   0,   0},
    131     {"+VGS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
    132     {"+VGM",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
    133     {"+CCWA",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
    134     /* Consider CHLD as str to take care of indexes for ECC */
    135     {"+CHLD",   (BTA_AG_AT_SET | BTA_AG_AT_TEST),   BTA_AG_AT_STR,   0,   4},
    136     {"+CHUP",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
    137     {"+CIND",   (BTA_AG_AT_READ | BTA_AG_AT_TEST),  BTA_AG_AT_STR,   0,   0},
    138     {"+CLIP",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
    139     {"+CMER",   BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
    140     {"+VTS",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
    141     {"+BINP",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   1,   1},
    142     {"+BLDN",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
    143     {"+BVRA",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
    144     {"+BRSF",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
    145     {"+NREC",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   0},
    146     {"+CNUM",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
    147     {"+BTRH",   (BTA_AG_AT_READ | BTA_AG_AT_SET),   BTA_AG_AT_INT,   0,   2},
    148     {"+CLCC",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
    149     {"+COPS",   (BTA_AG_AT_READ | BTA_AG_AT_SET),   BTA_AG_AT_STR,   0,   0},
    150     {"+CMEE",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
    151     {"+BIA",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   20},
    152     {"+CBC",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   100},
    153     {"+BCC",    BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
    154     {"+BCS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
    155     {"+BAC",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
    156     {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
    157 };
    158 
    159 /* AT result code table element */
    160 typedef struct
    161 {
    162     const char  *p_res;         /* AT result string */
    163     UINT8       fmt;            /* whether argument is int or string */
    164 } tBTA_AG_RESULT;
    165 
    166 /* AT result code argument types */
    167 enum
    168 {
    169     BTA_AG_RES_FMT_NONE,       /* no argument */
    170     BTA_AG_RES_FMT_INT,        /* integer argument */
    171     BTA_AG_RES_FMT_STR         /* string argument */
    172 };
    173 
    174 /* enumeration of AT result codes, matches constant table */
    175 enum
    176 {
    177     BTA_AG_RES_OK,
    178     BTA_AG_RES_ERROR,
    179     BTA_AG_RES_RING,
    180     BTA_AG_RES_VGS,
    181     BTA_AG_RES_VGM,
    182     BTA_AG_RES_CCWA,
    183     BTA_AG_RES_CHLD,
    184     BTA_AG_RES_CIND,
    185     BTA_AG_RES_CLIP,
    186     BTA_AG_RES_CIEV,
    187     BTA_AG_RES_BINP,
    188     BTA_AG_RES_BVRA,
    189     BTA_AG_RES_BRSF,
    190     BTA_AG_RES_BSIR,
    191     BTA_AG_RES_CNUM,
    192     BTA_AG_RES_BTRH,
    193     BTA_AG_RES_CLCC,
    194     BTA_AG_RES_COPS,
    195     BTA_AG_RES_CMEE,
    196     BTA_AG_RES_BCS,
    197     BTA_AG_RES_UNAT
    198 };
    199 
    200 #if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
    201 #define COLON_IDX_4_VGSVGM    4
    202 #endif
    203 /* AT result code constant table  (Indexed by result code) */
    204 const tBTA_AG_RESULT bta_ag_result_tbl[] =
    205 {
    206     {"OK",      BTA_AG_RES_FMT_NONE},
    207     {"ERROR",   BTA_AG_RES_FMT_NONE},
    208     {"RING",    BTA_AG_RES_FMT_NONE},
    209     {"+VGS: ",  BTA_AG_RES_FMT_INT},
    210     {"+VGM: ",  BTA_AG_RES_FMT_INT},
    211     {"+CCWA: ", BTA_AG_RES_FMT_STR},
    212     {"+CHLD: ", BTA_AG_RES_FMT_STR},
    213     {"+CIND: ", BTA_AG_RES_FMT_STR},
    214     {"+CLIP: ", BTA_AG_RES_FMT_STR},
    215     {"+CIEV: ", BTA_AG_RES_FMT_STR},
    216     {"+BINP: ", BTA_AG_RES_FMT_STR},
    217     {"+BVRA: ", BTA_AG_RES_FMT_INT},
    218     {"+BRSF: ", BTA_AG_RES_FMT_INT},
    219     {"+BSIR: ", BTA_AG_RES_FMT_INT},
    220     {"+CNUM: ", BTA_AG_RES_FMT_STR},
    221     {"+BTRH: ", BTA_AG_RES_FMT_INT},
    222     {"+CLCC: ", BTA_AG_RES_FMT_STR},
    223     {"+COPS: ", BTA_AG_RES_FMT_STR},
    224     {"+CME ERROR: ", BTA_AG_RES_FMT_INT},
    225     {"+BCS: ",  BTA_AG_RES_FMT_INT},
    226     {"",        BTA_AG_RES_FMT_STR}
    227 };
    228 
    229 const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX] =
    230 {
    231     bta_ag_hsp_cmd,
    232     bta_ag_hfp_cmd
    233 };
    234 
    235 /* callback event lookup table for HSP */
    236 const tBTA_AG_EVT bta_ag_hsp_cb_evt[] =
    237 {
    238     BTA_AG_AT_CKPD_EVT,     /* BTA_AG_HS_CMD_CKPD */
    239     BTA_AG_SPK_EVT,         /* BTA_AG_HS_CMD_VGS */
    240     BTA_AG_MIC_EVT          /* BTA_AG_HS_CMD_VGM */
    241 };
    242 
    243 /* callback event lookup table for HFP  (Indexed by command) */
    244 const tBTA_AG_EVT bta_ag_hfp_cb_evt[] =
    245 {
    246     BTA_AG_AT_A_EVT,        /* BTA_AG_HF_CMD_A */
    247     BTA_AG_AT_D_EVT,        /* BTA_AG_HF_CMD_D */
    248     BTA_AG_SPK_EVT,         /* BTA_AG_HF_CMD_VGS */
    249     BTA_AG_MIC_EVT,         /* BTA_AG_HF_CMD_VGM */
    250     0,                      /* BTA_AG_HF_CMD_CCWA */
    251     BTA_AG_AT_CHLD_EVT,     /* BTA_AG_HF_CMD_CHLD */
    252     BTA_AG_AT_CHUP_EVT,     /* BTA_AG_HF_CMD_CHUP */
    253     BTA_AG_AT_CIND_EVT,     /* BTA_AG_HF_CMD_CIND */
    254     0,                      /* BTA_AG_HF_CMD_CLIP */
    255     0,                      /* BTA_AG_HF_CMD_CMER */
    256     BTA_AG_AT_VTS_EVT,      /* BTA_AG_HF_CMD_VTS */
    257     BTA_AG_AT_BINP_EVT,     /* BTA_AG_HF_CMD_BINP */
    258     BTA_AG_AT_BLDN_EVT,     /* BTA_AG_HF_CMD_BLDN */
    259     BTA_AG_AT_BVRA_EVT,     /* BTA_AG_HF_CMD_BVRA */
    260     0,                      /* BTA_AG_HF_CMD_BRSF */
    261     BTA_AG_AT_NREC_EVT,     /* BTA_AG_HF_CMD_NREC */
    262     BTA_AG_AT_CNUM_EVT,     /* BTA_AG_HF_CMD_CNUM */
    263     BTA_AG_AT_BTRH_EVT,     /* BTA_AG_HF_CMD_BTRH */
    264     BTA_AG_AT_CLCC_EVT,     /* BTA_AG_HF_CMD_CLCC */
    265     BTA_AG_AT_COPS_EVT,     /* BTA_AG_HF_CMD_COPS */
    266     0,                      /* BTA_AG_HF_CMD_CMEE */
    267     0,                      /* BTA_AG_HF_CMD_BIA */
    268     BTA_AG_AT_CBC_EVT,      /* BTA_AG_HF_CMD_CBC */
    269     0,                      /* BTA_AG_HF_CMD_BCC */
    270     BTA_AG_AT_BCS_EVT,      /* BTA_AG_HF_CMD_BCS */
    271     BTA_AG_AT_BAC_EVT       /* BTA_AG_HF_CMD_BAC */
    272 };
    273 
    274 /* translation of API result code values to internal values */
    275 const UINT8 bta_ag_trans_result[] =
    276 {
    277     BTA_AG_RES_VGS,     /* BTA_AG_SPK_RES */
    278     BTA_AG_RES_VGM,     /* BTA_AG_MIC_RES */
    279     BTA_AG_RES_BSIR,    /* BTA_AG_INBAND_RING_RES */
    280     BTA_AG_RES_CIND,    /* BTA_AG_CIND_RES */
    281     BTA_AG_RES_BINP,    /* BTA_AG_BINP_RES */
    282     BTA_AG_RES_CIEV,    /* BTA_AG_IND_RES */
    283     BTA_AG_RES_BVRA,    /* BTA_AG_BVRA_RES */
    284     BTA_AG_RES_CNUM,    /* BTA_AG_CNUM_RES */
    285     BTA_AG_RES_BTRH,    /* BTA_AG_BTRH_RES */
    286     BTA_AG_RES_CLCC,    /* BTA_AG_CLCC_RES */
    287     BTA_AG_RES_COPS,    /* BTA_AG_COPS_RES */
    288     0,                  /* BTA_AG_IN_CALL_RES */
    289     0,                  /* BTA_AG_IN_CALL_CONN_RES */
    290     BTA_AG_RES_CCWA,    /* BTA_AG_CALL_WAIT_RES */
    291     0,                  /* BTA_AG_OUT_CALL_ORIG_RES */
    292     0,                  /* BTA_AG_OUT_CALL_ALERT_RES */
    293     0,                  /* BTA_AG_OUT_CALL_CONN_RES */
    294     0,                  /* BTA_AG_CALL_CANCEL_RES */
    295     0,                  /* BTA_AG_END_CALL_RES */
    296     0,                  /* BTA_AG_IN_CALL_HELD_RES */
    297     BTA_AG_RES_UNAT     /* BTA_AG_UNAT_RES */
    298 };
    299 
    300 /* callsetup indicator value lookup table */
    301 const UINT8 bta_ag_callsetup_ind_tbl[] =
    302 {
    303     0,                          /* BTA_AG_SPK_RES */
    304     0,                          /* BTA_AG_MIC_RES */
    305     0,                          /* BTA_AG_INBAND_RING_RES */
    306     0,                          /* BTA_AG_CIND_RES */
    307     0,                          /* BTA_AG_BINP_RES */
    308     0,                          /* BTA_AG_IND_RES */
    309     0,                          /* BTA_AG_BVRA_RES */
    310     0,                          /* BTA_AG_CNUM_RES */
    311     0,                          /* BTA_AG_BTRH_RES */
    312     0,                          /* BTA_AG_CLCC_RES */
    313     0,                          /* BTA_AG_COPS_RES */
    314     BTA_AG_CALLSETUP_INCOMING,  /* BTA_AG_IN_CALL_RES */
    315     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_IN_CALL_CONN_RES */
    316     BTA_AG_CALLSETUP_INCOMING,  /* BTA_AG_CALL_WAIT_RES */
    317     BTA_AG_CALLSETUP_OUTGOING,  /* BTA_AG_OUT_CALL_ORIG_RES */
    318     BTA_AG_CALLSETUP_ALERTING,  /* BTA_AG_OUT_CALL_ALERT_RES */
    319     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_OUT_CALL_CONN_RES */
    320     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_CALL_CANCEL_RES */
    321     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_END_CALL_RES */
    322     BTA_AG_CALLSETUP_NONE       /* BTA_AG_IN_CALL_HELD_RES */
    323 };
    324 
    325 /*******************************************************************************
    326 **
    327 ** Function         bta_ag_send_result
    328 **
    329 ** Description      Send an AT result code.
    330 **
    331 **
    332 ** Returns          void
    333 **
    334 *******************************************************************************/
    335 static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg,
    336                                INT16 int_arg)
    337 {
    338     char    buf[BTA_AG_AT_MAX_LEN + 16];
    339     char    *p = buf;
    340     UINT16  len;
    341 
    342 #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
    343     memset(buf, NULL, sizeof(buf));
    344 #endif
    345     /* init with \r\n */
    346     *p++ = '\r';
    347     *p++ = '\n';
    348 
    349     /* copy result code string */
    350     BCM_STRCPY_S(p, sizeof(buf), bta_ag_result_tbl[code].p_res);
    351 #if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
    352     if(p_scb->conn_service == BTA_AG_HSP)
    353     {
    354         /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */
    355         switch(code)
    356         {
    357         case BTA_AG_RES_VGS:
    358         case BTA_AG_RES_VGM:
    359             if(*(p+COLON_IDX_4_VGSVGM) == ':')
    360             {
    361                 #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
    362                 APPL_TRACE_DEBUG("[HSP] ':'symbol is changed as '=' for HSP compatibility");
    363                 #endif
    364                 *(p+COLON_IDX_4_VGSVGM) = '=';
    365             }
    366             break;
    367         }
    368     }
    369 #endif
    370     p += strlen(bta_ag_result_tbl[code].p_res);
    371 
    372     /* copy argument if any */
    373     if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_INT)
    374     {
    375         p += utl_itoa((UINT16) int_arg, p);
    376     }
    377     else if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_STR)
    378     {
    379         BCM_STRCPY_S(p, sizeof(buf), p_arg);
    380         p += strlen(p_arg);
    381     }
    382 
    383     /* finish with \r\n */
    384     *p++ = '\r';
    385     *p++ = '\n';
    386 
    387 #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
    388     APPL_TRACE_DEBUG("bta_ag_send_result: %s", buf);
    389 #endif
    390 
    391     /* send to RFCOMM */
    392     PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
    393 }
    394 
    395 #if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
    396 /*******************************************************************************
    397 **
    398 ** Function         bta_ag_send_multi_result
    399 **
    400 ** Description      Send multiple AT result codes.
    401 **
    402 **
    403 ** Returns          void
    404 **
    405 *******************************************************************************/
    406 static void bta_ag_send_multi_result(tBTA_AG_SCB *p_scb, tBTA_AG_MULTI_RESULT_CB *m_res_cb)
    407 {
    408     char    buf[BTA_AG_AT_MAX_LEN * BTA_AG_AT_MULTI_LEN + 16];
    409     char    *p = buf;
    410     UINT16  len;
    411     UINT8   res_idx = 0;
    412 
    413     if((!m_res_cb) || (m_res_cb->num_result == 0) || (m_res_cb->num_result > BTA_AG_AT_MULTI_LEN))
    414     {
    415         APPL_TRACE_DEBUG("m_res_cb is NULL or num_result is out of range.");
    416         return;
    417     }
    418 
    419 #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
    420     memset(buf, NULL, sizeof(buf));
    421 #endif
    422 
    423     while(res_idx < m_res_cb->num_result)
    424     {
    425         /* init with \r\n */
    426         *p++ = '\r';
    427         *p++ = '\n';
    428 
    429         /* copy result code string */
    430         BCM_STRCPY_S(p, sizeof(buf), bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
    431         p += strlen(bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
    432 
    433         /* copy argument if any */
    434         if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_INT)
    435         {
    436             p += utl_itoa((UINT16) m_res_cb->res_cb[res_idx].int_arg, p);
    437         }
    438         else if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_STR)
    439         {
    440             BCM_STRCPY_S(p, sizeof(buf), m_res_cb->res_cb[res_idx].p_arg);
    441             p += strlen(m_res_cb->res_cb[res_idx].p_arg);
    442         }
    443 
    444         /* finish with \r\n */
    445         *p++ = '\r';
    446         *p++ = '\n';
    447 
    448         res_idx++;
    449     }
    450 
    451 #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
    452     APPL_TRACE_DEBUG("send_result: %s", buf);
    453 #endif
    454 
    455     /* send to RFCOMM */
    456     PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
    457 }
    458 #endif
    459 
    460 /*******************************************************************************
    461 **
    462 ** Function         bta_ag_send_ok
    463 **
    464 ** Description      Send an OK result code.
    465 **
    466 **
    467 ** Returns          void
    468 **
    469 *******************************************************************************/
    470 static void bta_ag_send_ok(tBTA_AG_SCB *p_scb)
    471 {
    472     bta_ag_send_result(p_scb, BTA_AG_RES_OK, NULL, 0);
    473 }
    474 
    475 /*******************************************************************************
    476 **
    477 ** Function         bta_ag_send_error
    478 **
    479 ** Description      Send an ERROR result code.
    480 **                      errcode - used to send verbose errocode
    481 **
    482 **
    483 ** Returns          void
    484 **
    485 *******************************************************************************/
    486 static void bta_ag_send_error(tBTA_AG_SCB *p_scb, INT16 errcode)
    487 {
    488     /* If HFP and extended audio gateway error codes are enabled */
    489     if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
    490         bta_ag_send_result(p_scb, BTA_AG_RES_CMEE, NULL, errcode);
    491     else
    492         bta_ag_send_result(p_scb, BTA_AG_RES_ERROR, NULL, 0);
    493 }
    494 
    495 /*******************************************************************************
    496 **
    497 ** Function         bta_ag_send_ind
    498 **
    499 ** Description      Send an indicator CIEV result code.
    500 **
    501 **
    502 ** Returns          void
    503 **
    504 *******************************************************************************/
    505 static void bta_ag_send_ind(tBTA_AG_SCB *p_scb, UINT16 id, UINT16 value, BOOLEAN on_demand)
    506 {
    507     char    str[12];
    508     char    *p = str;
    509 
    510     /* If the indicator is masked out, just return */
    511     /* Mandatory indicators can not be masked out. */
    512     if ((p_scb->bia_masked_out & ((UINT32)1 << id)) &&
    513         ((id != BTA_AG_IND_CALL) && (id != BTA_AG_IND_CALLSETUP) && (id != BTA_AG_IND_CALLHELD)))
    514         return;
    515 
    516     /* Ensure we do not send duplicate indicators if not requested by app */
    517     /* If it was requested by app, transmit CIEV even if it is duplicate. */
    518     if (id == BTA_AG_IND_CALL)
    519     {
    520         if ((value == p_scb->call_ind) && (on_demand == FALSE))
    521             return;
    522 
    523         p_scb->call_ind = (UINT8)value;
    524     }
    525 
    526     if ((id == BTA_AG_IND_CALLSETUP) && (on_demand == FALSE))
    527     {
    528         if (value == p_scb->callsetup_ind)
    529             return;
    530 
    531         p_scb->callsetup_ind = (UINT8)value;
    532     }
    533 
    534     if ((id == BTA_AG_IND_SERVICE) && (on_demand == FALSE))
    535     {
    536         if (value == p_scb->service_ind)
    537             return;
    538 
    539         p_scb->service_ind = (UINT8)value;
    540     }
    541     if ((id == BTA_AG_IND_SIGNAL) && (on_demand == FALSE))
    542     {
    543         if (value == p_scb->signal_ind)
    544             return;
    545 
    546         p_scb->signal_ind = (UINT8)value;
    547     }
    548     if ((id == BTA_AG_IND_ROAM) && (on_demand == FALSE))
    549     {
    550         if (value == p_scb->roam_ind)
    551             return;
    552 
    553         p_scb->roam_ind = (UINT8)value;
    554     }
    555     if ((id == BTA_AG_IND_BATTCHG) && (on_demand == FALSE))
    556     {
    557         if (value == p_scb->battchg_ind)
    558             return;
    559 
    560         p_scb->battchg_ind = (UINT8)value;
    561     }
    562 
    563     if ((id == BTA_AG_IND_CALLHELD) && (on_demand == FALSE))
    564     {
    565         /* call swap could result in sending callheld=1 multiple times */
    566         if ((value != 1) && (value == p_scb->callheld_ind))
    567             return;
    568 
    569         p_scb->callheld_ind = (UINT8)value;
    570     }
    571 
    572     if (p_scb->cmer_enabled)
    573     {
    574         p += utl_itoa(id, p);
    575         *p++ = ',';
    576         utl_itoa(value, p);
    577         bta_ag_send_result(p_scb, BTA_AG_RES_CIEV, str, 0);
    578     }
    579 }
    580 
    581 /*******************************************************************************
    582 **
    583 ** Function         bta_ag_parse_cmer
    584 **
    585 ** Description      Parse AT+CMER parameter string.
    586 **
    587 **
    588 ** Returns          TRUE if parsed ok, FALSE otherwise.
    589 **
    590 *******************************************************************************/
    591 static BOOLEAN bta_ag_parse_cmer(char *p_s, BOOLEAN *p_enabled)
    592 {
    593     INT16   n[4] = {-1, -1, -1, -1};
    594     int     i;
    595     char    *p;
    596 
    597     for (i = 0; i < 4; i++)
    598     {
    599         /* skip to comma delimiter */
    600         for (p = p_s; *p != ',' && *p != 0; p++);
    601 
    602         /* get integer value */
    603         *p = 0;
    604         n[i] = utl_str2int(p_s);
    605         p_s = p + 1;
    606         if (p_s == 0)
    607         {
    608             break;
    609         }
    610     }
    611 
    612     /* process values */
    613     if (n[0] < 0 || n[3] < 0)
    614     {
    615         return FALSE;
    616     }
    617 
    618     if ((n[0] == 3) && ((n[3] == 1) || (n[3] == 0)))
    619     {
    620         *p_enabled = (BOOLEAN) n[3];
    621     }
    622 
    623     return TRUE;
    624 }
    625 
    626 /*******************************************************************************
    627 **
    628 ** Function         bta_ag_parse_chld
    629 **
    630 ** Description      Parse AT+CHLD parameter string.
    631 **
    632 **
    633 ** Returns          Returns idx (1-7), 0 if ECC not enabled or BTA_AG_INVALID_CHLD
    634                     if idx doesn't exist/1st character of argument is not a digit
    635 **
    636 *******************************************************************************/
    637 static UINT8 bta_ag_parse_chld(tBTA_AG_SCB *p_scb, char *p_s)
    638 {
    639     UINT8   retval = 0;
    640     INT16   idx = -1;
    641     UNUSED(p_scb);
    642 
    643     if (!isdigit(p_s[0]))
    644     {
    645         return BTA_AG_INVALID_CHLD;
    646     }
    647 
    648     if (p_s[1] != 0)
    649     {
    650         /* p_idxstr++;  point to beginning of call number */
    651         idx = utl_str2int(&p_s[1]);
    652         if (idx != -1 && idx < 255)
    653         {
    654             retval = (UINT8)idx;
    655         }
    656         else
    657         {
    658             retval = BTA_AG_INVALID_CHLD;
    659         }
    660     }
    661 
    662     return (retval);
    663 }
    664 
    665 #if (BTM_WBS_INCLUDED == TRUE )
    666 /*******************************************************************************
    667 **
    668 ** Function         bta_ag_parse_bac
    669 **
    670 ** Description      Parse AT+BAC parameter string.
    671 **
    672 ** Returns          Returns bitmap of supported codecs.
    673 **
    674 *******************************************************************************/
    675 static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB *p_scb, char *p_s)
    676 {
    677     tBTA_AG_PEER_CODEC  retval = BTA_AG_CODEC_NONE;
    678     UINT16  uuid_codec;
    679     BOOLEAN cont = FALSE;       /* Continue processing */
    680     char *p;
    681 
    682     while(p_s)
    683     {
    684         /* skip to comma delimiter */
    685         for(p = p_s; *p != ',' && *p != 0; p++);
    686 
    687         /* get integre value */
    688         if (*p != 0)
    689         {
    690             *p = 0;
    691             cont = TRUE;
    692         }
    693         else
    694             cont = FALSE;
    695 
    696         uuid_codec = utl_str2int(p_s);
    697         switch(uuid_codec)
    698         {
    699             case UUID_CODEC_CVSD:   retval |= BTA_AG_CODEC_CVSD;     break;
    700             case UUID_CODEC_MSBC:   retval |= BTA_AG_CODEC_MSBC;     break;
    701             default:
    702                 APPL_TRACE_ERROR("Unknown Codec UUID(%d) received", uuid_codec);
    703                 return BTA_AG_CODEC_NONE;
    704         }
    705 
    706         if (cont)
    707             p_s = p + 1;
    708         else
    709             break;
    710     }
    711 
    712     return (retval);
    713 }
    714 #endif
    715 
    716 /*******************************************************************************
    717 **
    718 ** Function         bta_ag_process_unat_res
    719 **
    720 ** Description      Process the unat response data and remove extra carriage return
    721 **                  and line feed
    722 **
    723 **
    724 ** Returns          void
    725 **
    726 *******************************************************************************/
    727 
    728 static void bta_ag_process_unat_res(char *unat_result)
    729 {
    730     UINT8   str_leng;
    731     UINT8   i = 0;
    732     UINT8   j = 0;
    733     UINT8   pairs_of_nl_cr;
    734     char    trim_data[BTA_AG_AT_MAX_LEN];
    735 
    736 
    737 
    738     str_leng = strlen(unat_result);
    739 
    740     /* If no extra CR and LF, just return */
    741     if(str_leng < 4)
    742         return;
    743 
    744     /* Remove the carriage return and left feed */
    745     while(unat_result[0] =='\r' && unat_result[1] =='\n'
    746         && unat_result[str_leng-2] =='\r' && unat_result[str_leng-1] =='\n')
    747     {
    748         pairs_of_nl_cr = 1;
    749         for (i=0;i<(str_leng-4*pairs_of_nl_cr);i++)
    750         {
    751             trim_data[j++] = unat_result[i+pairs_of_nl_cr*2];
    752         }
    753         /* Add EOF */
    754         trim_data[j] = '\0';
    755         str_leng = str_leng - 4;
    756         BCM_STRNCPY_S(unat_result, BTA_AG_AT_MAX_LEN+1, trim_data,str_leng+1);
    757         i=0;
    758         j=0;
    759 
    760         if(str_leng <4)
    761             return;
    762 
    763 
    764     }
    765     return;
    766 }
    767 
    768 
    769 /*******************************************************************************
    770 **
    771 ** Function         bta_ag_inband_enabled
    772 **
    773 ** Description      Determine whether in-band ring can be used.
    774 **
    775 **
    776 ** Returns          void
    777 **
    778 *******************************************************************************/
    779 BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb)
    780 {
    781     /* if feature is enabled and no other scbs connected */
    782     if (p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb))
    783     {
    784         return TRUE;
    785     }
    786     else
    787     {
    788         return FALSE;
    789     }
    790 }
    791 
    792 /*******************************************************************************
    793 **
    794 ** Function         bta_ag_send_call_inds
    795 **
    796 ** Description      Send call and callsetup indicators.
    797 **
    798 **
    799 ** Returns          void
    800 **
    801 *******************************************************************************/
    802 void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
    803 {
    804     UINT8 call = p_scb->call_ind;
    805     UINT8 callsetup;
    806 
    807     /* set new call and callsetup values based on BTA_AgResult */
    808     callsetup = bta_ag_callsetup_ind_tbl[result];
    809 
    810     if (result == BTA_AG_END_CALL_RES)
    811     {
    812         call = BTA_AG_CALL_INACTIVE;
    813     }
    814     else if (result == BTA_AG_IN_CALL_CONN_RES || result == BTA_AG_OUT_CALL_CONN_RES
    815              || result == BTA_AG_IN_CALL_HELD_RES)
    816     {
    817         call = BTA_AG_CALL_ACTIVE;
    818     }
    819     else
    820     {
    821         call = p_scb->call_ind;
    822     }
    823 
    824     /* Send indicator function tracks if the values have actually changed */
    825     bta_ag_send_ind(p_scb, BTA_AG_IND_CALL, call, FALSE);
    826     bta_ag_send_ind(p_scb, BTA_AG_IND_CALLSETUP, callsetup, FALSE);
    827 }
    828 
    829 /*******************************************************************************
    830 **
    831 ** Function         bta_ag_at_hsp_cback
    832 **
    833 ** Description      AT command processing callback for HSP.
    834 **
    835 **
    836 ** Returns          void
    837 **
    838 *******************************************************************************/
    839 void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
    840                                 char *p_arg, INT16 int_arg)
    841 {
    842     tBTA_AG_VAL val;
    843 
    844     APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
    845                       int_arg, p_arg);
    846 
    847     /* send OK */
    848     bta_ag_send_ok(p_scb);
    849 
    850     val.hdr.handle = bta_ag_scb_to_idx(p_scb);
    851     val.hdr.app_id = p_scb->app_id;
    852     val.num = (UINT16) int_arg;
    853     BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
    854     val.str[BTA_AG_AT_MAX_LEN] = 0;
    855 
    856     /* call callback with event */
    857     (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
    858 }
    859 
    860 /*******************************************************************************
    861 **
    862 ** Function         bta_ag_at_hfp_cback
    863 **
    864 ** Description      AT command processing callback for HFP.
    865 **
    866 **
    867 ** Returns          void
    868 **
    869 *******************************************************************************/
    870 void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
    871                                 char *p_arg, INT16 int_arg)
    872 {
    873     tBTA_AG_VAL     val;
    874     tBTA_AG_EVT   event;
    875     tBTA_AG_SCB     *ag_scb;
    876     UINT32          i, ind_id;
    877     UINT32          bia_masked_out;
    878 #if (BTM_WBS_INCLUDED == TRUE )
    879     tBTA_AG_PEER_CODEC  codec_type, codec_sent;
    880 #endif
    881     if (p_arg == NULL)
    882     {
    883         APPL_TRACE_ERROR("%s: p_arg is null, send error and return", __func__);
    884         bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
    885         return;
    886     }
    887 
    888     APPL_TRACE_DEBUG("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
    889                       int_arg, p_arg);
    890 
    891     val.hdr.handle = bta_ag_scb_to_idx(p_scb);
    892     val.hdr.app_id = p_scb->app_id;
    893     val.num = int_arg;
    894     bdcpy(val.bd_addr, p_scb->peer_addr);
    895     BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
    896     val.str[BTA_AG_AT_MAX_LEN] = 0;
    897 
    898     event = bta_ag_hfp_cb_evt[cmd];
    899 
    900     switch (cmd)
    901     {
    902         case BTA_AG_HF_CMD_A:
    903         case BTA_AG_HF_CMD_VGS:
    904         case BTA_AG_HF_CMD_VGM:
    905         case BTA_AG_HF_CMD_CHUP:
    906         case BTA_AG_HF_CMD_CBC:
    907             /* send OK */
    908             bta_ag_send_ok(p_scb);
    909             break;
    910 
    911         case BTA_AG_HF_CMD_BLDN:
    912             /* Do not send OK, App will send error or OK depending on
    913             ** last dial number enabled or not */
    914             break;
    915 
    916         case BTA_AG_HF_CMD_D:
    917             /* Do not send OK for Dial cmds
    918             ** Let application decide whether to send OK or ERROR*/
    919 
    920             /* if mem dial cmd, make sure string contains only digits */
    921             if(p_arg[0] == '>')
    922             {
    923                 if(!utl_isintstr(p_arg+1))
    924                 {
    925                     event = 0;
    926                     bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
    927                 }
    928             }
    929             else if (p_arg[0] == 'V')   /* ATDV : Dial VoIP Call */
    930             {
    931                 /* We do not check string. Code will be added later if needed. */
    932                 if(!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) && (p_scb->features & BTA_AG_FEAT_VOIP)))
    933                 {
    934                     event = 0;
    935                     bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
    936                 }
    937             }
    938             /* If dial cmd, make sure string contains only dial digits
    939             ** Dial digits are 0-9, A-C, *, #, + */
    940             else
    941             {
    942                 if(!utl_isdialstr(p_arg))
    943                 {
    944                     event = 0;
    945                     bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
    946                 }
    947             }
    948             break;
    949 
    950         case BTA_AG_HF_CMD_CCWA:
    951             /* store setting */
    952             p_scb->ccwa_enabled = (BOOLEAN) int_arg;
    953 
    954             /* send OK */
    955             bta_ag_send_ok(p_scb);
    956             break;
    957 
    958         case BTA_AG_HF_CMD_CHLD:
    959             if (arg_type == BTA_AG_AT_TEST)
    960             {
    961                 /* don't call callback */
    962                 event = 0;
    963 
    964                 /* send CHLD string */
    965                 /* Form string based on supported 1.5 feature */
    966                 if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
    967                     (p_scb->features & BTA_AG_FEAT_ECC) &&
    968                     (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
    969                     bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
    970                 else
    971                     bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
    972 
    973                 /* send OK */
    974                 bta_ag_send_ok(p_scb);
    975 
    976                 /* if service level conn. not already open, now it's open */
    977                 bta_ag_svc_conn_open(p_scb, NULL);
    978 
    979             }
    980             else
    981             {
    982                 val.idx = bta_ag_parse_chld(p_scb, val.str);
    983 
    984                 if (val.idx == BTA_AG_INVALID_CHLD)
    985                 {
    986                     event = 0;
    987                     bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
    988                     break;
    989                 }
    990                 if(val.idx && !((p_scb->features & BTA_AG_FEAT_ECC) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC)))
    991                 {
    992                     /* we do not support ECC, but HF is sending us a CHLD with call index*/
    993                     event = 0;
    994                     bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
    995 
    996                 }
    997                 else
    998                 {
    999 
   1000                 /* If it is swap between calls, set call held indicator to 3(out of valid 0-2)
   1001                 ** Application will set it back to 1
   1002                 ** callheld indicator will be sent across to the peer. */
   1003                 if(val.str[0] == '2')
   1004                 {
   1005                     for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
   1006                     {
   1007                         if (ag_scb->in_use)
   1008                         {
   1009                             if((ag_scb->call_ind == BTA_AG_CALL_ACTIVE)
   1010                                 && (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
   1011                                 ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1;
   1012                         }
   1013                     }
   1014                 }
   1015                 }
   1016 
   1017                 /* Do not send OK. Let app decide after parsing the val str */
   1018                 /* bta_ag_send_ok(p_scb); */
   1019             }
   1020             break;
   1021 
   1022         case BTA_AG_HF_CMD_CIND:
   1023             if (arg_type == BTA_AG_AT_TEST)
   1024             {
   1025                 /* don't call callback */
   1026                 event = 0;
   1027 
   1028                 /* send CIND string, send OK */
   1029                 bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
   1030                 bta_ag_send_ok(p_scb);
   1031             }
   1032             break;
   1033 
   1034         case BTA_AG_HF_CMD_CLIP:
   1035             /* store setting, send OK */
   1036             p_scb->clip_enabled = (BOOLEAN) int_arg;
   1037             bta_ag_send_ok(p_scb);
   1038             break;
   1039 
   1040         case BTA_AG_HF_CMD_CMER:
   1041             /* if parsed ok store setting, send OK */
   1042             if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled))
   1043             {
   1044                 bta_ag_send_ok(p_scb);
   1045 
   1046                 /* if service level conn. not already open and our features and
   1047                 ** peer features do not have 3-way, service level conn. now open
   1048                 */
   1049                 if (!p_scb->svc_conn &&
   1050                     !((p_scb->features & BTA_AG_FEAT_3WAY) && (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)))
   1051                 {
   1052                     bta_ag_svc_conn_open(p_scb, NULL);
   1053                 }
   1054             }
   1055             else
   1056             {
   1057                 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
   1058             }
   1059             break;
   1060 
   1061         case BTA_AG_HF_CMD_VTS:
   1062             /* check argument */
   1063             if (strlen(p_arg) == 1)
   1064             {
   1065                 bta_ag_send_ok(p_scb);
   1066             }
   1067             else
   1068             {
   1069                 event = 0;
   1070                 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
   1071             }
   1072             break;
   1073 
   1074         case BTA_AG_HF_CMD_BINP:
   1075             /* if feature not set don't call callback, send ERROR */
   1076             if (!(p_scb->features & BTA_AG_FEAT_VTAG))
   1077             {
   1078                 event = 0;
   1079                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1080             }
   1081             break;
   1082 
   1083         case BTA_AG_HF_CMD_BVRA:
   1084             /* if feature not supported don't call callback, send ERROR. App will send OK */
   1085             if (!(p_scb->features & BTA_AG_FEAT_VREC))
   1086             {
   1087                 event = 0;
   1088                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1089             }
   1090             break;
   1091 
   1092         case BTA_AG_HF_CMD_BRSF:
   1093             /* store peer features */
   1094             p_scb->peer_features = (UINT16) int_arg;
   1095 
   1096             /* send BRSF, send OK */
   1097             bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
   1098                                (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC));
   1099             bta_ag_send_ok(p_scb);
   1100             break;
   1101 
   1102         case BTA_AG_HF_CMD_NREC:
   1103             /* if feature send OK, else don't call callback, send ERROR */
   1104             if (p_scb->features & BTA_AG_FEAT_ECNR)
   1105             {
   1106                 bta_ag_send_ok(p_scb);
   1107             }
   1108             else
   1109             {
   1110                 event = 0;
   1111                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1112             }
   1113             break;
   1114 
   1115         case BTA_AG_HF_CMD_BTRH:
   1116             /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
   1117             if (p_scb->features & BTA_AG_FEAT_BTRH)
   1118             {
   1119                 /* If set command; send response and notify app */
   1120                 if (arg_type == BTA_AG_AT_SET)
   1121                 {
   1122                     for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
   1123                     {
   1124                         if (ag_scb->in_use)
   1125                         {
   1126                             bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
   1127                         }
   1128                     }
   1129                     bta_ag_send_ok(p_scb);
   1130                 }
   1131                 else /* Read Command */
   1132                 {
   1133                     val.num = BTA_AG_BTRH_READ;
   1134                 }
   1135             }
   1136             else
   1137             {
   1138                 event = 0;
   1139                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1140             }
   1141             break;
   1142 
   1143         case BTA_AG_HF_CMD_COPS:
   1144             if (arg_type == BTA_AG_AT_SET)
   1145             {
   1146                 /* don't call callback */
   1147                 event = 0;
   1148 
   1149                 /* send OK */
   1150                 bta_ag_send_ok(p_scb);
   1151             }
   1152             break;
   1153 
   1154         case BTA_AG_HF_CMD_CMEE:
   1155             if (p_scb->features & BTA_AG_FEAT_EXTERR)
   1156             {
   1157                 /* store setting */
   1158                 p_scb->cmee_enabled = (BOOLEAN) int_arg;
   1159 
   1160                 /* send OK */
   1161                 bta_ag_send_ok(p_scb);
   1162             }
   1163             else
   1164             {
   1165                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1166             }
   1167             /* don't call callback */
   1168             event = 0;
   1169             break;
   1170 
   1171         case BTA_AG_HF_CMD_BIA:
   1172             /* don't call callback */
   1173             event = 0;
   1174 
   1175             bia_masked_out = p_scb->bia_masked_out;
   1176 
   1177             /* Parse the indicator mask */
   1178             for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); i++, ind_id++)
   1179             {
   1180                 if (val.str[i] == ',')
   1181                     continue;
   1182 
   1183                 if (val.str[i] == '0')
   1184                     bia_masked_out |= ((UINT32)1 << ind_id);
   1185                 else if (val.str[i] == '1')
   1186                     bia_masked_out &= ~((UINT32)1 << ind_id);
   1187                 else
   1188                     break;
   1189 
   1190                 i++;
   1191                 if ( (val.str[i] != 0) && (val.str[i] != ',') )
   1192                     break;
   1193             }
   1194             if (val.str[i] == 0)
   1195             {
   1196                 p_scb->bia_masked_out = bia_masked_out;
   1197                 bta_ag_send_ok (p_scb);
   1198             }
   1199             else
   1200                 bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
   1201             break;
   1202 
   1203         case BTA_AG_HF_CMD_CNUM:
   1204             break;
   1205         case BTA_AG_HF_CMD_CLCC:
   1206             if(!(p_scb->features & BTA_AG_FEAT_ECS))
   1207             {
   1208                 event = 0;
   1209                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1210             }
   1211             break;
   1212 
   1213 #if (BTM_WBS_INCLUDED == TRUE )
   1214         case BTA_AG_HF_CMD_BAC:
   1215             bta_ag_send_ok(p_scb);
   1216 
   1217             /* store available codecs from the peer */
   1218             if((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC))
   1219             {
   1220                 p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
   1221                 p_scb->codec_updated = TRUE;
   1222 
   1223                 if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC)
   1224                 {
   1225                     p_scb->sco_codec = UUID_CODEC_MSBC;
   1226                     APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to MSBC");
   1227                 }
   1228                 else
   1229                 {
   1230                     p_scb->sco_codec = UUID_CODEC_CVSD;
   1231                     APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to CVSD");
   1232                 }
   1233                 /* The above logic sets the stack preferred codec based on local and peer codec
   1234                 capabilities. This can be overridden by the application depending on its preference
   1235                 using the bta_ag_setcodec API. We send the peer_codecs to the application. */
   1236                 val.num = p_scb->peer_codecs;
   1237                 /* Received BAC while in codec negotiation. */
   1238                 if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && (bta_ag_cb.sco.p_curr_scb == p_scb))
   1239                 {
   1240                     bta_ag_codec_negotiate (p_scb);
   1241                 }
   1242             }
   1243             else
   1244             {
   1245                 p_scb->peer_codecs = BTA_AG_CODEC_NONE;
   1246                 APPL_TRACE_ERROR("Unexpected CMD:AT+BAC, Codec Negotiation is not supported");
   1247             }
   1248             break;
   1249 
   1250         case BTA_AG_HF_CMD_BCS:
   1251             bta_ag_send_ok(p_scb);
   1252 
   1253             /* stop cn timer */
   1254             bta_sys_stop_timer(&p_scb->cn_timer);
   1255 
   1256             switch(int_arg)
   1257             {
   1258                 case UUID_CODEC_CVSD:   codec_type = BTA_AG_CODEC_CVSD;     break;
   1259                 case UUID_CODEC_MSBC:   codec_type = BTA_AG_CODEC_MSBC;     break;
   1260                 default:
   1261                     APPL_TRACE_ERROR("Unknown codec_uuid %d", int_arg);
   1262                     codec_type = 0xFFFF;
   1263                     break;
   1264             }
   1265 
   1266             if (p_scb->codec_fallback)
   1267                 codec_sent = BTA_AG_CODEC_CVSD;
   1268             else
   1269                 codec_sent = p_scb->sco_codec;
   1270 
   1271             if(codec_type == codec_sent)
   1272                 bta_ag_sco_codec_nego(p_scb, TRUE);
   1273             else
   1274                 bta_ag_sco_codec_nego(p_scb, FALSE);
   1275 
   1276             /* send final codec info to callback */
   1277             val.num = codec_sent;
   1278             break;
   1279 
   1280         case BTA_AG_HF_CMD_BCC:
   1281             bta_ag_send_ok(p_scb);
   1282             bta_ag_sco_open(p_scb, NULL);
   1283             break;
   1284 #endif
   1285 
   1286         default:
   1287             bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1288             break;
   1289     }
   1290 
   1291     /* call callback */
   1292     if (event != 0)
   1293     {
   1294         (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &val);
   1295     }
   1296 }
   1297 
   1298 /*******************************************************************************
   1299 **
   1300 ** Function         bta_ag_at_err_cback
   1301 **
   1302 ** Description      AT command parser error callback.
   1303 **
   1304 **
   1305 ** Returns          void
   1306 **
   1307 *******************************************************************************/
   1308 void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
   1309 {
   1310     tBTA_AG_VAL     val;
   1311 
   1312     if(unknown && (!strlen(p_arg)))
   1313     {
   1314         APPL_TRACE_DEBUG("Empty AT cmd string received");
   1315         bta_ag_send_ok(p_scb);
   1316         return;
   1317     }
   1318 
   1319     /* if unknown AT command and configured to pass these to app */
   1320     if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT))
   1321     {
   1322         val.hdr.handle = bta_ag_scb_to_idx(p_scb);
   1323         val.hdr.app_id = p_scb->app_id;
   1324         val.num = 0;
   1325         BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
   1326         val.str[BTA_AG_AT_MAX_LEN] = 0;
   1327         (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
   1328     }
   1329     else
   1330     {
   1331         bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
   1332     }
   1333 }
   1334 
   1335 /*******************************************************************************
   1336 **
   1337 ** Function         bta_ag_hsp_result
   1338 **
   1339 ** Description      Handle API result for HSP connections.
   1340 **
   1341 **
   1342 ** Returns          void
   1343 **
   1344 *******************************************************************************/
   1345 void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
   1346 {
   1347     UINT8 code = bta_ag_trans_result[p_result->result];
   1348 
   1349     APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result);
   1350 
   1351     switch(p_result->result)
   1352     {
   1353         case BTA_AG_SPK_RES:
   1354         case BTA_AG_MIC_RES:
   1355             bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
   1356             break;
   1357 
   1358         case BTA_AG_IN_CALL_RES:
   1359             /* tell sys to stop av if any */
   1360             bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
   1361 
   1362             /* if sco already opened or no inband ring send ring now */
   1363             if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
   1364                 (p_scb->features & BTA_AG_FEAT_NOSCO))
   1365             {
   1366                 bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
   1367             }
   1368             /* else open sco, send ring after sco opened */
   1369             else
   1370             {
   1371                 /* HSPv1.2: AG shall not send RING if using in-band ring tone. */
   1372                 if (p_scb->hsp_version >= HSP_VERSION_1_2)
   1373                     p_scb->post_sco = BTA_AG_POST_SCO_NONE;
   1374                 else
   1375                     p_scb->post_sco = BTA_AG_POST_SCO_RING;
   1376 
   1377                 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1378             }
   1379             break;
   1380 
   1381         case BTA_AG_IN_CALL_CONN_RES:
   1382         case BTA_AG_OUT_CALL_ORIG_RES:
   1383             /* if incoming call connected stop ring timer */
   1384             if (p_result->result == BTA_AG_IN_CALL_CONN_RES)
   1385             {
   1386                 bta_sys_stop_timer(&p_scb->act_timer);
   1387             }
   1388 
   1389             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
   1390             {
   1391                 /* if audio connected to this scb open sco */
   1392                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
   1393                 {
   1394                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1395                 }
   1396                 /* else if no audio at call close sco */
   1397                 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
   1398                 {
   1399                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
   1400                 }
   1401             }
   1402             break;
   1403 
   1404         case BTA_AG_END_CALL_RES:
   1405             /* stop ring timer */
   1406             bta_sys_stop_timer(&p_scb->act_timer);
   1407 
   1408             /* close sco */
   1409             if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
   1410             {
   1411                 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
   1412             }
   1413             else
   1414             {
   1415                 /* if av got suspended by this call, let it resume. */
   1416                 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
   1417             }
   1418             break;
   1419 
   1420         case BTA_AG_INBAND_RING_RES:
   1421             p_scb->inband_enabled = p_result->data.state;
   1422             APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
   1423             break;
   1424 
   1425         case BTA_AG_UNAT_RES:
   1426             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
   1427             {
   1428                 if (p_result->data.str[0] != 0)
   1429                 {
   1430                     bta_ag_send_result(p_scb, code, p_result->data.str, 0);
   1431                 }
   1432 
   1433                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
   1434                     bta_ag_send_ok(p_scb);
   1435             }
   1436             else
   1437             {
   1438                 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
   1439             }
   1440             break;
   1441 
   1442         default:
   1443             /* ignore all others */
   1444             break;
   1445     }
   1446 }
   1447 
   1448 /*******************************************************************************
   1449 **
   1450 ** Function         bta_ag_hfp_result
   1451 **
   1452 ** Description      Handle API result for HFP connections.
   1453 **
   1454 **
   1455 ** Returns          void
   1456 **
   1457 *******************************************************************************/
   1458 void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
   1459 {
   1460     UINT8 code = bta_ag_trans_result[p_result->result];
   1461 
   1462     APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
   1463 
   1464     switch(p_result->result)
   1465     {
   1466         case BTA_AG_SPK_RES:
   1467         case BTA_AG_MIC_RES:
   1468             bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
   1469             break;
   1470 
   1471         case BTA_AG_IN_CALL_RES:
   1472             /* tell sys to stop av if any */
   1473             bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
   1474 
   1475             /* store caller id string.
   1476              * append type info at the end.
   1477              * make sure a valid type info is passed.
   1478              * otherwise add 129 as default type */
   1479             if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) || (p_result->data.num > BTA_AG_CLIP_TYPE_MAX))
   1480             {
   1481                 if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
   1482                     p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
   1483             }
   1484 
   1485             APPL_TRACE_DEBUG("CLIP type :%d", p_result->data.num);
   1486             p_scb->clip[0] = 0;
   1487             if (p_result->data.str[0] != 0)
   1488                 snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", p_result->data.str, p_result->data.num);
   1489 
   1490             /* send callsetup indicator */
   1491             if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)
   1492             {
   1493                 /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO close. */
   1494                 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
   1495             }
   1496             else
   1497             {
   1498                 bta_ag_send_call_inds(p_scb, p_result->result);
   1499 
   1500                 /* if sco already opened or no inband ring send ring now */
   1501                 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
   1502                     (p_scb->features & BTA_AG_FEAT_NOSCO))
   1503                 {
   1504                     bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
   1505                 }
   1506                 /* else open sco, send ring after sco opened */
   1507                 else
   1508                 {
   1509                     p_scb->post_sco = BTA_AG_POST_SCO_RING;
   1510                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1511                 }
   1512             }
   1513             break;
   1514 
   1515         case BTA_AG_IN_CALL_CONN_RES:
   1516             /* stop ring timer */
   1517             bta_sys_stop_timer(&p_scb->act_timer);
   1518 
   1519             /* if sco not opened and we need to open it, send indicators first
   1520             ** then  open sco.
   1521             */
   1522             bta_ag_send_call_inds(p_scb, p_result->result);
   1523 
   1524             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
   1525             {
   1526                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
   1527                 {
   1528                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1529                 }
   1530                 else if ((p_result->data.audio_handle == BTA_AG_HANDLE_NONE) &&
   1531                         bta_ag_sco_is_open(p_scb))
   1532                 {
   1533                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
   1534                 }
   1535             }
   1536             break;
   1537 
   1538         case BTA_AG_IN_CALL_HELD_RES:
   1539             /* stop ring timer */
   1540             bta_sys_stop_timer(&p_scb->act_timer);
   1541 
   1542             bta_ag_send_call_inds(p_scb, p_result->result);
   1543 
   1544             break;
   1545 
   1546         case BTA_AG_OUT_CALL_ORIG_RES:
   1547             bta_ag_send_call_inds(p_scb, p_result->result);
   1548             if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
   1549                 !(p_scb->features & BTA_AG_FEAT_NOSCO))
   1550             {
   1551                 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1552             }
   1553             break;
   1554 
   1555         case BTA_AG_OUT_CALL_ALERT_RES:
   1556             /* send indicators */
   1557             bta_ag_send_call_inds(p_scb, p_result->result);
   1558             if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
   1559                 !(p_scb->features & BTA_AG_FEAT_NOSCO))
   1560             {
   1561                 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1562             }
   1563             break;
   1564 
   1565         case BTA_AG_MULTI_CALL_RES:
   1566             /* open SCO at SLC for this three way call */
   1567             APPL_TRACE_DEBUG("Headset Connected in three way call");
   1568             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
   1569             {
   1570                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
   1571                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1572                 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
   1573                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
   1574             }
   1575             break;
   1576 
   1577         case BTA_AG_OUT_CALL_CONN_RES:
   1578             /* send indicators */
   1579             bta_ag_send_call_inds(p_scb, p_result->result);
   1580 
   1581             /* open or close sco */
   1582             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
   1583             {
   1584                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
   1585                 {
   1586                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
   1587                 }
   1588                 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
   1589                 {
   1590                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
   1591                 }
   1592             }
   1593             break;
   1594 
   1595         case BTA_AG_CALL_CANCEL_RES:
   1596             /* send indicators */
   1597             bta_ag_send_call_inds(p_scb, p_result->result);
   1598             break;
   1599 
   1600         case BTA_AG_END_CALL_RES:
   1601             /* stop ring timer */
   1602             bta_sys_stop_timer(&p_scb->act_timer);
   1603 
   1604             /* if sco open, close sco then send indicator values */
   1605             if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
   1606             {
   1607                 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
   1608                 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
   1609             }
   1610             else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL)
   1611             {
   1612                 /* sco closing for outgoing call because of incoming call */
   1613                 /* Send only callsetup end indicator after sco close */
   1614                 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
   1615             }
   1616             else
   1617             {
   1618                 bta_ag_send_call_inds(p_scb, p_result->result);
   1619 
   1620                 /* if av got suspended by this call, let it resume. */
   1621                 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
   1622             }
   1623             break;
   1624 
   1625         case BTA_AG_INBAND_RING_RES:
   1626             p_scb->inband_enabled = p_result->data.state;
   1627             APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
   1628             bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
   1629             break;
   1630 
   1631         case BTA_AG_CIND_RES:
   1632             /* store local values */
   1633             p_scb->call_ind = p_result->data.str[0] - '0';
   1634             p_scb->callsetup_ind = p_result->data.str[2] - '0';
   1635             p_scb->service_ind = p_result->data.str[4] - '0';
   1636             p_scb->signal_ind = p_result->data.str[6] - '0';
   1637             p_scb->roam_ind = p_result->data.str[8] - '0';
   1638             p_scb->battchg_ind = p_result->data.str[10] - '0';
   1639             p_scb->callheld_ind = p_result->data.str[12] - '0';
   1640             APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
   1641 
   1642             bta_ag_send_result(p_scb, code, p_result->data.str, 0);
   1643             bta_ag_send_ok(p_scb);
   1644             break;
   1645 
   1646         case BTA_AG_BINP_RES:
   1647         case BTA_AG_CNUM_RES:
   1648         case BTA_AG_CLCC_RES:
   1649         case BTA_AG_COPS_RES:
   1650             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
   1651             {
   1652                 if (p_result->data.str[0] != 0)
   1653                 {
   1654                    bta_ag_send_result(p_scb, code, p_result->data.str, 0);
   1655                 }
   1656 
   1657                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
   1658                     bta_ag_send_ok(p_scb);
   1659             }
   1660             else
   1661             {
   1662                 bta_ag_send_error(p_scb, p_result->data.errcode);
   1663             }
   1664             break;
   1665 
   1666 
   1667         case BTA_AG_UNAT_RES:
   1668             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
   1669             {
   1670                 if (p_result->data.str[0] != 0)
   1671                 {
   1672                     bta_ag_process_unat_res(p_result->data.str);
   1673                     APPL_TRACE_DEBUG("BTA_AG_RES :%s",p_result->data.str);
   1674                     bta_ag_send_result(p_scb, code, p_result->data.str, 0);
   1675                 }
   1676 
   1677                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
   1678                     bta_ag_send_ok(p_scb);
   1679             }
   1680             else
   1681             {
   1682                 bta_ag_send_error(p_scb, p_result->data.errcode);
   1683             }
   1684             break;
   1685 
   1686         case BTA_AG_CALL_WAIT_RES:
   1687             if (p_scb->ccwa_enabled)
   1688             {
   1689                 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
   1690             }
   1691             bta_ag_send_call_inds(p_scb, p_result->result);
   1692             break;
   1693 
   1694         case BTA_AG_IND_RES:
   1695             bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value, FALSE);
   1696             break;
   1697 
   1698         case BTA_AG_BVRA_RES:
   1699             bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
   1700             break;
   1701 
   1702         case BTA_AG_BTRH_RES:
   1703             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
   1704             {
   1705                 /* Don't respond to read if not in response & hold state */
   1706                 if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
   1707                 {
   1708                     bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
   1709                 }
   1710 
   1711                 /* In case of a response to a read request we need to send OK */
   1712                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
   1713                     bta_ag_send_ok(p_scb);
   1714             }
   1715             else
   1716             {
   1717                 bta_ag_send_error(p_scb, p_result->data.errcode);
   1718             }
   1719             break;
   1720 
   1721        default:
   1722             break;
   1723     }
   1724 }
   1725 
   1726 
   1727 /*******************************************************************************
   1728 **
   1729 ** Function         bta_ag_result
   1730 **
   1731 ** Description      Handle API result.
   1732 **
   1733 **
   1734 ** Returns          void
   1735 **
   1736 *******************************************************************************/
   1737 void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
   1738 {
   1739     if (p_scb->conn_service == BTA_AG_HSP)
   1740     {
   1741         bta_ag_hsp_result(p_scb, &p_data->api_result);
   1742     }
   1743     else
   1744     {
   1745         bta_ag_hfp_result(p_scb, &p_data->api_result);
   1746     }
   1747 }
   1748 
   1749 #if (BTM_WBS_INCLUDED == TRUE )
   1750 /*******************************************************************************
   1751 **
   1752 ** Function         bta_ag_send_bcs
   1753 **
   1754 ** Description      Send +BCS AT command to peer.
   1755 **
   1756 ** Returns          void
   1757 **
   1758 *******************************************************************************/
   1759 void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
   1760 {
   1761     UINT16 codec_uuid;
   1762 
   1763     if (p_scb->codec_fallback)
   1764     {
   1765         codec_uuid = UUID_CODEC_CVSD;
   1766     }
   1767     else
   1768     {
   1769         switch(p_scb->sco_codec)
   1770         {
   1771             case BTA_AG_CODEC_NONE:     codec_uuid = UUID_CODEC_CVSD;   break;
   1772             case BTA_AG_CODEC_CVSD:     codec_uuid = UUID_CODEC_CVSD;   break;
   1773             case BTA_AG_CODEC_MSBC:     codec_uuid = UUID_CODEC_MSBC;   break;
   1774             default:
   1775                 APPL_TRACE_ERROR("bta_ag_send_bcs: unknown codec %d, use CVSD", p_scb->sco_codec);
   1776                 codec_uuid = UUID_CODEC_CVSD;
   1777                 break;
   1778         }
   1779     }
   1780 
   1781     /* send +BCS */
   1782     APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid);
   1783     bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
   1784 
   1785 }
   1786 #endif
   1787 
   1788 /*******************************************************************************
   1789 **
   1790 ** Function         bta_ag_send_ring
   1791 **
   1792 ** Description      Send RING result code to peer.
   1793 **
   1794 **
   1795 ** Returns          void
   1796 **
   1797 *******************************************************************************/
   1798 void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
   1799 {
   1800     UNUSED(p_data);
   1801 
   1802 #if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
   1803     tBTA_AG_MULTI_RESULT_CB m_res_cb;
   1804 
   1805     if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
   1806     {
   1807         memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
   1808 
   1809         m_res_cb.num_result = 2;
   1810         AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
   1811         AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
   1812 
   1813         bta_ag_send_multi_result(p_scb, &m_res_cb);
   1814     }
   1815     else
   1816     {
   1817         /* send RING ONLY */
   1818         bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
   1819     }
   1820 #else
   1821     /* send RING */
   1822     bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
   1823 
   1824     /* if HFP and clip enabled and clip data send CLIP */
   1825     if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
   1826     {
   1827         bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
   1828     }
   1829 #endif
   1830 
   1831     /* restart ring timer */
   1832     bta_sys_start_timer(&p_scb->act_timer, BTA_AG_RING_TOUT_EVT, BTA_AG_RING_TOUT);
   1833 }
   1834 
   1835 
   1836