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