1 /******************************************************************************
2  *
3  *  Copyright (c) 2014 The Android Open Source Project
4  *  Copyright (C) 2003-2012 Broadcom Corporation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 // #include <errno.h>
20 #include <string.h>
21 #include <stdio.h>
22 
23 #include "bta/bta_hf_client_api.h"
24 #include "bta_hf_client_int.h"
25 #include "stack/port_api.h"
26 #include "osi/allocator.h"
27 
28 #if (BTA_HF_INCLUDED == TRUE)
29 /* Uncomment to enable AT traffic dumping */
30 /* #define BTA_HF_CLIENT_AT_DUMP 1 */
31 
32 /* minimum length of AT event */
33 #define BTA_HF_CLIENT_AT_EVENT_MIN_LEN 3
34 
35 /* timeout for AT response */
36 #define BTA_HF_CLIENT_AT_TIMEOUT 29989
37 
38 /* timeout for AT hold timer */
39 #define BTA_HF_CLIENT_AT_HOLD_TIMEOUT 41
40 
41 /******************************************************************************
42 **
43 **          DATA TYPES AND CONTAINERS
44 **
45 *******************************************************************************/
46 /* BRSF: store received values here */
47 extern tBTA_HF_CLIENT_CB  bta_hf_client_cb;
48 
49 /******************************************************************************
50 **       SUPPORTED EVENT MESSAGES
51 *******************************************************************************/
52 
53 /* CIND: supported indicator names */
54 #define BTA_HF_CLIENT_INDICATOR_BATTERYCHG  "battchg"
55 #define BTA_HF_CLIENT_INDICATOR_SIGNAL      "signal"
56 #define BTA_HF_CLIENT_INDICATOR_SERVICE     "service"
57 #define BTA_HF_CLIENT_INDICATOR_CALL        "call"
58 #define BTA_HF_CLIENT_INDICATOR_ROAM        "roam"
59 #define BTA_HF_CLIENT_INDICATOR_CALLSETUP   "callsetup"
60 #define BTA_HF_CLIENT_INDICATOR_CALLHELD    "callheld"
61 
62 #define MIN(a, b) \
63     ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); (_a < _b) ? _a : _b; })
64 
65 /* CIND: represents each indicators boundaries */
66 typedef struct {
67     char *name;
68     UINT8 min;
69     UINT8 max;
70     UINT8 namelen;
71 } tBTA_HF_CLIENT_INDICATOR;
72 
73 #define BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT 7
74 
75 /* CIND: storage room for indicators value range and their statuses */
76 static const tBTA_HF_CLIENT_INDICATOR bta_hf_client_indicators[BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT] = {
77     /* name                                | min | max | name length - used by parser */
78     {BTA_HF_CLIENT_INDICATOR_CALL,           0,   1,    sizeof(BTA_HF_CLIENT_INDICATOR_CALL)},
79     {BTA_HF_CLIENT_INDICATOR_CALLSETUP,      0,   3,    sizeof(BTA_HF_CLIENT_INDICATOR_CALLSETUP)},
80     {BTA_HF_CLIENT_INDICATOR_SERVICE,        0,   1,    sizeof(BTA_HF_CLIENT_INDICATOR_SERVICE)},
81     {BTA_HF_CLIENT_INDICATOR_SIGNAL,         0,   5,    sizeof(BTA_HF_CLIENT_INDICATOR_SIGNAL)},
82     {BTA_HF_CLIENT_INDICATOR_ROAM,           0,   1,    sizeof(BTA_HF_CLIENT_INDICATOR_ROAM)},
83     {BTA_HF_CLIENT_INDICATOR_BATTERYCHG,     0,   5,    sizeof(BTA_HF_CLIENT_INDICATOR_BATTERYCHG)},
84     {BTA_HF_CLIENT_INDICATOR_CALLHELD,       0,   2,    sizeof(BTA_HF_CLIENT_INDICATOR_CALLHELD)}
85 };
86 
87 /* +VGM/+VGS - gain min/max values  */
88 #define BTA_HF_CLIENT_VGS_MIN   0
89 #define BTA_HF_CLIENT_VGS_MAX  15
90 #define BTA_HF_CLIENT_VGM_MIN   0
91 #define BTA_HF_CLIENT_VGM_MAX  15
92 
93 UINT32 service_index = 0;
94 BOOLEAN service_availability = TRUE;
95 /* helper functions for handling AT commands queueing */
96 
97 static void bta_hf_client_handle_ok(void);
98 
bta_hf_client_clear_queued_at(void)99 static void bta_hf_client_clear_queued_at(void)
100 {
101     tBTA_HF_CLIENT_AT_QCMD *cur = bta_hf_client_cb.scb.at_cb.queued_cmd;
102     tBTA_HF_CLIENT_AT_QCMD *next;
103 
104     while (cur != NULL) {
105         next = cur->next;
106         osi_free(cur);
107         cur = next;
108     }
109 
110     bta_hf_client_cb.scb.at_cb.queued_cmd = NULL;
111 }
112 
bta_hf_client_queue_at(tBTA_HF_CLIENT_AT_CMD cmd,const char * buf,UINT16 buf_len)113 static void bta_hf_client_queue_at(tBTA_HF_CLIENT_AT_CMD cmd, const char *buf, UINT16 buf_len)
114 {
115     tBTA_HF_CLIENT_AT_QCMD *new_cmd;
116 
117     APPL_TRACE_DEBUG("%s", __FUNCTION__);
118 
119     if ((new_cmd = (tBTA_HF_CLIENT_AT_QCMD *) osi_malloc(sizeof(tBTA_HF_CLIENT_AT_QCMD))) != NULL) {
120         new_cmd->cmd = cmd;
121         new_cmd->buf_len = buf_len;
122         new_cmd->next = NULL;
123         memcpy(new_cmd->buf, buf, buf_len);
124 
125         if (bta_hf_client_cb.scb.at_cb.queued_cmd != NULL) {
126             tBTA_HF_CLIENT_AT_QCMD *qcmd = bta_hf_client_cb.scb.at_cb.queued_cmd;
127 
128             while (qcmd->next != NULL) {
129                 qcmd = qcmd->next;
130             }
131 
132             qcmd->next = new_cmd;
133         } else {
134             bta_hf_client_cb.scb.at_cb.queued_cmd = new_cmd;
135         }
136     }
137 }
138 
bta_hf_client_at_resp_timer_cback(TIMER_LIST_ENT * p_tle)139 static void bta_hf_client_at_resp_timer_cback (TIMER_LIST_ENT *p_tle)
140 {
141     if (p_tle) {
142         bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE;
143 
144         APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting");
145 
146         bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
147     }
148 }
149 
bta_hf_client_stop_at_resp_timer(void)150 static void bta_hf_client_stop_at_resp_timer(void)
151 {
152     if (bta_hf_client_cb.scb.at_cb.resp_timer_on) {
153         bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE;
154         bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.resp_timer);
155     }
156 }
157 
bta_hf_client_free_at_resp_timer(void)158 static void bta_hf_client_free_at_resp_timer(void)
159 {
160     bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE;
161     bta_sys_free_timer (&bta_hf_client_cb.scb.at_cb.resp_timer);
162 }
163 
bta_hf_client_start_at_resp_timer(void)164 static void bta_hf_client_start_at_resp_timer(void)
165 {
166     if (bta_hf_client_cb.scb.at_cb.resp_timer_on) {
167         bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.resp_timer);
168     }
169 
170     bta_hf_client_cb.scb.at_cb.resp_timer.p_cback = (TIMER_CBACK *)&bta_hf_client_at_resp_timer_cback;
171     bta_sys_start_timer(&bta_hf_client_cb.scb.at_cb.resp_timer, 0, BTA_HF_CLIENT_AT_TIMEOUT);
172     bta_hf_client_cb.scb.at_cb.resp_timer_on = TRUE;
173 }
174 
bta_hf_client_send_at(tBTA_HF_CLIENT_AT_CMD cmd,char * buf,UINT16 buf_len)175 static void bta_hf_client_send_at(tBTA_HF_CLIENT_AT_CMD cmd, char *buf, UINT16 buf_len)
176 {
177     if ((bta_hf_client_cb.scb.at_cb.current_cmd == BTA_HF_CLIENT_AT_NONE ||
178             bta_hf_client_cb.scb.svc_conn == FALSE) &&
179             bta_hf_client_cb.scb.at_cb.hold_timer_on == FALSE) {
180         UINT16  len;
181 
182 #ifdef BTA_HF_CLIENT_AT_DUMP
183         APPL_TRACE_DEBUG("%s %.*s", __FUNCTION__, buf_len - 1, buf);
184 #endif
185 
186         bta_hf_client_cb.scb.at_cb.current_cmd = cmd;
187         /* Generate fake responses for these because they won't reliably work */
188         if (!service_availability &&
189                 (cmd == BTA_HF_CLIENT_AT_CNUM || cmd == BTA_HF_CLIENT_AT_COPS)) {
190             APPL_TRACE_WARNING("%s: No service, skipping %d command", __FUNCTION__, cmd);
191             bta_hf_client_handle_ok();
192             return;
193         }
194 
195         PORT_WriteData(bta_hf_client_cb.scb.conn_handle, buf, buf_len, &len);
196 
197         bta_hf_client_start_at_resp_timer();
198 
199         return;
200     }
201 
202     bta_hf_client_queue_at(cmd, buf, buf_len);
203 }
204 
bta_hf_client_send_queued_at(void)205 static void bta_hf_client_send_queued_at(void)
206 {
207     tBTA_HF_CLIENT_AT_QCMD *cur = bta_hf_client_cb.scb.at_cb.queued_cmd;
208 
209     APPL_TRACE_DEBUG("%s", __FUNCTION__);
210 
211     if (cur != NULL) {
212         bta_hf_client_cb.scb.at_cb.queued_cmd = cur->next;
213 
214         bta_hf_client_send_at(cur->cmd, cur->buf, cur->buf_len);
215 
216         osi_free(cur);
217     }
218 }
219 
bta_hf_client_at_hold_timer_cback(TIMER_LIST_ENT * p_tle)220 static void bta_hf_client_at_hold_timer_cback(TIMER_LIST_ENT *p_tle)
221 {
222     APPL_TRACE_DEBUG("%s", __FUNCTION__);
223 
224     if (p_tle) {
225         bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE;
226         bta_hf_client_send_queued_at();
227     }
228 }
229 
bta_hf_client_stop_at_hold_timer(void)230 static void bta_hf_client_stop_at_hold_timer(void)
231 {
232     APPL_TRACE_DEBUG("%s", __FUNCTION__);
233 
234     if (bta_hf_client_cb.scb.at_cb.hold_timer_on) {
235         bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE;
236         bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.hold_timer);
237     }
238 }
239 
bta_hf_client_free_at_hold_timer(void)240 static void bta_hf_client_free_at_hold_timer(void)
241 {
242     APPL_TRACE_DEBUG("%s", __FUNCTION__);
243 
244     bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE;
245     bta_sys_free_timer(&bta_hf_client_cb.scb.at_cb.hold_timer);
246 }
247 
bta_hf_client_start_at_hold_timer(void)248 static void bta_hf_client_start_at_hold_timer(void)
249 {
250     TIMER_LIST_ENT *timer = &bta_hf_client_cb.scb.at_cb.hold_timer;
251 
252     APPL_TRACE_DEBUG("%s", __FUNCTION__);
253 
254     if (bta_hf_client_cb.scb.at_cb.hold_timer_on) {
255         bta_sys_stop_timer (timer);
256     }
257 
258     timer->p_cback = (TIMER_CBACK *)&bta_hf_client_at_hold_timer_cback;
259     bta_sys_start_timer(timer, 0, BTA_HF_CLIENT_AT_HOLD_TIMEOUT);
260     bta_hf_client_cb.scb.at_cb.hold_timer_on = TRUE;
261 }
262 
263 /******************************************************************************
264 **
265 **          COMMON AT EVENT HANDLING FUNCTIONS
266 **
267 **   Receives data (strings, ints, etc.) from the parser and processes this data.
268 **   No buffer parsing is being done here.
269 *******************************************************************************/
270 
bta_hf_client_handle_ok(void)271 static void bta_hf_client_handle_ok(void)
272 {
273     APPL_TRACE_DEBUG("%s", __FUNCTION__);
274 
275     bta_hf_client_stop_at_resp_timer();
276 
277     if (!bta_hf_client_cb.scb.svc_conn) {
278         bta_hf_client_slc_seq(FALSE);
279         return;
280     }
281 
282     switch (bta_hf_client_cb.scb.at_cb.current_cmd) {
283     case BTA_HF_CLIENT_AT_BIA:
284     case BTA_HF_CLIENT_AT_BCC:
285         break;
286     case BTA_HF_CLIENT_AT_BCS:
287         bta_hf_client_start_at_hold_timer();
288         bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
289         return;
290     case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq
291         if (bta_hf_client_cb.scb.send_at_reply == FALSE) {
292             bta_hf_client_cb.scb.send_at_reply = TRUE;
293         }
294         break;
295     case BTA_HF_CLIENT_AT_NONE:
296         bta_hf_client_stop_at_hold_timer();
297         break;
298     default:
299         if (bta_hf_client_cb.scb.send_at_reply) {
300             bta_hf_client_at_result(BTA_HF_CLIENT_AT_RESULT_OK, 0);
301         }
302         break;
303     }
304 
305     bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
306 
307     bta_hf_client_send_queued_at();
308 }
309 
bta_hf_client_handle_error(tBTA_HF_CLIENT_AT_RESULT_TYPE type,UINT16 cme)310 static void bta_hf_client_handle_error(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme)
311 {
312     APPL_TRACE_DEBUG("%s %u %u", __FUNCTION__, type, cme);
313 
314     bta_hf_client_stop_at_resp_timer();
315 
316     if (!bta_hf_client_cb.scb.svc_conn) {
317         bta_hf_client_slc_seq(TRUE);
318         return;
319     }
320 
321     switch (bta_hf_client_cb.scb.at_cb.current_cmd) {
322     case BTA_HF_CLIENT_AT_BIA:
323         break;
324     case BTA_HF_CLIENT_AT_BCC:
325     case BTA_HF_CLIENT_AT_BCS:
326         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
327         break;
328     case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq
329         if (bta_hf_client_cb.scb.send_at_reply == FALSE) {
330             bta_hf_client_cb.scb.send_at_reply = TRUE;
331         }
332         break;
333     default:
334         if (bta_hf_client_cb.scb.send_at_reply) {
335             bta_hf_client_at_result(type, cme);
336         }
337         break;
338     }
339 
340     bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
341 
342     bta_hf_client_send_queued_at();
343 }
344 
bta_hf_client_handle_ring(void)345 static void bta_hf_client_handle_ring(void)
346 {
347     APPL_TRACE_DEBUG("%s", __FUNCTION__);
348     bta_hf_client_evt_val(BTA_HF_CLIENT_RING_INDICATION, 0);
349 }
350 
bta_hf_client_handle_brsf(UINT32 value)351 static void bta_hf_client_handle_brsf(UINT32 value)
352 {
353     APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, value);
354     bta_hf_client_cb.scb.peer_features = value;
355 }
356 
357 /* handles a single indicator descriptor - registers it for value changing events */
bta_hf_client_handle_cind_list_item(char * name,UINT32 min,UINT32 max,UINT32 index)358 static void bta_hf_client_handle_cind_list_item(char *name, UINT32 min, UINT32 max, UINT32 index)
359 {
360 
361     UINT8 i = 0;
362 
363     APPL_TRACE_DEBUG("%s %u.%s <%u:%u>", __FUNCTION__, index, name, min, max);
364 
365     /* look for a matching indicator on list of supported ones */
366     for (i = 0; i < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT; i++) {
367         if (strcmp(name, BTA_HF_CLIENT_INDICATOR_SERVICE) == 0) {
368             service_index = index;
369         }
370         /* look for a match - search one sign further than indicators name to check for string end */
371         /* It will distinguish 'callheld' which could be matched by strncmp as 'call'.               */
372         if (strncmp(name, bta_hf_client_indicators[i].name, bta_hf_client_indicators[i].namelen) != 0) {
373             continue;
374         }
375 
376         /* index - enumerates value position in the incoming sequence                      */
377         /* if name matches one of the known indicators, add its incoming position          */
378         /* to lookup table for easy value->indicator matching later, when only values come  */
379         bta_hf_client_cb.scb.at_cb.indicator_lookup[index] = i;
380 
381         return;
382     }
383 }
384 
bta_hf_client_handle_cind_value(UINT32 index,UINT32 value)385 static void bta_hf_client_handle_cind_value(UINT32 index, UINT32 value)
386 {
387     APPL_TRACE_DEBUG("%s index: %u value: %u", __FUNCTION__, index, value);
388 
389     if (index >= BTA_HF_CLIENT_AT_INDICATOR_COUNT) {
390         return;
391     }
392 
393     if (service_index == index) {
394         if (value == 0) {
395             service_availability = FALSE;
396         } else {
397             service_availability = TRUE;
398         }
399     }
400     if (bta_hf_client_cb.scb.at_cb.indicator_lookup[index] == -1) {
401         return;
402     }
403 
404     /* get the real array index from lookup table */
405     index = bta_hf_client_cb.scb.at_cb.indicator_lookup[index];
406 
407     /* Ignore out of range values */
408     if (value > bta_hf_client_indicators[index].max ||
409             value < bta_hf_client_indicators[index].min) {
410         return;
411     }
412 
413     /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */
414     bta_hf_client_ind(index, value);
415 }
416 
bta_hf_client_handle_chld(UINT32 mask)417 static void bta_hf_client_handle_chld(UINT32 mask)
418 {
419     APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, mask);
420 
421     bta_hf_client_cb.scb.chld_features |= mask;
422 }
423 
bta_hf_client_handle_ciev(UINT32 index,UINT32 value)424 static void bta_hf_client_handle_ciev(UINT32 index, UINT32 value)
425 {
426     INT8 realind = -1;
427 
428     APPL_TRACE_DEBUG("%s index: %u value: %u", __FUNCTION__, index, value);
429 
430     if (index == 0 || index > BTA_HF_CLIENT_AT_INDICATOR_COUNT) {
431         APPL_TRACE_WARNING("%s: Invalid index %d", __FUNCTION__, index);
432         return;
433     }
434 
435     if (service_index == index - 1) {
436         service_availability = value == 0 ? FALSE : TRUE;
437     }
438 
439     realind = bta_hf_client_cb.scb.at_cb.indicator_lookup[index - 1];
440 
441     if (realind >= 0 && realind < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT) {
442         /* get the real in-array index from lookup table by index it comes at */
443         /* if there is no bug it should automatically be correctly calculated    */
444         if (value > bta_hf_client_indicators[realind].max || value < bta_hf_client_indicators[realind].min) {
445             return;
446         }
447 
448         /* update service availability on +ciev from AG. */
449         if (service_index == (index - 1)) {
450             if (value == 1) {
451                 service_availability = TRUE;
452             } else {
453                 service_availability = FALSE;
454             }
455         }
456 
457         /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */
458         bta_hf_client_ind(realind, value);
459     }
460 }
461 
bta_hf_client_handle_bcs(UINT32 codec)462 static void bta_hf_client_handle_bcs(UINT32 codec)
463 {
464     APPL_TRACE_DEBUG("%s %u", __FUNCTION__, codec);
465 
466     if (codec == BTM_SCO_CODEC_CVSD ||
467             (codec == BTM_SCO_CODEC_MSBC && bta_hf_client_cb.msbc_enabled == TRUE)) {
468         bta_hf_client_cb.scb.negotiated_codec = codec;
469         bta_hf_client_send_at_bcs(codec);
470     } else {
471         bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
472         bta_hf_client_send_at_bac();
473     }
474 }
475 
bta_hf_client_handle_bsir(UINT32 provided)476 static void bta_hf_client_handle_bsir(UINT32 provided)
477 {
478     APPL_TRACE_DEBUG("%s %u", __FUNCTION__, provided);
479 
480     bta_hf_client_evt_val(BTA_HF_CLIENT_BSIR_EVT, provided);
481 }
482 
bta_hf_client_handle_cmeerror(UINT32 code)483 static void bta_hf_client_handle_cmeerror(UINT32 code)
484 {
485     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_CME, code);
486 }
487 
bta_hf_client_handle_vgm(UINT32 value)488 static void bta_hf_client_handle_vgm(UINT32 value)
489 {
490     APPL_TRACE_DEBUG("%s %u", __FUNCTION__, value);
491 
492     if (value <= BTA_HF_CLIENT_VGM_MAX) {
493         bta_hf_client_evt_val(BTA_HF_CLIENT_MIC_EVT, value);
494     }
495 }
496 
bta_hf_client_handle_vgs(UINT32 value)497 static void bta_hf_client_handle_vgs(UINT32 value)
498 {
499     APPL_TRACE_DEBUG("%s %u", __FUNCTION__, value);
500 
501     if (value <= BTA_HF_CLIENT_VGS_MAX) {
502         bta_hf_client_evt_val(BTA_HF_CLIENT_SPK_EVT, value);
503     }
504 }
505 
bta_hf_client_handle_bvra(UINT32 value)506 static void bta_hf_client_handle_bvra(UINT32 value)
507 {
508     APPL_TRACE_DEBUG("%s %u", __FUNCTION__, value);
509 
510     if (value > 1) {
511         return;
512     }
513 
514     bta_hf_client_evt_val(BTA_HF_CLIENT_VOICE_REC_EVT, value);
515 }
516 
bta_hf_client_handle_clip(char * numstr,UINT32 type)517 static void bta_hf_client_handle_clip(char *numstr, UINT32 type)
518 {
519     APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, type, numstr);
520 
521     bta_hf_client_clip(numstr);
522 }
523 
bta_hf_client_handle_ccwa(char * numstr,UINT32 type)524 static void bta_hf_client_handle_ccwa(char *numstr, UINT32 type)
525 {
526     APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, type, numstr);
527 
528     bta_hf_client_ccwa(numstr);
529 }
530 
bta_hf_client_handle_cops(char * opstr,UINT32 mode)531 static void bta_hf_client_handle_cops(char *opstr, UINT32 mode)
532 {
533     APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, mode, opstr);
534 
535     bta_hf_client_operator_name(opstr);
536 }
537 
bta_hf_client_handle_binp(char * numstr)538 static void bta_hf_client_handle_binp(char *numstr)
539 {
540     APPL_TRACE_DEBUG("%s %s", __FUNCTION__, numstr);
541 
542     bta_hf_client_binp(numstr);
543 }
544 
bta_hf_client_handle_clcc(UINT16 idx,UINT16 dir,UINT16 status,UINT16 mode,UINT16 mpty,char * numstr,UINT16 type)545 static void bta_hf_client_handle_clcc(UINT16 idx, UINT16 dir, UINT16 status, UINT16 mode, UINT16 mpty, char *numstr, UINT16 type)
546 {
547     APPL_TRACE_DEBUG("%s idx: %u dir: %u status: %u mode: %u mpty: %u",
548                      __FUNCTION__, idx, dir, status, mode, mpty);
549 
550     if (numstr) {
551         APPL_TRACE_DEBUG("%s number: %s  type: %u", __FUNCTION__, numstr, type);
552     }
553 
554     bta_hf_client_clcc(idx, dir, status, mpty, numstr);
555 }
556 
bta_hf_client_handle_cnum(char * numstr,UINT16 type,UINT16 service)557 static void bta_hf_client_handle_cnum( char *numstr, UINT16 type, UINT16 service)
558 {
559     APPL_TRACE_DEBUG("%s number: %s type: %u service: %u", __FUNCTION__, numstr, type, service);
560 
561     /* TODO: should number be modified according to type? */
562     bta_hf_client_cnum(numstr, service);
563 }
564 
bta_hf_client_handle_btrh(UINT16 code)565 static void bta_hf_client_handle_btrh( UINT16 code)
566 {
567     APPL_TRACE_DEBUG("%s %u", __FUNCTION__, code);
568 
569     bta_hf_client_evt_val(BTA_HF_CLIENT_BTRH_EVT, code);
570 }
571 
572 /******************************************************************************
573 **
574 **          COMMON AT EVENTS PARSING FUNCTIONS
575 **
576 *******************************************************************************/
577 
578 /* Check if prefix match and skip spaces if any */
579 #define AT_CHECK_EVENT(buf, event) \
580 if (strncmp("\r\n"event,buf,sizeof("\r\n"event) - 1) != 0) \
581     return buf; \
582 buf += sizeof("\r\n"event) - 1; \
583 while (*buf == ' ') buf++;
584 
585 /* check for <cr><lf> and forward buffer if match */
586 #define AT_CHECK_RN(buf) \
587     if (strncmp("\r\n", buf, sizeof("\r\n") - 1) != 0) { \
588         APPL_TRACE_ERROR("%s missing end <cr><lf>", __FUNCTION__); \
589         return NULL;\
590     } \
591     buf += sizeof("\r\n") - 1;
592 
593 /* skip rest of AT string up to <cr> */
594 #define AT_SKIP_REST(buf) while(*buf != '\r') buf++;
595 
bta_hf_client_parse_ok(char * buffer)596 static char *bta_hf_client_parse_ok(char *buffer)
597 {
598     AT_CHECK_EVENT(buffer, "OK");
599     AT_CHECK_RN(buffer);
600 
601     bta_hf_client_handle_ok();
602 
603     return buffer;
604 }
605 
bta_hf_client_parse_error(char * buffer)606 static char *bta_hf_client_parse_error(char *buffer)
607 {
608     AT_CHECK_EVENT(buffer, "ERROR");
609     AT_CHECK_RN(buffer);
610 
611     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_ERROR, 0);
612 
613     return buffer;
614 }
615 
bta_hf_client_parse_ring(char * buffer)616 static char *bta_hf_client_parse_ring(char *buffer)
617 {
618     AT_CHECK_EVENT(buffer, "RING");
619     AT_CHECK_RN(buffer);
620 
621     bta_hf_client_handle_ring();
622 
623     return buffer;
624 }
625 
626 /* generic uint32 parser */
bta_hf_client_parse_uint32(char * buffer,void (* handler_callback)(UINT32))627 static char *bta_hf_client_parse_uint32(char *buffer, void (*handler_callback)(UINT32))
628 {
629     UINT32 value;
630     int res;
631     int offset;
632 
633     res = sscanf(buffer, "%u%n", &value, &offset);
634     if (res < 1) {
635         return NULL;
636     }
637 
638     buffer += offset;
639 
640     AT_CHECK_RN(buffer);
641 
642     handler_callback(value);
643     return buffer;
644 }
645 
bta_hf_client_parse_brsf(char * buffer)646 static char *bta_hf_client_parse_brsf(char *buffer)
647 {
648     AT_CHECK_EVENT(buffer, "+BRSF:");
649 
650     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_brsf);
651 }
652 
bta_hf_client_parse_cind_values(char * buffer)653 static char *bta_hf_client_parse_cind_values(char *buffer)
654 {
655     /* value and its position */
656     UINT16 index = 0;
657     UINT32 value = 0;
658 
659     int offset;
660     int res;
661 
662     while ((res = sscanf(buffer, "%u%n", &value, &offset)) > 0) {
663         /* decides if its valid index and value, if yes stores it */
664         bta_hf_client_handle_cind_value(index, value);
665 
666         buffer += offset;
667 
668         /* check if more values are present */
669         if (*buffer != ',') {
670             break;
671         }
672 
673         index++;
674         buffer++;
675     }
676 
677     if (res > 0) {
678         AT_CHECK_RN(buffer);
679         return buffer;
680     }
681 
682     return NULL;
683 }
684 
bta_hf_client_parse_cind_list(char * buffer)685 static char *bta_hf_client_parse_cind_list(char *buffer)
686 {
687     int offset;
688     char *name = osi_malloc(129);
689     UINT32 min, max;
690     UINT32 index = 0;
691     int res;
692 
693     if (name == NULL) {
694         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
695         return NULL;
696     }
697 
698     while ((res = sscanf(buffer, "(\"%128[^\"]\",(%u%*[-,]%u))%n", name, &min, &max, &offset)) > 2) {
699         bta_hf_client_handle_cind_list_item(name, min, max, index);
700         buffer += offset;
701         index++;
702 
703         if (*buffer != ',') {
704             break;
705         }
706 
707         buffer++;
708     }
709 
710     osi_free(name);
711 
712     if (res > 2) {
713         AT_CHECK_RN(buffer);
714         return buffer;
715     }
716 
717     return NULL;
718 }
719 
bta_hf_client_parse_cind(char * buffer)720 static char *bta_hf_client_parse_cind(char *buffer)
721 {
722     AT_CHECK_EVENT(buffer, "+CIND:");
723 
724     if (*buffer == '(') {
725         return bta_hf_client_parse_cind_list(buffer);
726     }
727 
728     return bta_hf_client_parse_cind_values(buffer);
729 }
730 
bta_hf_client_parse_chld(char * buffer)731 static char *bta_hf_client_parse_chld(char *buffer)
732 {
733     AT_CHECK_EVENT(buffer, "+CHLD:");
734 
735     if (*buffer != '(') {
736         return NULL;
737     }
738 
739     buffer++;
740 
741     while (*buffer != '\0') {
742         if (strncmp("0", buffer, 1) == 0) {
743             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL);
744             buffer++;
745         } else if (strncmp("1x", buffer, 2) == 0) {
746             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL_X);
747             buffer += 2;
748         } else if (strncmp("1", buffer, 1) == 0) {
749             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL_ACC);
750             buffer++;
751         } else if (strncmp("2x", buffer, 2) == 0) {
752             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_PRIV_X);
753             buffer += 2;
754         } else if (strncmp("2", buffer, 1) == 0) {
755             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_HOLD_ACC);
756             buffer++;
757         } else if (strncmp("3", buffer, 1) == 0) {
758             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_MERGE);
759             buffer++;
760         } else if (strncmp("4", buffer, 1) == 0) {
761             bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_MERGE_DETACH);
762             buffer++;
763         } else {
764             return NULL;
765         }
766 
767         if (*buffer == ',') {
768             buffer++;
769             continue;
770         }
771 
772         if (*buffer == ')') {
773             buffer++;
774             break;
775         }
776 
777         return NULL;
778     }
779 
780     AT_CHECK_RN(buffer);
781 
782     return buffer;
783 }
784 
bta_hf_client_parse_ciev(char * buffer)785 static char *bta_hf_client_parse_ciev(char *buffer)
786 {
787     UINT32 index, value;
788     int res;
789     int offset;
790 
791     AT_CHECK_EVENT(buffer, "+CIEV:");
792 
793     res = sscanf(buffer, "%u,%u%n", &index, &value, &offset);
794     if (res < 2) {
795         return NULL;
796     }
797 
798     buffer += offset;
799 
800     AT_CHECK_RN(buffer);
801 
802     bta_hf_client_handle_ciev(index, value);
803     return buffer;
804 }
805 
bta_hf_client_parse_bcs(char * buffer)806 static char *bta_hf_client_parse_bcs(char *buffer)
807 {
808     AT_CHECK_EVENT(buffer, "+BCS:");
809 
810     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bcs);
811 }
812 
bta_hf_client_parse_bsir(char * buffer)813 static char *bta_hf_client_parse_bsir(char *buffer)
814 {
815     AT_CHECK_EVENT(buffer, "+BSIR:");
816 
817     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bsir);
818 }
819 
bta_hf_client_parse_cmeerror(char * buffer)820 static char *bta_hf_client_parse_cmeerror(char *buffer)
821 {
822     AT_CHECK_EVENT(buffer, "+CME ERROR:");
823 
824     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_cmeerror);
825 }
826 
bta_hf_client_parse_vgm(char * buffer)827 static char *bta_hf_client_parse_vgm(char *buffer)
828 {
829     AT_CHECK_EVENT(buffer, "+VGM:");
830 
831     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgm);
832 }
833 
bta_hf_client_parse_vgme(char * buffer)834 static char *bta_hf_client_parse_vgme(char *buffer)
835 {
836     AT_CHECK_EVENT(buffer, "+VGM=");
837 
838     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgm);
839 }
840 
bta_hf_client_parse_vgs(char * buffer)841 static char *bta_hf_client_parse_vgs(char *buffer)
842 {
843     AT_CHECK_EVENT(buffer, "+VGS:");
844 
845     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgs);
846 }
847 
bta_hf_client_parse_vgse(char * buffer)848 static char *bta_hf_client_parse_vgse(char *buffer)
849 {
850     AT_CHECK_EVENT(buffer, "+VGS=");
851 
852     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgs);
853 }
854 
bta_hf_client_parse_bvra(char * buffer)855 static char *bta_hf_client_parse_bvra(char *buffer)
856 {
857     AT_CHECK_EVENT(buffer, "+BVRA:");
858 
859     return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bvra);
860 }
861 
bta_hf_client_parse_clip(char * buffer)862 static char *bta_hf_client_parse_clip(char *buffer)
863 {
864     /* spec forces 32 chars, plus \0 here */
865     char number[33];
866     UINT32 type = 0;
867     int res;
868     int offset;
869 
870     AT_CHECK_EVENT(buffer, "+CLIP:");
871 
872     /* there might be something more after %lu but HFP doesn't care */
873     res = sscanf(buffer, "\"%32[^\"]\",%u%n", number, &type, &offset);
874     if (res < 2) {
875         return NULL;
876     }
877 
878     buffer += offset;
879 
880     AT_SKIP_REST(buffer);
881 
882     AT_CHECK_RN(buffer);
883 
884     bta_hf_client_handle_clip(number, type);
885     return buffer;
886 }
887 
888 /* in HFP context there is no difference between ccwa and clip */
bta_hf_client_parse_ccwa(char * buffer)889 static char *bta_hf_client_parse_ccwa(char *buffer)
890 {
891     /* ac to spec 32 chars max, plus \0 here */
892     char number[33];
893     UINT32 type = 0;
894     int res ;
895     int offset;
896 
897     AT_CHECK_EVENT(buffer, "+CCWA:");
898 
899     /* there might be something more after %lu but HFP doesn't care */
900     res = sscanf(buffer, "\"%32[^\"]\",%u%n", number, &type, &offset);
901     if (res < 2) {
902         return NULL;
903     }
904 
905     buffer += offset;
906 
907     AT_SKIP_REST(buffer);
908 
909     AT_CHECK_RN(buffer);
910 
911     bta_hf_client_handle_ccwa(number, type);
912     return buffer;
913 }
914 
bta_hf_client_parse_cops(char * buffer)915 static char *bta_hf_client_parse_cops(char *buffer)
916 {
917     UINT8 mode;
918     /* spec forces 16 chars max, plus \0 here */
919     char opstr[17];
920     int res;
921     int offset;
922 
923     AT_CHECK_EVENT(buffer, "+COPS:");
924 
925     /* TODO: Not sure if operator string actually can contain escaped " char inside */
926     res = sscanf(buffer, "%hhi,0,\"%16[^\"]\"%n", &mode, opstr, &offset);
927     if (res < 2) {
928         return NULL;
929     }
930 
931     buffer += offset;
932 
933     AT_SKIP_REST(buffer);
934 
935     AT_CHECK_RN(buffer);
936 
937     bta_hf_client_handle_cops(opstr, mode);
938     return buffer;
939 }
940 
bta_hf_client_parse_binp(char * buffer)941 static char *bta_hf_client_parse_binp(char *buffer)
942 {
943     /* HFP only supports phone number as BINP data */
944     /* phone number is 32 chars plus one for \0*/
945     char numstr[33];
946     int res;
947     int offset;
948 
949     AT_CHECK_EVENT(buffer, "+BINP:");
950 
951     res = sscanf(buffer, "\"%32[^\"]\"\r\n%n", numstr, &offset);
952     if (res < 1) {
953         return NULL;
954     }
955 
956     buffer += offset;
957 
958     /* some phones might sent type as well, just skip it */
959     AT_SKIP_REST(buffer);
960 
961     AT_CHECK_RN(buffer);
962 
963     bta_hf_client_handle_binp(numstr);
964     return buffer;
965 }
966 
bta_hf_client_parse_clcc(char * buffer)967 static char *bta_hf_client_parse_clcc(char *buffer)
968 {
969     UINT16 idx, dir, status, mode, mpty;
970     char numstr[33];     /* spec forces 32 chars, plus one for \0*/
971     UINT16 type;
972     int res;
973     int offset;
974     AT_CHECK_EVENT(buffer, "+CLCC:");
975 
976     res = sscanf(buffer, "%hu,%hu,%hu,%hu,%hu%n",
977                  &idx, &dir, &status, &mode, &mpty, &offset);
978     if (res < 5) {
979         return NULL;
980     }
981 
982     /* Abort in case offset not set because of format error */
983     if (offset == 0) {
984         APPL_TRACE_ERROR("%s: Format Error %s", __func__, buffer);
985         return NULL;
986     }
987 
988     buffer += offset;
989     offset = 0;
990 
991     /* check optional part */
992     if (*buffer == ',') {
993         int res2 = sscanf(buffer, ",\"%32[^\"]\",%hu%n", numstr, &type, &offset);
994         if (res2 < 0) {
995             return NULL;
996         }
997 
998         if (res2 == 0) {
999             res2 = sscanf(buffer, ",\"\",%hu%n", &type, &offset);
1000             if (res2 < 0) {
1001                 return NULL;
1002             }
1003 
1004             /* numstr is not matched in second attempt, correct this */
1005             res2++;
1006             numstr[0] = '\0';
1007         }
1008 
1009         if (res2 >= 2) {
1010             res += res2;
1011             /* Abort in case offset not set because of format error */
1012             if (offset == 0) {
1013                 APPL_TRACE_ERROR("%s: Format Error %s", __func__, buffer);
1014                 return NULL;
1015             }
1016 
1017             buffer += offset;
1018         }
1019     }
1020 
1021     /* Skip any remaing param,as they are not defined by BT HFP spec */
1022     AT_SKIP_REST(buffer);
1023     AT_CHECK_RN(buffer);
1024 
1025     if (res > 6) {
1026         /* we also have last two optional parameters */
1027         bta_hf_client_handle_clcc(idx, dir, status, mode, mpty, numstr, type);
1028     } else {
1029         /* we didn't get the last two parameters */
1030         bta_hf_client_handle_clcc(idx, dir, status, mode, mpty, NULL, 0);
1031     }
1032 
1033     return buffer;
1034 }
1035 
bta_hf_client_parse_cnum(char * buffer)1036 static char *bta_hf_client_parse_cnum(char *buffer)
1037 {
1038     char numstr[33];     /* spec forces 32 chars, plus one for \0*/
1039     UINT16 type;
1040     UINT16 service = 0; /* 0 in case this optional parameter is not being sent */
1041     int res;
1042     int offset;
1043 
1044     AT_CHECK_EVENT(buffer, "+CNUM:");
1045 
1046     res = sscanf(buffer, ",\"%32[^\"]\",%hu%n,,%hu%n", numstr, &type, &offset, &service, &offset);
1047     if (res < 0) {
1048         return NULL;
1049     }
1050 
1051     if (res == 0) {
1052         res = sscanf(buffer, ",\"\",%hu%n,,%hu%n", &type, &offset, &service, &offset);
1053         if (res < 0) {
1054             return NULL;
1055         }
1056 
1057         /* numstr is not matched in second attempt, correct this */
1058         res++;
1059         numstr[0] = '\0';
1060     }
1061 
1062     if (res < 2) {
1063         return NULL;
1064     }
1065 
1066     buffer += offset;
1067 
1068     AT_CHECK_RN(buffer);
1069 
1070     /* service is optional */
1071     if (res == 2) {
1072         bta_hf_client_handle_cnum(numstr, type, service);
1073         return buffer;
1074     }
1075 
1076     if (service != 4 && service != 5) {
1077         return NULL;
1078     }
1079 
1080     bta_hf_client_handle_cnum(numstr, type, service);
1081     return buffer;
1082 }
1083 
bta_hf_client_parse_btrh(char * buffer)1084 static char *bta_hf_client_parse_btrh(char *buffer)
1085 {
1086     UINT16 code = 0;
1087     int res;
1088     int offset;
1089 
1090     AT_CHECK_EVENT(buffer, "+BTRH:");
1091 
1092     res = sscanf(buffer, "%hu%n", &code, &offset);
1093     if (res < 1) {
1094         return NULL;
1095     }
1096 
1097     buffer += offset;
1098 
1099     AT_CHECK_RN(buffer);
1100 
1101     bta_hf_client_handle_btrh(code);
1102     return buffer;
1103 }
1104 
bta_hf_client_parse_busy(char * buffer)1105 static char *bta_hf_client_parse_busy(char *buffer)
1106 {
1107     AT_CHECK_EVENT(buffer, "BUSY");
1108     AT_CHECK_RN(buffer);
1109 
1110     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_BUSY, 0);
1111 
1112     return buffer;
1113 }
1114 
bta_hf_client_parse_delayed(char * buffer)1115 static char *bta_hf_client_parse_delayed(char *buffer)
1116 {
1117     AT_CHECK_EVENT(buffer, "DELAYED");
1118     AT_CHECK_RN(buffer);
1119 
1120     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_DELAY, 0);
1121 
1122     return buffer;
1123 }
1124 
bta_hf_client_parse_no_carrier(char * buffer)1125 static char *bta_hf_client_parse_no_carrier(char *buffer)
1126 {
1127     AT_CHECK_EVENT(buffer, "NO CARRIER");
1128     AT_CHECK_RN(buffer);
1129 
1130     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_NO_CARRIER, 0);
1131 
1132     return buffer;
1133 }
1134 
bta_hf_client_parse_no_answer(char * buffer)1135 static char *bta_hf_client_parse_no_answer(char *buffer)
1136 {
1137     AT_CHECK_EVENT(buffer, "NO ANSWER");
1138     AT_CHECK_RN(buffer);
1139 
1140     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_NO_ANSWER, 0);
1141 
1142     return buffer;
1143 }
1144 
bta_hf_client_parse_blacklisted(char * buffer)1145 static char *bta_hf_client_parse_blacklisted(char *buffer)
1146 {
1147     AT_CHECK_EVENT(buffer, "BLACKLISTED");
1148     AT_CHECK_RN(buffer);
1149 
1150     bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_BLACKLISTED, 0);
1151 
1152     return buffer;
1153 }
1154 
bta_hf_client_skip_unknown(char * buffer)1155 static char *bta_hf_client_skip_unknown(char *buffer)
1156 {
1157     char *start;
1158     char *tmp;
1159 
1160     tmp = strstr(buffer, "\r\n");
1161     if (tmp == NULL) {
1162         return NULL;
1163     }
1164 
1165     buffer += 2;
1166     start = buffer;
1167 
1168     tmp = strstr(buffer, "\r\n");
1169     if (tmp == NULL) {
1170         return NULL;
1171     }
1172 
1173     buffer = tmp + 2;
1174 
1175     APPL_TRACE_DEBUG("%s %.*s", __FUNCTION__, buffer - start - 2, start);
1176     UNUSED(start);
1177 
1178     return buffer;
1179 }
1180 
1181 
1182 /******************************************************************************
1183 **       SUPPORTED EVENT MESSAGES
1184 *******************************************************************************/
1185 
1186 /* returned values are as follow:
1187  * != NULL && != buf  : match and parsed ok
1188  * == NULL            : match but parse failed
1189  * != NULL && == buf  : no match
1190  */
1191 typedef char *(*tBTA_HF_CLIENT_PARSER_CALLBACK)(char *);
1192 
1193 static const tBTA_HF_CLIENT_PARSER_CALLBACK bta_hf_client_parser_cb[] = {
1194     bta_hf_client_parse_ok,
1195     bta_hf_client_parse_error,
1196     bta_hf_client_parse_ring,
1197     bta_hf_client_parse_brsf,
1198     bta_hf_client_parse_cind,
1199     bta_hf_client_parse_ciev,
1200     bta_hf_client_parse_chld,
1201     bta_hf_client_parse_bcs,
1202     bta_hf_client_parse_bsir,
1203     bta_hf_client_parse_cmeerror,
1204     bta_hf_client_parse_vgm,
1205     bta_hf_client_parse_vgme,
1206     bta_hf_client_parse_vgs,
1207     bta_hf_client_parse_vgse,
1208     bta_hf_client_parse_bvra,
1209     bta_hf_client_parse_clip,
1210     bta_hf_client_parse_ccwa,
1211     bta_hf_client_parse_cops,
1212     bta_hf_client_parse_binp,
1213     bta_hf_client_parse_clcc,
1214     bta_hf_client_parse_cnum,
1215     bta_hf_client_parse_btrh,
1216     bta_hf_client_parse_busy,
1217     bta_hf_client_parse_delayed,
1218     bta_hf_client_parse_no_carrier,
1219     bta_hf_client_parse_no_answer,
1220     bta_hf_client_parse_blacklisted,
1221     bta_hf_client_skip_unknown
1222 };
1223 
1224 /* calculate supported event list length */
1225 static const UINT16 bta_hf_client_psraser_cb_count =
1226     sizeof(bta_hf_client_parser_cb) / sizeof(bta_hf_client_parser_cb[0]);
1227 
1228 #ifdef BTA_HF_CLIENT_AT_DUMP
bta_hf_client_dump_at(void)1229 static void bta_hf_client_dump_at(void)
1230 {
1231     char dump[(4 * BTA_HF_CLIENT_AT_PARSER_MAX_LEN) + 1];
1232     char *p1, *p2;
1233 
1234     p1 = bta_hf_client_cb.scb.at_cb.buf;
1235     p2 = dump;
1236 
1237     while (*p1 != '\0') {
1238         if (*p1 == '\r') {
1239             strlcpy(p2, "<cr>", 4);
1240             p2 += 4;
1241         } else if (*p1 == '\n') {
1242             strlcpy(p2, "<lf>", 4);
1243             p2 += 4;
1244         } else {
1245             *p2 = *p1;
1246             p2++;
1247         }
1248         p1++;
1249     }
1250 
1251     *p2 = '\0';
1252 
1253     APPL_TRACE_DEBUG("%s %s", __FUNCTION__, dump);
1254 }
1255 #endif
1256 
bta_hf_client_at_parse_start(void)1257 static void bta_hf_client_at_parse_start(void)
1258 {
1259     char *buf = bta_hf_client_cb.scb.at_cb.buf;
1260 
1261     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1262 
1263 #ifdef BTA_HF_CLIENT_AT_DUMP
1264     bta_hf_client_dump_at();
1265 #endif
1266 
1267     while (*buf != '\0') {
1268         int i;
1269         char *tmp = NULL;
1270 
1271         for (i = 0; i < bta_hf_client_psraser_cb_count; i++) {
1272             tmp = bta_hf_client_parser_cb[i](buf);
1273             if (tmp == NULL) {
1274                 APPL_TRACE_ERROR("HFPCient: AT event/reply parsing failed, skipping %d", i);
1275                 tmp = bta_hf_client_skip_unknown(buf);
1276                 break;
1277             }
1278 
1279             /* matched or unknown skipped, if unknown failed tmp is NULL so
1280                this is also handled */
1281             if (tmp != buf) {
1282                 buf = tmp;
1283                 break;
1284             }
1285         }
1286 
1287         /* could not skip unknown (received garbage?)... disconnect */
1288         if (tmp == NULL) {
1289             APPL_TRACE_ERROR("HFPCient: could not skip unknown AT event, disconnecting");
1290             bta_hf_client_at_reset();
1291             bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
1292             return;
1293         }
1294 
1295         buf = tmp;
1296     }
1297 }
1298 
bta_hf_client_check_at_complete(void)1299 static BOOLEAN bta_hf_client_check_at_complete(void)
1300 {
1301     BOOLEAN ret = FALSE;
1302     tBTA_HF_CLIENT_AT_CB *at_cb = &bta_hf_client_cb.scb.at_cb;
1303 
1304     if (at_cb->offset >= BTA_HF_CLIENT_AT_EVENT_MIN_LEN) {
1305         if (at_cb->buf[at_cb->offset - 2] == '\r' && at_cb->buf[at_cb->offset - 1] == '\n') {
1306             ret = TRUE;
1307         }
1308     }
1309 
1310     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, ret);
1311 
1312     return ret;
1313 }
1314 
bta_hf_client_at_clear_buf(void)1315 static void bta_hf_client_at_clear_buf(void)
1316 {
1317     memset(bta_hf_client_cb.scb.at_cb.buf, 0, sizeof(bta_hf_client_cb.scb.at_cb.buf));
1318     bta_hf_client_cb.scb.at_cb.offset = 0;
1319 }
1320 
1321 /******************************************************************************
1322 **
1323 **          MAIN PARSING FUNCTION
1324 **
1325 **
1326 *******************************************************************************/
bta_hf_client_at_parse(char * buf,unsigned int len)1327 void bta_hf_client_at_parse(char *buf, unsigned int len)
1328 {
1329     APPL_TRACE_DEBUG("%s offset: %u len: %u", __FUNCTION__, bta_hf_client_cb.scb.at_cb.offset, len);
1330 
1331     if (len + bta_hf_client_cb.scb.at_cb.offset > BTA_HF_CLIENT_AT_PARSER_MAX_LEN) {
1332         unsigned int tmp = bta_hf_client_cb.scb.at_cb.offset;
1333         unsigned int space_left = BTA_HF_CLIENT_AT_PARSER_MAX_LEN - bta_hf_client_cb.scb.at_cb.offset;
1334         char *tmp_buff = osi_malloc(BTA_HF_CLIENT_AT_PARSER_MAX_LEN);
1335         if (tmp_buff == NULL) {
1336             APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1337             return;
1338         }
1339         APPL_TRACE_DEBUG("%s overrun, trying to recover", __FUNCTION__);
1340 
1341         /* fill up parser buffer */
1342         memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, space_left);
1343         len -= space_left;
1344         buf += space_left;
1345         bta_hf_client_cb.scb.at_cb.offset += space_left;
1346 
1347         /* find end of last complete command before proceeding */
1348         while (bta_hf_client_check_at_complete() == FALSE) {
1349             if (bta_hf_client_cb.scb.at_cb.offset == 0) {
1350                 APPL_TRACE_ERROR("HFPClient: AT parser buffer overrun, disconnecting");
1351 
1352                 bta_hf_client_at_reset();
1353                 bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
1354                 osi_free(tmp_buff);
1355                 return;
1356             }
1357 
1358             bta_hf_client_cb.scb.at_cb.offset--;
1359         }
1360 
1361         /* cut buffer to complete AT event and keep cut data */
1362         tmp += space_left - bta_hf_client_cb.scb.at_cb.offset;
1363         memcpy(tmp_buff, bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, tmp);
1364         bta_hf_client_cb.scb.at_cb.buf[bta_hf_client_cb.scb.at_cb.offset] = '\0';
1365 
1366         /* parse */
1367         bta_hf_client_at_parse_start();
1368         bta_hf_client_at_clear_buf();
1369 
1370         /* recover cut data */
1371         memcpy(bta_hf_client_cb.scb.at_cb.buf, tmp_buff, tmp);
1372         bta_hf_client_cb.scb.at_cb.offset += tmp;
1373 
1374         osi_free(tmp_buff);
1375     }
1376 
1377     memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, len);
1378     bta_hf_client_cb.scb.at_cb.offset += len;
1379 
1380     /* If last event is complete, parsing can be started */
1381     if (bta_hf_client_check_at_complete() == TRUE) {
1382         bta_hf_client_at_parse_start();
1383         bta_hf_client_at_clear_buf();
1384     }
1385 }
1386 
bta_hf_client_send_at_brsf(void)1387 void bta_hf_client_send_at_brsf(void)
1388 {
1389     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1390     int at_len;
1391 
1392     if (buf == NULL) {
1393         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1394         return;
1395     }
1396 
1397     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1398 
1399     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BRSF=%u\r", bta_hf_client_cb.scb.features);
1400 
1401     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BRSF , buf, at_len);
1402     osi_free(buf);
1403 }
1404 
bta_hf_client_send_at_bac(void)1405 void bta_hf_client_send_at_bac(void)
1406 {
1407     char *buf;
1408 
1409     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1410 
1411     if (bta_hf_client_cb.msbc_enabled) {
1412         buf = "AT+BAC=1,2\r";
1413     } else {
1414         buf = "AT+BAC=1\r";
1415     }
1416 
1417     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BAC, buf, strlen(buf));
1418 }
1419 
bta_hf_client_send_at_bcs(UINT32 codec)1420 void bta_hf_client_send_at_bcs(UINT32 codec)
1421 {
1422     char * buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1423     int at_len;
1424 
1425     if (buf == NULL) {
1426         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1427         return;
1428     }
1429 
1430     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BCS=%u\r", codec);
1431 
1432     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BCS, buf, at_len);
1433     osi_free(buf);
1434 }
1435 
bta_hf_client_send_at_cind(BOOLEAN status)1436 void bta_hf_client_send_at_cind(BOOLEAN status)
1437 {
1438     char *buf;
1439     tBTA_HF_CLIENT_AT_CMD cmd;
1440 
1441     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1442 
1443     if (status) {
1444         buf = "AT+CIND?\r";
1445         cmd = BTA_HF_CLIENT_AT_CIND_STATUS;
1446     } else {
1447         buf = "AT+CIND=?\r";
1448         cmd = BTA_HF_CLIENT_AT_CIND;
1449     }
1450 
1451     bta_hf_client_send_at(cmd, buf, strlen(buf));
1452 }
1453 
bta_hf_client_send_at_cmer(BOOLEAN activate)1454 void bta_hf_client_send_at_cmer(BOOLEAN activate)
1455 {
1456     char *buf;
1457 
1458     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1459 
1460     if (activate) {
1461         buf = "AT+CMER=3,0,0,1\r";
1462     } else {
1463         buf = "AT+CMER=3,0,0,0\r";
1464     }
1465 
1466     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CMER, buf, strlen(buf));
1467 }
1468 
bta_hf_client_send_at_chld(char cmd,UINT32 idx)1469 void bta_hf_client_send_at_chld(char cmd, UINT32 idx)
1470 {
1471     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1472     int at_len;
1473 
1474     if (buf == NULL) {
1475         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1476         return;
1477     }
1478 
1479     if (idx > 0) {
1480         at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+CHLD=%c%u\r", cmd, idx);
1481     } else {
1482         at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+CHLD=%c\r", cmd);
1483     }
1484 
1485     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CHLD, buf, at_len);
1486     osi_free(buf);
1487 }
1488 
bta_hf_client_send_at_clip(BOOLEAN activate)1489 void bta_hf_client_send_at_clip(BOOLEAN activate)
1490 {
1491     char *buf;
1492 
1493     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1494 
1495     if (activate) {
1496         buf = "AT+CLIP=1\r";
1497     } else {
1498         buf = "AT+CLIP=0\r";
1499     }
1500 
1501     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CLIP, buf, strlen(buf));
1502 }
1503 
bta_hf_client_send_at_ccwa(BOOLEAN activate)1504 void bta_hf_client_send_at_ccwa(BOOLEAN activate)
1505 {
1506     char *buf;
1507 
1508     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1509 
1510     if (activate) {
1511         buf = "AT+CCWA=1\r";
1512     } else {
1513         buf = "AT+CCWA=0\r";
1514     }
1515 
1516     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CCWA, buf, strlen(buf));
1517 }
1518 
1519 
bta_hf_client_send_at_cmee(BOOLEAN activate)1520 void bta_hf_client_send_at_cmee(BOOLEAN activate)
1521 {
1522     char *buf;
1523 
1524     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1525 
1526     if (activate) {
1527         buf = "AT+CMEE=1\r";
1528     } else {
1529         buf = "AT+CMEE=0\r";
1530     }
1531 
1532     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CMEE, buf, strlen(buf));
1533 }
1534 
bta_hf_client_send_at_cops(BOOLEAN query)1535 void bta_hf_client_send_at_cops(BOOLEAN query)
1536 {
1537     char *buf;
1538 
1539     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1540 
1541     if (query) {
1542         buf = "AT+COPS?\r";
1543     } else {
1544         buf = "AT+COPS=3,0\r";
1545     }
1546 
1547     bta_hf_client_send_at(BTA_HF_CLIENT_AT_COPS, buf, strlen(buf));
1548 }
1549 
bta_hf_client_send_at_clcc(void)1550 void bta_hf_client_send_at_clcc(void)
1551 {
1552     char *buf;
1553 
1554     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1555 
1556     buf = "AT+CLCC\r";
1557 
1558     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CLCC, buf, strlen(buf));
1559 }
1560 
1561 
bta_hf_client_send_at_xapl(char * information,UINT32 features)1562 void bta_hf_client_send_at_xapl(char *information, UINT32 features)
1563 {
1564     APPL_TRACE_DEBUG("%s(%s, %u)", __FUNCTION__, information, features);
1565 
1566     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1567 
1568     /*
1569     Format: AT+XAPL=vendorID-productID-version,features
1570     Parameters:
1571         *vendorID: A string representation of the hex value of the vendor ID from the manufacturer, without the 0x prefix.
1572         *productID: A string representation of the hex value of the product ID from the manufacturer, without the 0x prefix.
1573         *version: The revision of the software.
1574         *Fatures: A base-10 representation of a bit field. Available features are:
1575             *Bit 0 = reserved
1576             *Bit 1 = The accessory supports battery reporting (reserved only for battery operated accessories).
1577             *Bit 2 = The accessory is docked or powered (reserved only for battery operated accessories).
1578             *Bit 3 = The accessory supports Siri status reporting.
1579             *Bit 4 = the accessory supports noise reduction (NR) status reporting.
1580             *All other values are reserved.
1581     */
1582 
1583     snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+XAPL=%s,%u\r", information, features);
1584 
1585     bta_hf_client_send_at(BTA_HF_CLIENT_AT_XAPL, buf, strlen(buf));
1586     osi_free(buf);
1587 }
1588 
bta_hf_client_send_at_iphoneaccev(UINT32 bat_level,BOOLEAN docked)1589 void bta_hf_client_send_at_iphoneaccev(UINT32 bat_level, BOOLEAN docked)
1590 {
1591     APPL_TRACE_DEBUG("%s(%u, %s)", __FUNCTION__, bat_level, docked ? "docked" : "undocked");
1592 
1593     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1594 
1595     /*
1596     Format: AT+IPHONEACCEV=Number of key/value pairs,key1,val1,key2,val2,...
1597     Parameters:
1598         * Number of key/value pairs: The number of parameters coming next.
1599         * key: the type of change being reported:
1600             * 1 = Battery Level
1601             * 2 = Dock State
1602         * val: the value of the change:
1603             * Battery Level: string value between '0' and '9'
1604             * Dock State: 0 = undocked, 1 = docked
1605     */
1606 
1607     snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+IPHONEACCEV=2,1,%u,2,%u\r", bat_level, docked ? 1 : 0);
1608 
1609     bta_hf_client_send_at(BTA_HF_CLIENT_AT_IPHONEACCEV, buf, strlen(buf));
1610     osi_free(buf);
1611 }
1612 
bta_hf_client_send_at_bvra(BOOLEAN enable)1613 void bta_hf_client_send_at_bvra(BOOLEAN enable)
1614 {
1615     char *buf;
1616 
1617     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1618 
1619     if (enable) {
1620         buf = "AT+BVRA=1\r";
1621     } else {
1622         buf = "AT+BVRA=0\r";
1623     }
1624 
1625     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BVRA, buf, strlen(buf));
1626 }
1627 
bta_hf_client_send_at_vgs(UINT32 volume)1628 void bta_hf_client_send_at_vgs(UINT32 volume)
1629 {
1630     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1631     int at_len;
1632     if (buf == NULL) {
1633         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1634         return;
1635     }
1636     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1637 
1638     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+VGS=%u\r", volume);
1639 
1640     bta_hf_client_send_at(BTA_HF_CLIENT_AT_VGS, buf, at_len);
1641     osi_free(buf);
1642 }
1643 
bta_hf_client_send_at_vgm(UINT32 volume)1644 void bta_hf_client_send_at_vgm(UINT32 volume)
1645 {
1646     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1647     int at_len;
1648 
1649     if (buf == NULL) {
1650         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1651         return;
1652     }
1653     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1654 
1655     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+VGM=%u\r", volume);
1656 
1657     bta_hf_client_send_at(BTA_HF_CLIENT_AT_VGM, buf, at_len);
1658     osi_free(buf);
1659 }
1660 
bta_hf_client_send_at_atd(char * number,UINT32 memory)1661 void bta_hf_client_send_at_atd(char *number, UINT32 memory)
1662 {
1663     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1664     int at_len;
1665 
1666     if (buf == NULL) {
1667         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1668         return;
1669     }
1670     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1671 
1672     if (number[0] != '\0') {
1673         at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "ATD%s;\r", number);
1674     } else {
1675         at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "ATD>%u;\r", memory);
1676     }
1677 
1678     at_len = MIN(at_len, BTA_HF_CLIENT_AT_MAX_LEN);
1679 
1680     bta_hf_client_send_at(BTA_HF_CLIENT_AT_ATD, buf, at_len);
1681     osi_free(buf);
1682 }
1683 
bta_hf_client_send_at_bldn(void)1684 void bta_hf_client_send_at_bldn(void)
1685 {
1686     char *buf;
1687 
1688     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1689 
1690     buf = "AT+BLDN\r";
1691 
1692     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BLDN, buf, strlen(buf));
1693 }
1694 
bta_hf_client_send_at_ata(void)1695 void bta_hf_client_send_at_ata(void)
1696 {
1697     char *buf;
1698 
1699     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1700 
1701     buf = "ATA\r";
1702 
1703     bta_hf_client_send_at(BTA_HF_CLIENT_AT_ATA, buf, strlen(buf));
1704 }
1705 
bta_hf_client_send_at_chup(void)1706 void bta_hf_client_send_at_chup(void)
1707 {
1708     char *buf;
1709 
1710     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1711 
1712     buf = "AT+CHUP\r";
1713 
1714     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CHUP, buf, strlen(buf));
1715 }
1716 
bta_hf_client_send_at_btrh(BOOLEAN query,UINT32 val)1717 void bta_hf_client_send_at_btrh(BOOLEAN query, UINT32 val)
1718 {
1719     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1720     int at_len;
1721 
1722     if (buf == NULL) {
1723         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1724         return;
1725     }
1726     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1727 
1728     if (query == TRUE) {
1729         at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BTRH?\r");
1730     } else {
1731         at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BTRH=%u\r", val);
1732     }
1733 
1734     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BTRH, buf, at_len);
1735     osi_free(buf);
1736 }
1737 
bta_hf_client_send_at_vts(char code)1738 void bta_hf_client_send_at_vts(char code)
1739 {
1740     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1741     int at_len;
1742     if (buf == NULL) {
1743         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1744         return;
1745     }
1746     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1747 
1748     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+VTS=%c\r", code);
1749 
1750     bta_hf_client_send_at(BTA_HF_CLIENT_AT_VTS, buf, at_len);
1751     osi_free(buf);
1752 }
1753 
bta_hf_client_send_at_bcc(void)1754 void bta_hf_client_send_at_bcc(void)
1755 {
1756     char *buf;
1757 
1758     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1759 
1760     buf = "AT+BCC\r";
1761 
1762     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BCC, buf, strlen(buf));
1763 }
1764 
bta_hf_client_send_at_cnum(void)1765 void bta_hf_client_send_at_cnum(void)
1766 {
1767     char *buf;
1768 
1769     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1770 
1771     buf = "AT+CNUM\r";
1772 
1773     bta_hf_client_send_at(BTA_HF_CLIENT_AT_CNUM, buf, strlen(buf));
1774 }
1775 
bta_hf_client_send_at_nrec(void)1776 void bta_hf_client_send_at_nrec(void)
1777 {
1778     char *buf;
1779 
1780     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1781 
1782     if (!(bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_ECNR)) {
1783         APPL_TRACE_ERROR("%s: Remote does not support NREC.", __FUNCTION__);
1784         return;
1785     }
1786 
1787     buf = "AT+NREC=0\r";
1788 
1789     bta_hf_client_send_at(BTA_HF_CLIENT_AT_NREC, buf, strlen(buf));
1790 }
1791 
bta_hf_client_send_at_binp(UINT32 action)1792 void bta_hf_client_send_at_binp(UINT32 action)
1793 {
1794     char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1795     int at_len;
1796 
1797     if (buf == NULL) {
1798         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1799         return;
1800     }
1801 
1802     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BINP=%u\r", action);
1803 
1804     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BINP, buf, at_len);
1805     osi_free(buf);
1806 }
1807 
bta_hf_client_send_at_bia(void)1808 void bta_hf_client_send_at_bia(void)
1809 {
1810     char *buf;
1811     int at_len;
1812     int i;
1813 
1814     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1815     if (bta_hf_client_cb.scb.peer_version < HFP_VERSION_1_6) {
1816         APPL_TRACE_DEBUG("Remote does not Support AT+BIA");
1817         return;
1818     }
1819 
1820     buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN);
1821     if (buf == NULL) {
1822         APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
1823         return;
1824     }
1825     at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BIA=");
1826 
1827     for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) {
1828         int sup = bta_hf_client_cb.scb.at_cb.indicator_lookup[i] == -1 ? 0 : 1;
1829 
1830         at_len += snprintf(buf + at_len, BTA_HF_CLIENT_AT_MAX_LEN - at_len, "%u,", sup);
1831     }
1832 
1833     buf[at_len - 1] = '\r';
1834 
1835     bta_hf_client_send_at(BTA_HF_CLIENT_AT_BIA, buf, at_len);
1836     osi_free(buf);
1837 }
1838 
bta_hf_client_at_init(void)1839 void bta_hf_client_at_init(void)
1840 {
1841     memset(&bta_hf_client_cb.scb.at_cb, 0, sizeof(tBTA_HF_CLIENT_AT_CB));
1842     bta_hf_client_at_reset();
1843 }
1844 
bta_hf_client_at_reset(void)1845 void bta_hf_client_at_reset(void)
1846 {
1847     int i;
1848 
1849     bta_hf_client_free_at_resp_timer();
1850     bta_hf_client_free_at_hold_timer();
1851 
1852     bta_hf_client_clear_queued_at();
1853 
1854     bta_hf_client_at_clear_buf();
1855 
1856     for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) {
1857         bta_hf_client_cb.scb.at_cb.indicator_lookup[i] = -1;
1858     }
1859 
1860     bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
1861 }
1862 #endif /* #if (BTA_HF_INCLUDED == TRUE) */
1863