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 "bt_common.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_TIMEOUT_MS  (5 * 1000)      /* 5 seconds */
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     strlcpy(p, bta_ag_result_tbl[code].p_res, sizeof(buf) - 2);
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         strcpy(p, 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         strcpy(p, 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             strcpy(p, 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                 break;
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         strlcpy(unat_result, 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     strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
854 
855     /* call callback with event */
856     (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
857 }
858 
859 /*******************************************************************************
860 **
861 ** Function         bta_ag_at_hfp_cback
862 **
863 ** Description      AT command processing callback for HFP.
864 **
865 **
866 ** Returns          void
867 **
868 *******************************************************************************/
bta_ag_at_hfp_cback(tBTA_AG_SCB * p_scb,UINT16 cmd,UINT8 arg_type,char * p_arg,INT16 int_arg)869 void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
870                                 char *p_arg, INT16 int_arg)
871 {
872     tBTA_AG_VAL     val;
873     tBTA_AG_EVT   event;
874     tBTA_AG_SCB     *ag_scb;
875     UINT32          i, ind_id;
876     UINT32          bia_masked_out;
877 #if (BTM_WBS_INCLUDED == TRUE )
878     tBTA_AG_PEER_CODEC  codec_type, codec_sent;
879 #endif
880     if (p_arg == NULL)
881     {
882         APPL_TRACE_ERROR("%s: p_arg is null, send error and return", __func__);
883         bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
884         return;
885     }
886 
887     APPL_TRACE_DEBUG("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
888                       int_arg, p_arg);
889 
890     val.hdr.handle = bta_ag_scb_to_idx(p_scb);
891     val.hdr.app_id = p_scb->app_id;
892     val.num = int_arg;
893     bdcpy(val.bd_addr, p_scb->peer_addr);
894     strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
895 
896     event = bta_ag_hfp_cb_evt[cmd];
897 
898     switch (cmd)
899     {
900         case BTA_AG_HF_CMD_A:
901         case BTA_AG_HF_CMD_VGS:
902         case BTA_AG_HF_CMD_VGM:
903         case BTA_AG_HF_CMD_CHUP:
904         case BTA_AG_HF_CMD_CBC:
905             /* send OK */
906             bta_ag_send_ok(p_scb);
907             break;
908 
909         case BTA_AG_HF_CMD_BLDN:
910             /* Do not send OK, App will send error or OK depending on
911             ** last dial number enabled or not */
912             break;
913 
914         case BTA_AG_HF_CMD_D:
915             /* Do not send OK for Dial cmds
916             ** Let application decide whether to send OK or ERROR*/
917 
918             /* if mem dial cmd, make sure string contains only digits */
919             if(p_arg[0] == '>')
920             {
921                 if(!utl_isintstr(p_arg+1))
922                 {
923                     event = 0;
924                     bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
925                 }
926             }
927             else if (p_arg[0] == 'V')   /* ATDV : Dial VoIP Call */
928             {
929                 /* We do not check string. Code will be added later if needed. */
930                 if(!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) && (p_scb->features & BTA_AG_FEAT_VOIP)))
931                 {
932                     event = 0;
933                     bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
934                 }
935             }
936             /* If dial cmd, make sure string contains only dial digits
937             ** Dial digits are 0-9, A-C, *, #, + */
938             else
939             {
940                 if(!utl_isdialstr(p_arg))
941                 {
942                     event = 0;
943                     bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
944                 }
945             }
946             break;
947 
948         case BTA_AG_HF_CMD_CCWA:
949             /* store setting */
950             p_scb->ccwa_enabled = (BOOLEAN) int_arg;
951 
952             /* send OK */
953             bta_ag_send_ok(p_scb);
954             break;
955 
956         case BTA_AG_HF_CMD_CHLD:
957             if (arg_type == BTA_AG_AT_TEST)
958             {
959                 /* don't call callback */
960                 event = 0;
961 
962                 /* send CHLD string */
963                 /* Form string based on supported 1.5 feature */
964                 if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
965                     (p_scb->features & BTA_AG_FEAT_ECC) &&
966                     (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
967                     bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
968                 else
969                     bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
970 
971                 /* send OK */
972                 bta_ag_send_ok(p_scb);
973 
974                 /* if service level conn. not already open, now it's open */
975                 bta_ag_svc_conn_open(p_scb, NULL);
976 
977             }
978             else
979             {
980                 val.idx = bta_ag_parse_chld(p_scb, val.str);
981 
982                 if (val.idx == BTA_AG_INVALID_CHLD)
983                 {
984                     event = 0;
985                     bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
986                     break;
987                 }
988                 if(val.idx && !((p_scb->features & BTA_AG_FEAT_ECC) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC)))
989                 {
990                     /* we do not support ECC, but HF is sending us a CHLD with call index*/
991                     event = 0;
992                     bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
993 
994                 }
995                 else
996                 {
997 
998                 /* If it is swap between calls, set call held indicator to 3(out of valid 0-2)
999                 ** Application will set it back to 1
1000                 ** callheld indicator will be sent across to the peer. */
1001                 if(val.str[0] == '2')
1002                 {
1003                     for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
1004                     {
1005                         if (ag_scb->in_use)
1006                         {
1007                             if((ag_scb->call_ind == BTA_AG_CALL_ACTIVE)
1008                                 && (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
1009                                 ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1;
1010                         }
1011                     }
1012                 }
1013                 }
1014 
1015                 /* Do not send OK. Let app decide after parsing the val str */
1016                 /* bta_ag_send_ok(p_scb); */
1017             }
1018             break;
1019 
1020         case BTA_AG_HF_CMD_CIND:
1021             if (arg_type == BTA_AG_AT_TEST)
1022             {
1023                 /* don't call callback */
1024                 event = 0;
1025 
1026                 /* send CIND string, send OK */
1027                 bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
1028                 bta_ag_send_ok(p_scb);
1029             }
1030             break;
1031 
1032         case BTA_AG_HF_CMD_CLIP:
1033             /* store setting, send OK */
1034             p_scb->clip_enabled = (BOOLEAN) int_arg;
1035             bta_ag_send_ok(p_scb);
1036             break;
1037 
1038         case BTA_AG_HF_CMD_CMER:
1039             /* if parsed ok store setting, send OK */
1040             if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled))
1041             {
1042                 bta_ag_send_ok(p_scb);
1043 
1044                 /* if service level conn. not already open and our features and
1045                 ** peer features do not have 3-way, service level conn. now open
1046                 */
1047                 if (!p_scb->svc_conn &&
1048                     !((p_scb->features & BTA_AG_FEAT_3WAY) && (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)))
1049                 {
1050                     bta_ag_svc_conn_open(p_scb, NULL);
1051                 }
1052             }
1053             else
1054             {
1055                 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1056             }
1057             break;
1058 
1059         case BTA_AG_HF_CMD_VTS:
1060             /* check argument */
1061             if (strlen(p_arg) == 1)
1062             {
1063                 bta_ag_send_ok(p_scb);
1064             }
1065             else
1066             {
1067                 event = 0;
1068                 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1069             }
1070             break;
1071 
1072         case BTA_AG_HF_CMD_BINP:
1073             /* if feature not set don't call callback, send ERROR */
1074             if (!(p_scb->features & BTA_AG_FEAT_VTAG))
1075             {
1076                 event = 0;
1077                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1078             }
1079             break;
1080 
1081         case BTA_AG_HF_CMD_BVRA:
1082             /* if feature not supported don't call callback, send ERROR. App will send OK */
1083             if (!(p_scb->features & BTA_AG_FEAT_VREC))
1084             {
1085                 event = 0;
1086                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1087             }
1088             break;
1089 
1090         case BTA_AG_HF_CMD_BRSF:
1091             /* store peer features */
1092             p_scb->peer_features = (UINT16) int_arg;
1093 
1094             /* send BRSF, send OK */
1095             bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
1096                                (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC));
1097             bta_ag_send_ok(p_scb);
1098             break;
1099 
1100         case BTA_AG_HF_CMD_NREC:
1101             /* if feature send OK, else don't call callback, send ERROR */
1102             if (p_scb->features & BTA_AG_FEAT_ECNR)
1103             {
1104                 bta_ag_send_ok(p_scb);
1105             }
1106             else
1107             {
1108                 event = 0;
1109                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1110             }
1111             break;
1112 
1113         case BTA_AG_HF_CMD_BTRH:
1114             /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
1115             if (p_scb->features & BTA_AG_FEAT_BTRH)
1116             {
1117                 /* If set command; send response and notify app */
1118                 if (arg_type == BTA_AG_AT_SET)
1119                 {
1120                     for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
1121                     {
1122                         if (ag_scb->in_use)
1123                         {
1124                             bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
1125                         }
1126                     }
1127                     bta_ag_send_ok(p_scb);
1128                 }
1129                 else /* Read Command */
1130                 {
1131                     val.num = BTA_AG_BTRH_READ;
1132                 }
1133             }
1134             else
1135             {
1136                 event = 0;
1137                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1138             }
1139             break;
1140 
1141         case BTA_AG_HF_CMD_COPS:
1142             if (arg_type == BTA_AG_AT_SET)
1143             {
1144                 /* don't call callback */
1145                 event = 0;
1146 
1147                 /* send OK */
1148                 bta_ag_send_ok(p_scb);
1149             }
1150             break;
1151 
1152         case BTA_AG_HF_CMD_CMEE:
1153             if (p_scb->features & BTA_AG_FEAT_EXTERR)
1154             {
1155                 /* store setting */
1156                 p_scb->cmee_enabled = (BOOLEAN) int_arg;
1157 
1158                 /* send OK */
1159                 bta_ag_send_ok(p_scb);
1160             }
1161             else
1162             {
1163                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1164             }
1165             /* don't call callback */
1166             event = 0;
1167             break;
1168 
1169         case BTA_AG_HF_CMD_BIA:
1170             /* don't call callback */
1171             event = 0;
1172 
1173             bia_masked_out = p_scb->bia_masked_out;
1174 
1175             /* Parse the indicator mask */
1176             for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); i++, ind_id++)
1177             {
1178                 if (val.str[i] == ',')
1179                     continue;
1180 
1181                 if (val.str[i] == '0')
1182                     bia_masked_out |= ((UINT32)1 << ind_id);
1183                 else if (val.str[i] == '1')
1184                     bia_masked_out &= ~((UINT32)1 << ind_id);
1185                 else
1186                     break;
1187 
1188                 i++;
1189                 if ( (val.str[i] != 0) && (val.str[i] != ',') )
1190                     break;
1191             }
1192             if (val.str[i] == 0)
1193             {
1194                 p_scb->bia_masked_out = bia_masked_out;
1195                 bta_ag_send_ok (p_scb);
1196             }
1197             else
1198                 bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
1199             break;
1200 
1201         case BTA_AG_HF_CMD_CNUM:
1202             break;
1203         case BTA_AG_HF_CMD_CLCC:
1204             if(!(p_scb->features & BTA_AG_FEAT_ECS))
1205             {
1206                 event = 0;
1207                 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1208             }
1209             break;
1210 
1211 #if (BTM_WBS_INCLUDED == TRUE )
1212         case BTA_AG_HF_CMD_BAC:
1213             bta_ag_send_ok(p_scb);
1214 
1215             /* store available codecs from the peer */
1216             if((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC))
1217             {
1218                 p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
1219                 p_scb->codec_updated = TRUE;
1220 
1221                 if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC)
1222                 {
1223                     p_scb->sco_codec = UUID_CODEC_MSBC;
1224                     APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to MSBC");
1225                 }
1226                 else
1227                 {
1228                     p_scb->sco_codec = UUID_CODEC_CVSD;
1229                     APPL_TRACE_DEBUG("Received AT+BAC, updating sco codec to CVSD");
1230                 }
1231                 /* The above logic sets the stack preferred codec based on local and peer codec
1232                 capabilities. This can be overridden by the application depending on its preference
1233                 using the bta_ag_setcodec API. We send the peer_codecs to the application. */
1234                 val.num = p_scb->peer_codecs;
1235                 /* Received BAC while in codec negotiation. */
1236                 if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && (bta_ag_cb.sco.p_curr_scb == p_scb))
1237                 {
1238                     bta_ag_codec_negotiate (p_scb);
1239                 }
1240             }
1241             else
1242             {
1243                 p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
1244                 APPL_TRACE_ERROR("Unexpected CMD:AT+BAC, Codec Negotiation is not supported");
1245             }
1246             break;
1247 
1248         case BTA_AG_HF_CMD_BCS:
1249             bta_ag_send_ok(p_scb);
1250             alarm_cancel(p_scb->codec_negotiation_timer);
1251 
1252             switch(int_arg)
1253             {
1254                 case UUID_CODEC_CVSD:   codec_type = BTA_AG_CODEC_CVSD;     break;
1255                 case UUID_CODEC_MSBC:   codec_type = BTA_AG_CODEC_MSBC;     break;
1256                 default:
1257                     APPL_TRACE_ERROR("Unknown codec_uuid %d", int_arg);
1258                     codec_type = 0xFFFF;
1259                     break;
1260             }
1261 
1262             if (p_scb->codec_fallback)
1263                 codec_sent = BTA_AG_CODEC_CVSD;
1264             else
1265                 codec_sent = p_scb->sco_codec;
1266 
1267             if(codec_type == codec_sent)
1268                 bta_ag_sco_codec_nego(p_scb, TRUE);
1269             else
1270                 bta_ag_sco_codec_nego(p_scb, FALSE);
1271 
1272             /* send final codec info to callback */
1273             val.num = codec_sent;
1274             break;
1275 
1276         case BTA_AG_HF_CMD_BCC:
1277             bta_ag_send_ok(p_scb);
1278             bta_ag_sco_open(p_scb, NULL);
1279             break;
1280 #endif
1281 
1282         default:
1283             bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1284             break;
1285     }
1286 
1287     /* call callback */
1288     if (event != 0)
1289     {
1290         (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &val);
1291     }
1292 }
1293 
1294 /*******************************************************************************
1295 **
1296 ** Function         bta_ag_at_err_cback
1297 **
1298 ** Description      AT command parser error callback.
1299 **
1300 **
1301 ** Returns          void
1302 **
1303 *******************************************************************************/
bta_ag_at_err_cback(tBTA_AG_SCB * p_scb,BOOLEAN unknown,char * p_arg)1304 void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
1305 {
1306     tBTA_AG_VAL     val;
1307 
1308     if(unknown && (!strlen(p_arg)))
1309     {
1310         APPL_TRACE_DEBUG("Empty AT cmd string received");
1311         bta_ag_send_ok(p_scb);
1312         return;
1313     }
1314 
1315     /* if unknown AT command and configured to pass these to app */
1316     if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT))
1317     {
1318         val.hdr.handle = bta_ag_scb_to_idx(p_scb);
1319         val.hdr.app_id = p_scb->app_id;
1320         val.num = 0;
1321         strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
1322         (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
1323     }
1324     else
1325     {
1326         bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1327     }
1328 }
1329 
1330 /*******************************************************************************
1331 **
1332 ** Function         bta_ag_hsp_result
1333 **
1334 ** Description      Handle API result for HSP connections.
1335 **
1336 **
1337 ** Returns          void
1338 **
1339 *******************************************************************************/
bta_ag_hsp_result(tBTA_AG_SCB * p_scb,tBTA_AG_API_RESULT * p_result)1340 void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
1341 {
1342     UINT8 code = bta_ag_trans_result[p_result->result];
1343 
1344     APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result);
1345 
1346     switch(p_result->result)
1347     {
1348         case BTA_AG_SPK_RES:
1349         case BTA_AG_MIC_RES:
1350             bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
1351             break;
1352 
1353         case BTA_AG_IN_CALL_RES:
1354             /* tell sys to stop av if any */
1355             bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1356 
1357             /* if sco already opened or no inband ring send ring now */
1358             if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
1359                 (p_scb->features & BTA_AG_FEAT_NOSCO))
1360             {
1361                 bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
1362             }
1363             /* else open sco, send ring after sco opened */
1364             else
1365             {
1366                 /* HSPv1.2: AG shall not send RING if using in-band ring tone. */
1367                 if (p_scb->hsp_version >= HSP_VERSION_1_2)
1368                     p_scb->post_sco = BTA_AG_POST_SCO_NONE;
1369                 else
1370                     p_scb->post_sco = BTA_AG_POST_SCO_RING;
1371 
1372                 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1373             }
1374             break;
1375 
1376         case BTA_AG_IN_CALL_CONN_RES:
1377         case BTA_AG_OUT_CALL_ORIG_RES:
1378             /* if incoming call connected stop ring timer */
1379             if (p_result->result == BTA_AG_IN_CALL_CONN_RES)
1380             {
1381                 alarm_cancel(p_scb->ring_timer);
1382             }
1383 
1384             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
1385             {
1386                 /* if audio connected to this scb open sco */
1387                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1388                 {
1389                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1390                 }
1391                 /* else if no audio at call close sco */
1392                 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
1393                 {
1394                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1395                 }
1396             }
1397             break;
1398 
1399         case BTA_AG_END_CALL_RES:
1400             alarm_cancel(p_scb->ring_timer);
1401 
1402             /* close sco */
1403             if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1404             {
1405                 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1406             }
1407             else
1408             {
1409                 /* if av got suspended by this call, let it resume. */
1410                 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1411             }
1412             break;
1413 
1414         case BTA_AG_INBAND_RING_RES:
1415             p_scb->inband_enabled = p_result->data.state;
1416             APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
1417             break;
1418 
1419         case BTA_AG_UNAT_RES:
1420             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1421             {
1422                 if (p_result->data.str[0] != 0)
1423                 {
1424                     bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1425                 }
1426 
1427                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1428                     bta_ag_send_ok(p_scb);
1429             }
1430             else
1431             {
1432                 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1433             }
1434             break;
1435 
1436         default:
1437             /* ignore all others */
1438             break;
1439     }
1440 }
1441 
1442 /*******************************************************************************
1443 **
1444 ** Function         bta_ag_hfp_result
1445 **
1446 ** Description      Handle API result for HFP connections.
1447 **
1448 **
1449 ** Returns          void
1450 **
1451 *******************************************************************************/
bta_ag_hfp_result(tBTA_AG_SCB * p_scb,tBTA_AG_API_RESULT * p_result)1452 void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
1453 {
1454     UINT8 code = bta_ag_trans_result[p_result->result];
1455 
1456     APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
1457 
1458     switch(p_result->result)
1459     {
1460         case BTA_AG_SPK_RES:
1461         case BTA_AG_MIC_RES:
1462             bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
1463             break;
1464 
1465         case BTA_AG_IN_CALL_RES:
1466             /* tell sys to stop av if any */
1467             bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1468 
1469             /* store caller id string.
1470              * append type info at the end.
1471              * make sure a valid type info is passed.
1472              * otherwise add 129 as default type */
1473             if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) || (p_result->data.num > BTA_AG_CLIP_TYPE_MAX))
1474             {
1475                 if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
1476                     p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
1477             }
1478 
1479             APPL_TRACE_DEBUG("CLIP type :%d", p_result->data.num);
1480             p_scb->clip[0] = 0;
1481             if (p_result->data.str[0] != 0)
1482                 snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", p_result->data.str, p_result->data.num);
1483 
1484             /* send callsetup indicator */
1485             if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)
1486             {
1487                 /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO close. */
1488                 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
1489             }
1490             else
1491             {
1492                 bta_ag_send_call_inds(p_scb, p_result->result);
1493 
1494                 /* if sco already opened or no inband ring send ring now */
1495                 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
1496                     (p_scb->features & BTA_AG_FEAT_NOSCO))
1497                 {
1498                     bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
1499                 }
1500                 /* else open sco, send ring after sco opened */
1501                 else
1502                 {
1503                     p_scb->post_sco = BTA_AG_POST_SCO_RING;
1504                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1505                 }
1506             }
1507             break;
1508 
1509         case BTA_AG_IN_CALL_CONN_RES:
1510             alarm_cancel(p_scb->ring_timer);
1511 
1512             /* if sco not opened and we need to open it, send indicators first
1513             ** then  open sco.
1514             */
1515             bta_ag_send_call_inds(p_scb, p_result->result);
1516 
1517             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
1518             {
1519                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1520                 {
1521                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1522                 }
1523                 else if ((p_result->data.audio_handle == BTA_AG_HANDLE_NONE) &&
1524                         bta_ag_sco_is_open(p_scb))
1525                 {
1526                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1527                 }
1528             }
1529             break;
1530 
1531         case BTA_AG_IN_CALL_HELD_RES:
1532             alarm_cancel(p_scb->ring_timer);
1533 
1534             bta_ag_send_call_inds(p_scb, p_result->result);
1535 
1536             break;
1537 
1538         case BTA_AG_OUT_CALL_ORIG_RES:
1539             bta_ag_send_call_inds(p_scb, p_result->result);
1540             if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1541                 !(p_scb->features & BTA_AG_FEAT_NOSCO))
1542             {
1543                 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1544             }
1545             break;
1546 
1547         case BTA_AG_OUT_CALL_ALERT_RES:
1548             /* send indicators */
1549             bta_ag_send_call_inds(p_scb, p_result->result);
1550             if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1551                 !(p_scb->features & BTA_AG_FEAT_NOSCO))
1552             {
1553                 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1554             }
1555             break;
1556 
1557         case BTA_AG_MULTI_CALL_RES:
1558             /* open SCO at SLC for this three way call */
1559             APPL_TRACE_DEBUG("Headset Connected in three way call");
1560             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
1561             {
1562                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1563                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1564                 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
1565                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1566             }
1567             break;
1568 
1569         case BTA_AG_OUT_CALL_CONN_RES:
1570             /* send indicators */
1571             bta_ag_send_call_inds(p_scb, p_result->result);
1572 
1573             /* open or close sco */
1574             if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
1575             {
1576                 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1577                 {
1578                     bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1579                 }
1580                 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
1581                 {
1582                     bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1583                 }
1584             }
1585             break;
1586 
1587         case BTA_AG_CALL_CANCEL_RES:
1588             /* send indicators */
1589             bta_ag_send_call_inds(p_scb, p_result->result);
1590             break;
1591 
1592         case BTA_AG_END_CALL_RES:
1593             alarm_cancel(p_scb->ring_timer);
1594 
1595             /* if sco open, close sco then send indicator values */
1596             if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1597             {
1598                 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
1599                 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1600             }
1601             else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL)
1602             {
1603                 /* sco closing for outgoing call because of incoming call */
1604                 /* Send only callsetup end indicator after sco close */
1605                 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
1606             }
1607             else
1608             {
1609                 bta_ag_send_call_inds(p_scb, p_result->result);
1610 
1611                 /* if av got suspended by this call, let it resume. */
1612                 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1613             }
1614             break;
1615 
1616         case BTA_AG_INBAND_RING_RES:
1617             p_scb->inband_enabled = p_result->data.state;
1618             APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
1619             bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
1620             break;
1621 
1622         case BTA_AG_CIND_RES:
1623             /* store local values */
1624             p_scb->call_ind = p_result->data.str[0] - '0';
1625             p_scb->callsetup_ind = p_result->data.str[2] - '0';
1626             p_scb->service_ind = p_result->data.str[4] - '0';
1627             p_scb->signal_ind = p_result->data.str[6] - '0';
1628             p_scb->roam_ind = p_result->data.str[8] - '0';
1629             p_scb->battchg_ind = p_result->data.str[10] - '0';
1630             p_scb->callheld_ind = p_result->data.str[12] - '0';
1631             APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
1632 
1633             bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1634             bta_ag_send_ok(p_scb);
1635             break;
1636 
1637         case BTA_AG_BINP_RES:
1638         case BTA_AG_CNUM_RES:
1639         case BTA_AG_CLCC_RES:
1640         case BTA_AG_COPS_RES:
1641             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1642             {
1643                 if (p_result->data.str[0] != 0)
1644                 {
1645                    bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1646                 }
1647 
1648                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1649                     bta_ag_send_ok(p_scb);
1650             }
1651             else
1652             {
1653                 bta_ag_send_error(p_scb, p_result->data.errcode);
1654             }
1655             break;
1656 
1657 
1658         case BTA_AG_UNAT_RES:
1659             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1660             {
1661                 if (p_result->data.str[0] != 0)
1662                 {
1663                     bta_ag_process_unat_res(p_result->data.str);
1664                     APPL_TRACE_DEBUG("BTA_AG_RES :%s",p_result->data.str);
1665                     bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1666                 }
1667 
1668                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1669                     bta_ag_send_ok(p_scb);
1670             }
1671             else
1672             {
1673                 bta_ag_send_error(p_scb, p_result->data.errcode);
1674             }
1675             break;
1676 
1677         case BTA_AG_CALL_WAIT_RES:
1678             if (p_scb->ccwa_enabled)
1679             {
1680                 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1681             }
1682             bta_ag_send_call_inds(p_scb, p_result->result);
1683             break;
1684 
1685         case BTA_AG_IND_RES:
1686             bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value, FALSE);
1687             break;
1688 
1689         case BTA_AG_BVRA_RES:
1690             bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
1691             break;
1692 
1693         case BTA_AG_BTRH_RES:
1694             if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1695             {
1696                 /* Don't respond to read if not in response & hold state */
1697                 if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
1698                 {
1699                     bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
1700                 }
1701 
1702                 /* In case of a response to a read request we need to send OK */
1703                 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1704                     bta_ag_send_ok(p_scb);
1705             }
1706             else
1707             {
1708                 bta_ag_send_error(p_scb, p_result->data.errcode);
1709             }
1710             break;
1711 
1712        default:
1713             break;
1714     }
1715 }
1716 
1717 
1718 /*******************************************************************************
1719 **
1720 ** Function         bta_ag_result
1721 **
1722 ** Description      Handle API result.
1723 **
1724 **
1725 ** Returns          void
1726 **
1727 *******************************************************************************/
bta_ag_result(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1728 void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1729 {
1730     if (p_scb->conn_service == BTA_AG_HSP)
1731     {
1732         bta_ag_hsp_result(p_scb, &p_data->api_result);
1733     }
1734     else
1735     {
1736         bta_ag_hfp_result(p_scb, &p_data->api_result);
1737     }
1738 }
1739 
1740 #if (BTM_WBS_INCLUDED == TRUE )
1741 /*******************************************************************************
1742 **
1743 ** Function         bta_ag_send_bcs
1744 **
1745 ** Description      Send +BCS AT command to peer.
1746 **
1747 ** Returns          void
1748 **
1749 *******************************************************************************/
bta_ag_send_bcs(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1750 void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1751 {
1752     UINT16 codec_uuid;
1753 
1754     if (p_scb->codec_fallback)
1755     {
1756         codec_uuid = UUID_CODEC_CVSD;
1757     }
1758     else
1759     {
1760         switch(p_scb->sco_codec)
1761         {
1762             case BTA_AG_CODEC_NONE:     codec_uuid = UUID_CODEC_CVSD;   break;
1763             case BTA_AG_CODEC_CVSD:     codec_uuid = UUID_CODEC_CVSD;   break;
1764             case BTA_AG_CODEC_MSBC:     codec_uuid = UUID_CODEC_MSBC;   break;
1765             default:
1766                 APPL_TRACE_ERROR("bta_ag_send_bcs: unknown codec %d, use CVSD", p_scb->sco_codec);
1767                 codec_uuid = UUID_CODEC_CVSD;
1768                 break;
1769         }
1770     }
1771 
1772     /* send +BCS */
1773     APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid);
1774     bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
1775 
1776 }
1777 #endif
1778 
1779 /*******************************************************************************
1780 **
1781 ** Function         bta_ag_send_ring
1782 **
1783 ** Description      Send RING result code to peer.
1784 **
1785 **
1786 ** Returns          void
1787 **
1788 *******************************************************************************/
bta_ag_send_ring(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)1789 void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1790 {
1791     UNUSED(p_data);
1792 
1793 #if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
1794     tBTA_AG_MULTI_RESULT_CB m_res_cb;
1795 
1796     if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
1797     {
1798         memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
1799 
1800         m_res_cb.num_result = 2;
1801         AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
1802         AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
1803 
1804         bta_ag_send_multi_result(p_scb, &m_res_cb);
1805     }
1806     else
1807     {
1808         /* send RING ONLY */
1809         bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
1810     }
1811 #else
1812     /* send RING */
1813     bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
1814 
1815     /* if HFP and clip enabled and clip data send CLIP */
1816     if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
1817     {
1818         bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
1819     }
1820 #endif
1821 
1822     bta_sys_start_timer(p_scb->ring_timer, BTA_AG_RING_TIMEOUT_MS,
1823                         BTA_AG_RING_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
1824 }
1825