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