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