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