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