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