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