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