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