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