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