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