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