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