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