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