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