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