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