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