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