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