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