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