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