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