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