1 /******************************************************************************
2 *
3 * Copyright 2004-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * BTA AG AT command interpreter.
22 *
23 ******************************************************************************/
24 #define LOG_TAG "bta_ag_at"
25
26 #include "bta/ag/bta_ag_at.h"
27
28 #include <bluetooth/log.h>
29 #include <com_android_bluetooth_flags.h>
30
31 #include <cstdint>
32 #include <cstdlib>
33 #include <cstring>
34
35 #include "bta/ag/bta_ag_int.h"
36 #include "bta/include/utl.h"
37 #include "osi/include/allocator.h"
38
39 using namespace bluetooth;
40
41 /*****************************************************************************
42 * Constants
43 ****************************************************************************/
44
45 /******************************************************************************
46 *
47 * Function bta_ag_at_init
48 *
49 * Description Initialize the AT command parser control block.
50 *
51 *
52 * Returns void
53 *
54 *****************************************************************************/
bta_ag_at_init(tBTA_AG_AT_CB * p_cb)55 void bta_ag_at_init(tBTA_AG_AT_CB* p_cb) {
56 p_cb->p_cmd_buf = nullptr;
57 p_cb->cmd_pos = 0;
58 }
59
60 /******************************************************************************
61 *
62 * Function bta_ag_at_reinit
63 *
64 * Description Re-initialize the AT command parser control block. This
65 * function resets the AT command parser state and frees
66 * any GKI buffer.
67 *
68 *
69 * Returns void
70 *
71 *****************************************************************************/
bta_ag_at_reinit(tBTA_AG_AT_CB * p_cb)72 void bta_ag_at_reinit(tBTA_AG_AT_CB* p_cb) {
73 osi_free_and_reset((void**)&p_cb->p_cmd_buf);
74 p_cb->cmd_pos = 0;
75 }
76
77 /******************************************************************************
78 *
79 * Function bta_ag_process_at
80 *
81 * Description Parse AT commands. This function will take the input
82 * character string and parse it for AT commands according to
83 * the AT command table passed in the control block.
84 *
85 *
86 * Returns void
87 *
88 *****************************************************************************/
bta_ag_process_at(tBTA_AG_AT_CB * p_cb,char * p_end)89 static void bta_ag_process_at(tBTA_AG_AT_CB* p_cb, char* p_end) {
90 uint16_t idx;
91 uint8_t arg_type;
92 char* p_arg;
93 int16_t int_arg = 0;
94 /* loop through at command table looking for match */
95 for (idx = 0; p_cb->p_at_tbl[idx].p_cmd[0] != 0; idx++) {
96 if (!utl_strucmp(p_cb->p_at_tbl[idx].p_cmd, p_cb->p_cmd_buf)) {
97 break;
98 }
99 }
100
101 /* if there is a match; verify argument type */
102 if (p_cb->p_at_tbl[idx].p_cmd[0] != 0) {
103 /* start of argument is p + strlen matching command */
104 p_arg = p_cb->p_cmd_buf + strlen(p_cb->p_at_tbl[idx].p_cmd);
105 if (p_arg > p_end) {
106 (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, false, nullptr);
107 return;
108 }
109
110 /* if no argument */
111 if (p_arg[0] == 0) {
112 arg_type = BTA_AG_AT_NONE;
113 } else if (p_arg[0] == '?' && p_arg[1] == 0) {
114 /* else if arg is '?' and it is last character */
115 /* we have a read */
116 arg_type = BTA_AG_AT_READ;
117 } else if (p_arg[0] == '=' && p_arg[1] != 0) {
118 /* else if arg is '=' */
119 if (p_arg[1] == '?' && p_arg[2] == 0) {
120 /* we have a test */
121 arg_type = BTA_AG_AT_TEST;
122 } else {
123 /* we have a set */
124 arg_type = BTA_AG_AT_SET;
125
126 /* skip past '=' */
127 p_arg++;
128 }
129 } else
130 /* else it is freeform argument */
131 {
132 arg_type = BTA_AG_AT_FREE;
133 }
134
135 /* if arguments match command capabilities */
136 if ((arg_type & p_cb->p_at_tbl[idx].arg_type) != 0) {
137 /* if it's a set integer check max, min range */
138 if (arg_type == BTA_AG_AT_SET && p_cb->p_at_tbl[idx].fmt == BTA_AG_AT_INT) {
139 if (com::android::bluetooth::flags::bta_ag_cmd_brsf_allow_uint32()) {
140 if (p_cb->p_at_tbl[idx].command_id == BTA_AG_LOCAL_EVT_BRSF) {
141 // Per HFP v1.9 BRSF could be 32-bit integer and we should ignore
142 // all reserved bits rather than responding ERROR.
143 long long int_arg_ll = std::atoll(p_arg);
144 if (int_arg_ll >= (1ll << 32) || int_arg_ll < 0) {
145 int_arg_ll = -1;
146 }
147
148 // Ignore reserved bits. 0xfff because there are 12 defined bits.
149 if (int_arg_ll > 0 && (int_arg_ll & (~0xfffll))) {
150 log::warn("BRSF: reserved bit is set: 0x{:x}", int_arg_ll);
151 int_arg_ll &= 0xfffll;
152 }
153
154 int_arg = static_cast<int16_t>(int_arg_ll);
155 } else {
156 int_arg = utl_str2int(p_arg);
157 }
158 } else {
159 int_arg = utl_str2int(p_arg);
160 }
161 if (int_arg < (int16_t)p_cb->p_at_tbl[idx].min ||
162 int_arg > (int16_t)p_cb->p_at_tbl[idx].max) {
163 /* arg out of range; error */
164 log::warn("arg out of range");
165 (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, false, nullptr);
166 } else {
167 (*p_cb->p_cmd_cback)((tBTA_AG_SCB*)p_cb->p_user, p_cb->p_at_tbl[idx].command_id, arg_type,
168 p_arg, p_end, int_arg);
169 }
170 } else {
171 (*p_cb->p_cmd_cback)((tBTA_AG_SCB*)p_cb->p_user, p_cb->p_at_tbl[idx].command_id, arg_type,
172 p_arg, p_end, int_arg);
173 }
174 } else {
175 /* else error */
176 log::warn("Incoming arg type 0x{:x} does not match cmd arg type 0x{:x}", arg_type,
177 p_cb->p_at_tbl[idx].arg_type);
178 (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, false, nullptr);
179 }
180 } else {
181 /* else no match call error callback */
182 log::warn("Unmatched command index {}", idx);
183 (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, true, p_cb->p_cmd_buf);
184 }
185 }
186
187 /******************************************************************************
188 *
189 * Function bta_ag_at_parse
190 *
191 * Description Parse AT commands. This function will take the input
192 * character string and parse it for AT commands according to
193 * the AT command table passed in the control block.
194 *
195 *
196 * Returns void
197 *
198 *****************************************************************************/
bta_ag_at_parse(tBTA_AG_AT_CB * p_cb,char * p_buf,uint16_t len)199 void bta_ag_at_parse(tBTA_AG_AT_CB* p_cb, char* p_buf, uint16_t len) {
200 int i = 0;
201 char* p_save;
202
203 if (p_cb->p_cmd_buf == nullptr) {
204 p_cb->p_cmd_buf = (char*)osi_malloc(p_cb->cmd_max_len);
205 p_cb->cmd_pos = 0;
206 }
207
208 for (i = 0; i < len;) {
209 while (p_cb->cmd_pos < p_cb->cmd_max_len - 1 && i < len) {
210 /* Skip null characters between AT commands. */
211 if ((p_cb->cmd_pos == 0) && (p_buf[i] == 0)) {
212 i++;
213 continue;
214 }
215
216 p_cb->p_cmd_buf[p_cb->cmd_pos] = p_buf[i++];
217 if (p_cb->p_cmd_buf[p_cb->cmd_pos] == '\r' || p_cb->p_cmd_buf[p_cb->cmd_pos] == '\n') {
218 p_cb->p_cmd_buf[p_cb->cmd_pos] = 0;
219 if ((p_cb->cmd_pos > 2) && (p_cb->p_cmd_buf[0] == 'A' || p_cb->p_cmd_buf[0] == 'a') &&
220 (p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't')) {
221 p_save = p_cb->p_cmd_buf;
222 char* p_end = p_cb->p_cmd_buf + p_cb->cmd_pos;
223 p_cb->p_cmd_buf += 2;
224 bta_ag_process_at(p_cb, p_end);
225 p_cb->p_cmd_buf = p_save;
226 }
227
228 p_cb->cmd_pos = 0;
229
230 } else if (p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A || p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B) {
231 p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
232 (*p_cb->p_err_cback)((tBTA_AG_SCB*)p_cb->p_user, true, p_cb->p_cmd_buf);
233 p_cb->cmd_pos = 0;
234 } else {
235 ++p_cb->cmd_pos;
236 }
237 }
238
239 if (i < len) {
240 p_cb->cmd_pos = 0;
241 }
242 }
243 }
244