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