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