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