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