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