blob: 54cd4d3d86e2f65e5ad865fc8257edde3c519f9f [file] [log] [blame]
Hemant Gupta3fe1b492014-04-29 16:23:59 +05301/******************************************************************************
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 */
57typedef 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 */
65typedef 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 */
73enum
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 */
81enum
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 */
112const 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 */
121const 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 */
154typedef 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 */
161enum
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 */
169enum
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) */
198const 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
223const 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 */
230const 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) */
238const 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 */
269const 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 */
295const 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*******************************************************************************/
329static 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*******************************************************************************/
400static 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*******************************************************************************/
464static 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*******************************************************************************/
480static 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*******************************************************************************/
499static 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*******************************************************************************/
585static 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*******************************************************************************/
630static UINT8 bta_ag_parse_chld(tBTA_AG_SCB *p_scb, char *p_s)
631{
632 UINT8 retval = 0;
633 INT16 idx = -1;
634 UNUSED(p_scb);
635
636 if (p_s[1] != 0)
637 {
638 /* p_idxstr++; point to beginning of call number */
639 idx = utl_str2int(&p_s[1]);
640 if (idx != -1 && idx < 255)
641 retval = (UINT8)idx;
642 }
643
644 return (retval);
645}
646
647#if (BTM_WBS_INCLUDED == TRUE )
648/*******************************************************************************
649**
650** Function bta_ag_parse_bac
651**
652** Description Parse AT+BAC parameter string.
653**
654** Returns Returns bitmap of supported codecs.
655**
656*******************************************************************************/
657static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB *p_scb, char *p_s)
658{
659 tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE;
660 UINT16 uuid_codec;
661 BOOLEAN cont = FALSE; /* Continue processing */
662 char *p;
663
664 while(p_s)
665 {
666 /* skip to comma delimiter */
667 for(p = p_s; *p != ',' && *p != 0; p++);
668
669 /* get integre value */
670 if (*p != 0)
671 {
672 *p = 0;
673 cont = TRUE;
674 }
675 else
676 cont = FALSE;
677
678 uuid_codec = utl_str2int(p_s);
679 switch(uuid_codec)
680 {
681 case UUID_CODEC_CVSD: retval |= BTA_AG_CODEC_CVSD; break;
682 case UUID_CODEC_MSBC: retval |= BTA_AG_CODEC_MSBC; break;
683 default:
684 APPL_TRACE_ERROR1("Unknown Codec UUID(%d) received", uuid_codec);
685 return BTA_AG_CODEC_NONE;
686 }
687
688 if (cont)
689 p_s = p + 1;
690 else
691 break;
692 }
693
694 return (retval);
695}
696#endif
697
698/*******************************************************************************
699**
700** Function bta_ag_process_unat_res
701**
702** Description Process the unat response data and remove extra carriage return
703** and line feed
704**
705**
706** Returns void
707**
708*******************************************************************************/
709
710static void bta_ag_process_unat_res(char *unat_result)
711{
712 UINT8 str_leng;
713 UINT8 i = 0;
714 UINT8 j = 0;
715 UINT8 pairs_of_nl_cr;
716 char trim_data[BTA_AG_AT_MAX_LEN];
717
718
719
720 str_leng = strlen(unat_result);
721
722 /* If no extra CR and LF, just return */
723 if(str_leng < 4)
724 return;
725
726 /* Remove the carriage return and left feed */
727 while(unat_result[0] =='\r' && unat_result[1] =='\n'
728 && unat_result[str_leng-2] =='\r' && unat_result[str_leng-1] =='\n')
729 {
730 pairs_of_nl_cr = 1;
731 for (i=0;i<(str_leng-4*pairs_of_nl_cr);i++)
732 {
733 trim_data[j++] = unat_result[i+pairs_of_nl_cr*2];
734 }
735 /* Add EOF */
736 trim_data[j] = '\0';
737 str_leng = str_leng - 4;
738 BCM_STRNCPY_S(unat_result, BTA_AG_AT_MAX_LEN+1, trim_data,str_leng+1);
739 i=0;
740 j=0;
741
742 if(str_leng <4)
743 return;
744
745
746 }
747 return;
748}
749
750
751/*******************************************************************************
752**
753** Function bta_ag_inband_enabled
754**
755** Description Determine whether in-band ring can be used.
756**
757**
758** Returns void
759**
760*******************************************************************************/
761BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb)
762{
763 /* if feature is enabled and no other scbs connected */
764 if (p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb))
765 {
766 return TRUE;
767 }
768 else
769 {
770 return FALSE;
771 }
772}
773
774/*******************************************************************************
775**
776** Function bta_ag_send_call_inds
777**
778** Description Send call and callsetup indicators.
779**
780**
781** Returns void
782**
783*******************************************************************************/
784void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
785{
786 UINT8 call = p_scb->call_ind;
787 UINT8 callsetup;
788
789 /* set new call and callsetup values based on BTA_AgResult */
790 callsetup = bta_ag_callsetup_ind_tbl[result];
791
792 if (result == BTA_AG_END_CALL_RES)
793 {
794 call = BTA_AG_CALL_INACTIVE;
795 }
796 else if (result == BTA_AG_IN_CALL_CONN_RES || result == BTA_AG_OUT_CALL_CONN_RES
797 || result == BTA_AG_IN_CALL_HELD_RES)
798 {
799 call = BTA_AG_CALL_ACTIVE;
800 }
801 else
802 {
803 call = p_scb->call_ind;
804 }
805
806 /* Send indicator function tracks if the values have actually changed */
807 bta_ag_send_ind(p_scb, BTA_AG_IND_CALL, call, FALSE);
808 bta_ag_send_ind(p_scb, BTA_AG_IND_CALLSETUP, callsetup, FALSE);
809}
810
811/*******************************************************************************
812**
813** Function bta_ag_at_hsp_cback
814**
815** Description AT command processing callback for HSP.
816**
817**
818** Returns void
819**
820*******************************************************************************/
821void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
822 char *p_arg, INT16 int_arg)
823{
824 tBTA_AG_VAL val;
825
826 APPL_TRACE_DEBUG4("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
827 int_arg, p_arg);
828
829 /* send OK */
830 bta_ag_send_ok(p_scb);
831
832 val.hdr.handle = bta_ag_scb_to_idx(p_scb);
833 val.hdr.app_id = p_scb->app_id;
834 val.num = (UINT16) int_arg;
835 BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
836 val.str[BTA_AG_AT_MAX_LEN] = 0;
837
838 /* call callback with event */
839 (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
840}
841
842/*******************************************************************************
843**
844** Function bta_ag_at_hfp_cback
845**
846** Description AT command processing callback for HFP.
847**
848**
849** Returns void
850**
851*******************************************************************************/
852void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
853 char *p_arg, INT16 int_arg)
854{
855 tBTA_AG_VAL val;
856 tBTA_AG_EVT event;
857 tBTA_AG_SCB *ag_scb;
858 UINT32 i, ind_id;
859 UINT32 bia_masked_out;
860#if (BTM_WBS_INCLUDED == TRUE )
861 tBTA_AG_PEER_CODEC codec_type, codec_sent;
862#endif
863
864 APPL_TRACE_DEBUG4("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
865 int_arg, p_arg);
866
867 val.hdr.handle = bta_ag_scb_to_idx(p_scb);
868 val.hdr.app_id = p_scb->app_id;
869 val.num = int_arg;
870 BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
871 val.str[BTA_AG_AT_MAX_LEN] = 0;
872
873 event = bta_ag_hfp_cb_evt[cmd];
874
875 switch (cmd)
876 {
877 case BTA_AG_HF_CMD_A:
878 case BTA_AG_HF_CMD_VGS:
879 case BTA_AG_HF_CMD_VGM:
880 case BTA_AG_HF_CMD_CHUP:
881 case BTA_AG_HF_CMD_CBC:
882 /* send OK */
883 bta_ag_send_ok(p_scb);
884 break;
885
886 case BTA_AG_HF_CMD_BLDN:
887 /* Do not send OK, App will send error or OK depending on
888 ** last dial number enabled or not */
889 break;
890
891 case BTA_AG_HF_CMD_D:
892 /* Do not send OK for Dial cmds
893 ** Let application decide whether to send OK or ERROR*/
894
895 /* if mem dial cmd, make sure string contains only digits */
896 if(p_arg[0] == '>')
897 {
898 if(!utl_isintstr(p_arg+1))
899 {
900 event = 0;
901 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
902 }
903 }
904 else if (p_arg[0] == 'V') /* ATDV : Dial VoIP Call */
905 {
906 /* We do not check string. Code will be added later if needed. */
907 if(!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) && (p_scb->features & BTA_AG_FEAT_VOIP)))
908 {
909 event = 0;
910 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
911 }
912 }
913 /* If dial cmd, make sure string contains only dial digits
914 ** Dial digits are 0-9, A-C, *, #, + */
915 else
916 {
917 if(!utl_isdialstr(p_arg))
918 {
919 event = 0;
920 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
921 }
922 }
923 break;
924
925 case BTA_AG_HF_CMD_CCWA:
926 /* store setting */
927 p_scb->ccwa_enabled = (BOOLEAN) int_arg;
928
929 /* send OK */
930 bta_ag_send_ok(p_scb);
931 break;
932
933 case BTA_AG_HF_CMD_CHLD:
934 if (arg_type == BTA_AG_AT_TEST)
935 {
936 /* don't call callback */
937 event = 0;
938
939 /* send CHLD string */
940 /* Form string based on supported 1.5 feature */
941 if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
942 (p_scb->features & BTA_AG_FEAT_ECC) &&
943 (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
944 bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
945 else
946 bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
947
948 /* send OK */
949 bta_ag_send_ok(p_scb);
950
951 /* if service level conn. not already open, now it's open */
952 bta_ag_svc_conn_open(p_scb, NULL);
953
954 }
955 else
956 {
957 val.idx = bta_ag_parse_chld(p_scb, val.str);
958
959 if(val.idx && !((p_scb->features & BTA_AG_FEAT_ECC) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC)))
960 {
961 /* we do not support ECC, but HF is sending us a CHLD with call index*/
962 event = 0;
963 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
964
965 }
966 else
967 {
968
969 /* If it is swap between calls, set call held indicator to 3(out of valid 0-2)
970 ** Application will set it back to 1
971 ** callheld indicator will be sent across to the peer. */
972 if(val.str[0] == '2')
973 {
974 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
975 {
976 if (ag_scb->in_use)
977 {
978 if((ag_scb->call_ind == BTA_AG_CALL_ACTIVE)
979 && (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
980 ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1;
981 }
982 }
983 }
984 }
985
986 /* Do not send OK. Let app decide after parsing the val str */
987 /* bta_ag_send_ok(p_scb); */
988 }
989 break;
990
991 case BTA_AG_HF_CMD_CIND:
992 if (arg_type == BTA_AG_AT_TEST)
993 {
994 /* don't call callback */
995 event = 0;
996
997 /* send CIND string, send OK */
998 bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
999 bta_ag_send_ok(p_scb);
1000 }
1001 break;
1002
1003 case BTA_AG_HF_CMD_CLIP:
1004 /* store setting, send OK */
1005 p_scb->clip_enabled = (BOOLEAN) int_arg;
1006 bta_ag_send_ok(p_scb);
1007 break;
1008
1009 case BTA_AG_HF_CMD_CMER:
1010 /* if parsed ok store setting, send OK */
1011 if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled))
1012 {
1013 bta_ag_send_ok(p_scb);
1014
1015 /* if service level conn. not already open and our features and
1016 ** peer features do not have 3-way, service level conn. now open
1017 */
1018 if (!p_scb->svc_conn &&
1019 !((p_scb->features & BTA_AG_FEAT_3WAY) && (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)))
1020 {
1021 bta_ag_svc_conn_open(p_scb, NULL);
1022 }
1023 }
1024 else
1025 {
1026 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1027 }
1028 break;
1029
1030 case BTA_AG_HF_CMD_VTS:
1031 /* check argument */
1032 if (strlen(p_arg) == 1)
1033 {
1034 bta_ag_send_ok(p_scb);
1035 }
1036 else
1037 {
1038 event = 0;
1039 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1040 }
1041 break;
1042
1043 case BTA_AG_HF_CMD_BINP:
1044 /* if feature not set don't call callback, send ERROR */
1045 if (!(p_scb->features & BTA_AG_FEAT_VTAG))
1046 {
1047 event = 0;
1048 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1049 }
1050 break;
1051
1052 case BTA_AG_HF_CMD_BVRA:
1053 /* if feature not supported don't call callback, send ERROR. App will send OK */
1054 if (!(p_scb->features & BTA_AG_FEAT_VREC))
1055 {
1056 event = 0;
1057 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1058 }
1059 break;
1060
1061 case BTA_AG_HF_CMD_BRSF:
1062 /* store peer features */
1063 p_scb->peer_features = (UINT16) int_arg;
1064
1065 /* send BRSF, send OK */
1066 bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
1067 (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC));
1068 bta_ag_send_ok(p_scb);
1069 break;
1070
1071 case BTA_AG_HF_CMD_NREC:
1072 /* if feature send OK, else don't call callback, send ERROR */
1073 if (p_scb->features & BTA_AG_FEAT_ECNR)
1074 {
1075 bta_ag_send_ok(p_scb);
1076 }
1077 else
1078 {
1079 event = 0;
1080 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1081 }
1082 break;
1083
1084 case BTA_AG_HF_CMD_BTRH:
1085 /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
1086 if (p_scb->features & BTA_AG_FEAT_BTRH)
1087 {
1088 /* If set command; send response and notify app */
1089 if (arg_type == BTA_AG_AT_SET)
1090 {
1091 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
1092 {
1093 if (ag_scb->in_use)
1094 {
1095 bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
1096 }
1097 }
1098 bta_ag_send_ok(p_scb);
1099 }
1100 else /* Read Command */
1101 {
1102 val.num = BTA_AG_BTRH_READ;
1103 }
1104 }
1105 else
1106 {
1107 event = 0;
1108 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1109 }
1110 break;
1111
1112 case BTA_AG_HF_CMD_COPS:
1113 if (arg_type == BTA_AG_AT_SET)
1114 {
1115 /* don't call callback */
1116 event = 0;
1117
1118 /* send OK */
1119 bta_ag_send_ok(p_scb);
1120 }
1121 break;
1122
1123 case BTA_AG_HF_CMD_CMEE:
1124 if (p_scb->features & BTA_AG_FEAT_EXTERR)
1125 {
1126 /* store setting */
1127 p_scb->cmee_enabled = (BOOLEAN) int_arg;
1128
1129 /* send OK */
1130 bta_ag_send_ok(p_scb);
1131 }
1132 else
1133 {
1134 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1135 }
1136 /* don't call callback */
1137 event = 0;
1138 break;
1139
1140 case BTA_AG_HF_CMD_BIA:
1141 /* don't call callback */
1142 event = 0;
1143
1144 bia_masked_out = p_scb->bia_masked_out;
1145
1146 /* Parse the indicator mask */
1147 for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); i++, ind_id++)
1148 {
1149 if (val.str[i] == ',')
1150 continue;
1151
1152 if (val.str[i] == '0')
1153 bia_masked_out |= ((UINT32)1 << ind_id);
1154 else if (val.str[i] == '1')
1155 bia_masked_out &= ~((UINT32)1 << ind_id);
1156 else
1157 break;
1158
1159 i++;
1160 if ( (val.str[i] != 0) && (val.str[i] != ',') )
1161 break;
1162 }
1163 if (val.str[i] == 0)
1164 {
1165 p_scb->bia_masked_out = bia_masked_out;
1166 bta_ag_send_ok (p_scb);
1167 }
1168 else
1169 bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
1170 break;
1171
1172 case BTA_AG_HF_CMD_CNUM:
1173 break;
1174 case BTA_AG_HF_CMD_CLCC:
1175 if(!(p_scb->features & BTA_AG_FEAT_ECS))
1176 {
1177 event = 0;
1178 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1179 }
1180 break;
1181
1182#if (BTM_WBS_INCLUDED == TRUE )
1183 case BTA_AG_HF_CMD_BAC:
1184 bta_ag_send_ok(p_scb);
1185
1186 /* store available codecs from the peer */
1187 if((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC))
1188 {
1189 p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
1190 p_scb->codec_updated = TRUE;
1191
1192 if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC)
1193 {
1194 p_scb->sco_codec = UUID_CODEC_MSBC;
1195 APPL_TRACE_DEBUG0("Received AT+BAC, updating sco codec to MSBC");
1196 }
1197 else
1198 {
1199 p_scb->sco_codec = UUID_CODEC_CVSD;
1200 APPL_TRACE_DEBUG0("Received AT+BAC, updating sco codec to CVSD");
1201 }
1202
1203 /* Received BAC while in codec negotiation. */
1204 if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && (bta_ag_cb.sco.p_curr_scb == p_scb))
1205 {
1206 bta_ag_codec_negotiate (p_scb);
1207 }
1208 }
1209 else
1210 {
1211 p_scb->peer_codecs = BTA_AG_CODEC_NONE;
1212 APPL_TRACE_ERROR0("Unexpected CMD:AT+BAC, Codec Negotiation is not supported");
1213 }
1214 break;
1215
1216 case BTA_AG_HF_CMD_BCS:
1217 /* stop cn timer */
1218 bta_sys_stop_timer(&p_scb->cn_timer);
1219
1220 switch(int_arg)
1221 {
1222 case UUID_CODEC_CVSD: codec_type = BTA_AG_CODEC_CVSD; break;
1223 case UUID_CODEC_MSBC: codec_type = BTA_AG_CODEC_MSBC; break;
1224 default:
1225 APPL_TRACE_ERROR1("Unknown codec_uuid %d", int_arg);
1226 codec_type = 0xFFFF;
1227 break;
1228 }
1229
1230 if (p_scb->codec_fallback)
1231 codec_sent = BTA_AG_CODEC_CVSD;
1232 else
1233 codec_sent = p_scb->sco_codec;
1234
1235 if(codec_type == codec_sent)
1236 bta_ag_sco_codec_nego(p_scb, TRUE);
1237 else
1238 bta_ag_sco_codec_nego(p_scb, FALSE);
1239
1240 bta_ag_send_ok(p_scb);
1241 break;
1242
1243 case BTA_AG_HF_CMD_BCC:
1244 bta_ag_send_ok(p_scb);
1245 bta_ag_sco_open(p_scb, NULL);
1246 break;
1247#endif
1248
1249 default:
1250 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1251 break;
1252 }
1253
1254 /* call callback */
1255 if (event != 0)
1256 {
1257 (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &val);
1258 }
1259}
1260
1261/*******************************************************************************
1262**
1263** Function bta_ag_at_err_cback
1264**
1265** Description AT command parser error callback.
1266**
1267**
1268** Returns void
1269**
1270*******************************************************************************/
1271void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
1272{
1273 tBTA_AG_VAL val;
1274
1275 if(unknown && (!strlen(p_arg)))
1276 {
1277 APPL_TRACE_DEBUG0("Empty AT cmd string received");
1278 bta_ag_send_ok(p_scb);
1279 return;
1280 }
1281
1282 /* if unknown AT command and configured to pass these to app */
1283 if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT))
1284 {
1285 val.hdr.handle = bta_ag_scb_to_idx(p_scb);
1286 val.hdr.app_id = p_scb->app_id;
1287 val.num = 0;
1288 BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
1289 val.str[BTA_AG_AT_MAX_LEN] = 0;
1290 (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
1291 }
1292 else
1293 {
1294 bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
1295 }
1296}
1297
1298/*******************************************************************************
1299**
1300** Function bta_ag_hsp_result
1301**
1302** Description Handle API result for HSP connections.
1303**
1304**
1305** Returns void
1306**
1307*******************************************************************************/
1308void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
1309{
1310 UINT8 code = bta_ag_trans_result[p_result->result];
1311
1312 APPL_TRACE_DEBUG1("bta_ag_hsp_result : res = %d", p_result->result);
1313
1314 switch(p_result->result)
1315 {
1316 case BTA_AG_SPK_RES:
1317 case BTA_AG_MIC_RES:
1318 bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
1319 break;
1320
1321 case BTA_AG_IN_CALL_RES:
1322 /* tell sys to stop av if any */
1323 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1324
1325 /* if sco already opened or no inband ring send ring now */
1326 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
1327 (p_scb->features & BTA_AG_FEAT_NOSCO))
1328 {
1329 bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
1330 }
1331 /* else open sco, send ring after sco opened */
1332 else
1333 {
1334 /* HSPv1.2: AG shall not send RING if using in-band ring tone. */
1335 if (p_scb->hsp_version >= HSP_VERSION_1_2)
1336 p_scb->post_sco = BTA_AG_POST_SCO_NONE;
1337 else
1338 p_scb->post_sco = BTA_AG_POST_SCO_RING;
1339
1340 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1341 }
1342 break;
1343
1344 case BTA_AG_IN_CALL_CONN_RES:
1345 case BTA_AG_OUT_CALL_ORIG_RES:
1346 /* if incoming call connected stop ring timer */
1347 if (p_result->result == BTA_AG_IN_CALL_CONN_RES)
1348 {
1349 bta_sys_stop_timer(&p_scb->act_timer);
1350 }
1351
1352 if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
1353 {
1354 /* if audio connected to this scb open sco */
1355 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1356 {
1357 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1358 }
1359 /* else if no audio at call close sco */
1360 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
1361 {
1362 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1363 }
1364 }
1365 break;
1366
1367 case BTA_AG_END_CALL_RES:
1368 /* stop ring timer */
1369 bta_sys_stop_timer(&p_scb->act_timer);
1370
1371 /* close sco */
1372 if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1373 {
1374 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1375 }
1376 else
1377 {
1378 /* if av got suspended by this call, let it resume. */
1379 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1380 }
1381 break;
1382
1383 case BTA_AG_INBAND_RING_RES:
1384 p_scb->inband_enabled = p_result->data.state;
1385 APPL_TRACE_DEBUG1("inband_enabled set to %d", p_scb->inband_enabled);
1386 break;
1387
1388 case BTA_AG_UNAT_RES:
1389 if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1390 {
1391 if (p_result->data.str[0] != 0)
1392 {
1393 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1394 }
1395
1396 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1397 bta_ag_send_ok(p_scb);
1398 }
1399 else
1400 {
1401 bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
1402 }
1403 break;
1404
1405 default:
1406 /* ignore all others */
1407 break;
1408 }
1409}
1410
1411/*******************************************************************************
1412**
1413** Function bta_ag_hfp_result
1414**
1415** Description Handle API result for HFP connections.
1416**
1417**
1418** Returns void
1419**
1420*******************************************************************************/
1421void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
1422{
1423 UINT8 code = bta_ag_trans_result[p_result->result];
1424
1425 APPL_TRACE_DEBUG1("bta_ag_hfp_result : res = %d", p_result->result);
1426
1427 switch(p_result->result)
1428 {
1429 case BTA_AG_SPK_RES:
1430 case BTA_AG_MIC_RES:
1431 bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
1432 break;
1433
1434 case BTA_AG_IN_CALL_RES:
1435 /* tell sys to stop av if any */
1436 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1437
1438 /* store caller id string.
1439 * append type info at the end.
1440 * make sure a valid type info is passed.
1441 * otherwise add 129 as default type */
1442 if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) || (p_result->data.num > BTA_AG_CLIP_TYPE_MAX))
1443 {
1444 if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
1445 p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
1446 }
1447
1448 APPL_TRACE_DEBUG1("CLIP type :%d", p_result->data.num);
1449 p_scb->clip[0] = 0;
1450 if (p_result->data.str[0] != 0)
1451 sprintf(p_scb->clip,"%s,%d", p_result->data.str, p_result->data.num);
1452
1453 /* send callsetup indicator */
1454 if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)
1455 {
1456 /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO close. */
1457 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
1458 }
1459 else
1460 {
1461 bta_ag_send_call_inds(p_scb, p_result->result);
1462
1463 /* if sco already opened or no inband ring send ring now */
1464 if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
1465 (p_scb->features & BTA_AG_FEAT_NOSCO))
1466 {
1467 bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
1468 }
1469 /* else open sco, send ring after sco opened */
1470 else
1471 {
1472 p_scb->post_sco = BTA_AG_POST_SCO_RING;
1473 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1474 }
1475 }
1476 break;
1477
1478 case BTA_AG_IN_CALL_CONN_RES:
1479 /* stop ring timer */
1480 bta_sys_stop_timer(&p_scb->act_timer);
1481
1482 /* if sco not opened and we need to open it, open sco first
1483 ** then send indicators
1484 */
1485 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1486 !bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1487 {
1488 p_scb->post_sco = BTA_AG_POST_SCO_CALL_CONN;
1489 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1490 }
1491 /* else if sco open and we need to close it, close sco first
1492 ** then send indicators
1493 */
1494 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
1495 bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1496 {
1497 p_scb->post_sco = BTA_AG_POST_SCO_CALL_CONN;
1498 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1499 }
1500 /* else send indicators now */
1501 else
1502 {
1503 bta_ag_send_call_inds(p_scb, p_result->result);
1504 }
1505 break;
1506
1507 case BTA_AG_IN_CALL_HELD_RES:
1508 /* stop ring timer */
1509 bta_sys_stop_timer(&p_scb->act_timer);
1510
1511 bta_ag_send_call_inds(p_scb, p_result->result);
1512
1513 break;
1514
1515 case BTA_AG_OUT_CALL_ORIG_RES:
1516 /* if sco open and we need to close it, close sco first
1517 ** then send indicators; else send indicators now
1518 */
1519 if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
1520 bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1521 {
1522 p_scb->post_sco = BTA_AG_POST_SCO_CALL_ORIG;
1523 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1524 }
1525 else
1526 {
1527 bta_ag_send_call_inds(p_scb, p_result->result);
1528 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1529 !(p_scb->features & BTA_AG_FEAT_NOSCO))
1530 {
1531 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1532 }
1533 }
1534 break;
1535
1536 case BTA_AG_OUT_CALL_ALERT_RES:
1537 /* send indicators */
1538 bta_ag_send_call_inds(p_scb, p_result->result);
1539 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
1540 !(p_scb->features & BTA_AG_FEAT_NOSCO))
1541 {
1542 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1543 }
1544 break;
1545
1546 case BTA_AG_OUT_CALL_CONN_RES:
1547 /* send indicators */
1548 bta_ag_send_call_inds(p_scb, p_result->result);
1549
1550 /* open or close sco */
1551 if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
1552 {
1553 if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
1554 {
1555 bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
1556 }
1557 else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
1558 {
1559 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1560 }
1561 }
1562 break;
1563
1564 case BTA_AG_CALL_CANCEL_RES:
1565 /* send indicators */
1566 bta_ag_send_call_inds(p_scb, p_result->result);
1567 break;
1568
1569 case BTA_AG_END_CALL_RES:
1570 /* stop ring timer */
1571 bta_sys_stop_timer(&p_scb->act_timer);
1572
1573 /* if sco open, close sco then send indicator values */
1574 if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
1575 {
1576 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
1577 bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
1578 }
1579 else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL)
1580 {
1581 /* sco closing for outgoing call because of incoming call */
1582 /* Send only callsetup end indicator after sco close */
1583 p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
1584 }
1585 else
1586 {
1587 bta_ag_send_call_inds(p_scb, p_result->result);
1588
1589 /* if av got suspended by this call, let it resume. */
1590 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1591 }
1592 break;
1593
1594 case BTA_AG_INBAND_RING_RES:
1595 p_scb->inband_enabled = p_result->data.state;
1596 APPL_TRACE_DEBUG1("inband_enabled set to %d", p_scb->inband_enabled);
1597 bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
1598 break;
1599
1600 case BTA_AG_CIND_RES:
1601 /* store local values */
1602 p_scb->call_ind = p_result->data.str[0] - '0';
1603 p_scb->callsetup_ind = p_result->data.str[2] - '0';
1604 p_scb->service_ind = p_result->data.str[4] - '0';
1605 p_scb->signal_ind = p_result->data.str[6] - '0';
1606 p_scb->roam_ind = p_result->data.str[8] - '0';
1607 p_scb->battchg_ind = p_result->data.str[10] - '0';
1608 APPL_TRACE_DEBUG2("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
1609
1610 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1611 bta_ag_send_ok(p_scb);
1612 break;
1613
1614 case BTA_AG_BINP_RES:
1615 case BTA_AG_CNUM_RES:
1616 case BTA_AG_CLCC_RES:
1617 case BTA_AG_COPS_RES:
1618 if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1619 {
1620 if (p_result->data.str[0] != 0)
1621 {
1622 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1623 }
1624
1625 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1626 bta_ag_send_ok(p_scb);
1627 }
1628 else
1629 {
1630 bta_ag_send_error(p_scb, p_result->data.errcode);
1631 }
1632 break;
1633
1634
1635 case BTA_AG_UNAT_RES:
1636 if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1637 {
1638 if (p_result->data.str[0] != 0)
1639 {
1640 bta_ag_process_unat_res(p_result->data.str);
1641 APPL_TRACE_DEBUG1("BTA_AG_RES :%s",p_result->data.str);
1642 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1643 }
1644
1645 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1646 bta_ag_send_ok(p_scb);
1647 }
1648 else
1649 {
1650 bta_ag_send_error(p_scb, p_result->data.errcode);
1651 }
1652 break;
1653
1654 case BTA_AG_CALL_WAIT_RES:
1655 if (p_scb->ccwa_enabled)
1656 {
1657 bta_ag_send_result(p_scb, code, p_result->data.str, 0);
1658 }
1659 bta_ag_send_call_inds(p_scb, p_result->result);
1660 break;
1661
1662 case BTA_AG_IND_RES:
1663 bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value, FALSE);
1664 break;
1665
1666 case BTA_AG_BVRA_RES:
1667 bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
1668 break;
1669
1670 case BTA_AG_BTRH_RES:
1671 if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
1672 {
1673 /* Don't respond to read if not in response & hold state */
1674 if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
1675 {
1676 bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
1677 }
1678
1679 /* In case of a response to a read request we need to send OK */
1680 if (p_result->data.ok_flag == BTA_AG_OK_DONE)
1681 bta_ag_send_ok(p_scb);
1682 }
1683 else
1684 {
1685 bta_ag_send_error(p_scb, p_result->data.errcode);
1686 }
1687 break;
1688
1689 default:
1690 break;
1691 }
1692}
1693
1694
1695/*******************************************************************************
1696**
1697** Function bta_ag_result
1698**
1699** Description Handle API result.
1700**
1701**
1702** Returns void
1703**
1704*******************************************************************************/
1705void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1706{
1707 if (p_scb->conn_service == BTA_AG_HSP)
1708 {
1709 bta_ag_hsp_result(p_scb, &p_data->api_result);
1710 }
1711 else
1712 {
1713 bta_ag_hfp_result(p_scb, &p_data->api_result);
1714 }
1715}
1716
1717/*******************************************************************************
1718**
1719** Function bta_ag_setcodec
1720**
1721** Description Handle API SetCodec
1722**
1723**
1724** Returns void
1725**
1726*******************************************************************************/
1727void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1728{
1729#if (BTM_WBS_INCLUDED == TRUE )
1730 tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
1731
1732 /* Check if the requested codec type is valid */
1733 if((codec_type != BTA_AG_CODEC_NONE) &&
1734 (codec_type != BTA_AG_CODEC_CVSD) &&
1735 (codec_type != BTA_AG_CODEC_MSBC))
1736 {
1737 APPL_TRACE_ERROR1("bta_ag_setcodec error: unsupported codec type %d", codec_type);
1738 return;
1739 }
1740
1741 if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || (codec_type == BTA_AG_CODEC_CVSD))
1742 {
1743 p_scb->sco_codec = codec_type;
1744 p_scb->codec_updated = TRUE;
1745 APPL_TRACE_DEBUG1("bta_ag_setcodec: Updated codec type %d", codec_type);
1746 }
1747 else
1748 {
1749 APPL_TRACE_ERROR1("bta_ag_setcodec error: unsupported codec type %d", codec_type);
1750 }
1751#else
1752 UNUSED(p_scb);
1753 UNUSED(p_data);
1754#endif
1755}
1756
1757
1758#if (BTM_WBS_INCLUDED == TRUE )
1759/*******************************************************************************
1760**
1761** Function bta_ag_send_bcs
1762**
1763** Description Send +BCS AT command to peer.
1764**
1765** Returns void
1766**
1767*******************************************************************************/
1768void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1769{
1770 UINT16 codec_uuid;
1771
1772 if (p_scb->codec_fallback)
1773 {
1774 codec_uuid = UUID_CODEC_CVSD;
1775 }
1776 else
1777 {
1778 switch(p_scb->sco_codec)
1779 {
1780 case BTA_AG_CODEC_NONE: codec_uuid = UUID_CODEC_CVSD; break;
1781 case BTA_AG_CODEC_CVSD: codec_uuid = UUID_CODEC_CVSD; break;
1782 case BTA_AG_CODEC_MSBC: codec_uuid = UUID_CODEC_MSBC; break;
1783 default:
1784 APPL_TRACE_ERROR1("bta_ag_send_bcs: unknown codec %d, use CVSD", p_scb->sco_codec);
1785 codec_uuid = UUID_CODEC_CVSD;
1786 break;
1787 }
1788 }
1789
1790 /* send +BCS */
1791 bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
1792
1793}
1794#endif
1795
1796/*******************************************************************************
1797**
1798** Function bta_ag_send_ring
1799**
1800** Description Send RING result code to peer.
1801**
1802**
1803** Returns void
1804**
1805*******************************************************************************/
1806void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1807{
1808 UNUSED(p_data);
1809
1810#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
1811 tBTA_AG_MULTI_RESULT_CB m_res_cb;
1812
1813 if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
1814 {
1815 memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
1816
1817 m_res_cb.num_result = 2;
1818 AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
1819 AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
1820
1821 bta_ag_send_multi_result(p_scb, &m_res_cb);
1822 }
1823 else
1824 {
1825 /* send RING ONLY */
1826 bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
1827 }
1828#else
1829 /* send RING */
1830 bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
1831
1832 /* if HFP and clip enabled and clip data send CLIP */
1833 if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
1834 {
1835 bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
1836 }
1837#endif
1838
1839 /* restart ring timer */
1840 bta_sys_start_timer(&p_scb->act_timer, BTA_AG_RING_TOUT_EVT, BTA_AG_RING_TOUT);
1841}
1842
1843