1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 */
26 #include "at_utils.h"
27
28 #include <td_base.h>
29 #include <securec.h>
30 #include <string.h>
31 #include <soc_osal.h>
32 #include <stdarg.h>
33
34 #include "at.h"
35
36 #ifdef __cplusplus
37 #if __cplusplus
38 extern "C" {
39 #endif
40 #endif
41
42 #define EXT_AT_SSID_MAX_LEN 32
43 #define EXT_AT_CUSTOM_PKT_MAX_LEN 2800
44
at_param_null_check(td_s32 argc,TD_CONST td_char ** argv)45 td_u32 at_param_null_check(td_s32 argc, TD_CONST td_char **argv)
46 {
47 for (td_s32 i = 0; i < argc; i++) {
48 if (argv[i] == TD_NULL) {
49 return EXT_ERR_FAILURE;
50 }
51 }
52 return EXT_ERR_SUCCESS;
53 }
54
integer_check(TD_CONST td_char * val)55 td_u32 integer_check(TD_CONST td_char *val)
56 {
57 td_u32 len;
58 td_u32 i;
59 td_char *buf = (td_char *)val;
60 if (buf == TD_NULL) {
61 return EXT_ERR_FAILURE;
62 }
63 len = strlen(buf);
64 if ((*buf == '0') && (len != 1)) {
65 return EXT_ERR_FAILURE;
66 }
67 for (i = 0; i < len; i++) {
68 if ((*buf < '0') || (*buf > '9')) {
69 return EXT_ERR_FAILURE;
70 }
71 buf++;
72 }
73 return EXT_ERR_SUCCESS;
74 }
75
alnum_check(TD_CONST td_char * val)76 td_u32 alnum_check(TD_CONST td_char *val)
77 {
78 td_u32 i;
79 td_u32 len;
80 td_char *buf = (td_char *)val;
81 if (buf == TD_NULL) {
82 return EXT_ERR_FAILURE;
83 }
84 len = strlen(buf);
85 if ((*buf == '0') && (len != 1)) {
86 return EXT_ERR_FAILURE;
87 }
88 for (i = 0; i < len; i++) {
89 if (((*buf >= '0') && (*buf <= '9')) || ((*buf >= 'a') && (*buf <= 'f')) ||
90 ((*buf >= 'A') && (*buf <= 'F'))) {
91 buf++;
92 } else {
93 return EXT_ERR_FAILURE;
94 }
95 }
96 return EXT_ERR_SUCCESS;
97 }
98
at_check_mac_elem(TD_CONST td_char elem)99 TD_PRV td_u32 at_check_mac_elem(TD_CONST td_char elem)
100 {
101 if (elem >= '0' && elem <= '9') {
102 return EXT_ERR_SUCCESS;
103 } else if (elem >= 'A' && elem <= 'F') {
104 return EXT_ERR_SUCCESS;
105 } else if (elem >= 'a' && elem <= 'f') {
106 return EXT_ERR_SUCCESS;
107 } else if (elem == ':') {
108 return EXT_ERR_SUCCESS;
109 }
110
111 return EXT_ERR_FAILURE;
112 }
113
cmd_strtoaddr(TD_CONST td_char * param,td_uchar * mac_addr,td_u32 addr_len)114 td_u32 cmd_strtoaddr(TD_CONST td_char *param, td_uchar *mac_addr, td_u32 addr_len)
115 {
116 td_u32 cnt;
117 td_char *tmp1 = (td_char *)param;
118 td_char *tmp2 = TD_NULL;
119 td_char *tmp3 = TD_NULL;
120
121 for (cnt = 0; cnt < 17; cnt++) { /* 17 */
122 if (at_check_mac_elem(param[cnt]) != EXT_ERR_SUCCESS) {
123 return EXT_ERR_FAILURE;
124 }
125 }
126
127 for (cnt = 0; cnt < (addr_len - 1); cnt++) {
128 tmp2 = (char*)strsep(&tmp1, ":");
129 if (tmp2 == TD_NULL) {
130 return EXT_ERR_AT_INVALID_PARAMETER;
131 }
132 mac_addr[cnt] = (td_uchar)strtoul(tmp2, &tmp3, 16); /* 16 */
133 }
134
135 if (tmp1 == TD_NULL) {
136 return EXT_ERR_AT_INVALID_PARAMETER;
137 }
138 mac_addr[cnt] = (td_uchar)strtoul(tmp1, &tmp3, 16); /* 16 */
139 return EXT_ERR_SUCCESS;
140 }
141
at_strrchr(TD_CONST char * src,int c)142 TD_PRV char *at_strrchr(TD_CONST char *src, int c)
143 {
144 return strrchr(src, c);
145 }
146
at_strlen(TD_CONST char * src)147 TD_PRV td_u32 at_strlen(TD_CONST char *src)
148 {
149 return strlen(src);
150 }
151
at_dup_binstr(TD_CONST char * src,td_u32 len)152 TD_PRV char *at_dup_binstr(TD_CONST char *src, td_u32 len)
153 {
154 char *res = TD_NULL;
155 int ret;
156
157 if (src == TD_NULL) {
158 return TD_NULL;
159 }
160 res = osal_kmalloc((td_ulong)(len + 1), OSAL_GFP_KERNEL);
161 if (res == TD_NULL) {
162 return TD_NULL;
163 }
164 ret = memcpy_s(res, len, src, len);
165 if (ret != EOK) {
166 osal_kfree(res);
167 res = TD_NULL;
168 return TD_NULL;
169 }
170 res[len] = '\0';
171
172 return res;
173 }
174
at_hex2num(char c)175 TD_PRV int at_hex2num(char c)
176 {
177 if (c >= '0' && c <= '9') {
178 return c - '0';
179 }
180 if (c >= 'a' && c <= 'f') {
181 return c - 'a' + 10; /* add 10 */
182 }
183 if (c >= 'A' && c <= 'F') {
184 return c - 'A' + 10; /* add 10 */
185 }
186 return -1;
187 }
188
at_hex2byte(TD_CONST char * hex)189 TD_PRV int at_hex2byte(TD_CONST char *hex)
190 {
191 int a, b;
192 TD_CONST char *tmp_hex = hex;
193 a = at_hex2num(*tmp_hex++);
194 if (a < 0) {
195 return -1;
196 }
197 b = at_hex2num(*tmp_hex++);
198 if (b < 0) {
199 return -1;
200 }
201 return ((td_u32)a << 4) | (td_u32)b; /* 4 */
202 }
203
204 /**
205 * at_hexstr2bin - Convert ASCII hex string into binary data
206 * @hex: ASCII hex string (e.g., "01ab")
207 * @buf: Buffer for the binary data
208 * @len: Length of the text to convert in bytes (of buf); hex will be double
209 * this size
210 * Returns: 0 on success, -1 on failure (invalid hex string)
211 */
at_hexstr2bin(TD_CONST char * hex,td_u8 * buf,td_u32 len)212 TD_PRV int at_hexstr2bin(TD_CONST char *hex, td_u8 *buf, td_u32 len)
213 {
214 td_u32 i;
215 TD_CONST char *ipos = hex;
216 td_u8 *opos = buf;
217
218 for (i = 0; i < len; i++) {
219 int a = at_hex2byte(ipos);
220 if (a < 0) {
221 return -1;
222 }
223 *opos++ = a;
224 ipos += 2; /* add 2 */
225 }
226 return 0;
227 }
228
at_printf_decode_slash(td_u8 * buf,TD_CONST char ** str_pos,td_u32 * str_len)229 TD_PRV td_void at_printf_decode_slash(td_u8 *buf, TD_CONST char **str_pos, td_u32 *str_len)
230 {
231 TD_CONST char *pos = *str_pos;
232 td_u32 len = *str_len;
233 int val;
234
235 pos++;
236 switch (*pos) {
237 case '\\':
238 case '"':
239 buf[len++] = *pos;
240 pos++;
241 break;
242 case 'n':
243 buf[len++] = '\n';
244 pos++;
245 break;
246 case 'r':
247 buf[len++] = '\r';
248 pos++;
249 break;
250 case 't':
251 buf[len++] = '\t';
252 pos++;
253 break;
254 case 'e':
255 buf[len++] = '\033';
256 pos++;
257 break;
258 case 'x':
259 pos++;
260 val = at_hex2byte(pos);
261 if (val < 0) {
262 val = at_hex2num(*pos);
263 if (val < 0) {
264 break;
265 }
266 buf[len++] = val;
267 pos++;
268 } else {
269 buf[len++] = val;
270 pos += 2; /* add 2 */
271 }
272 break;
273 case '0':
274 case '1':
275 case '2':
276 case '3':
277 case '4':
278 case '5':
279 case '6':
280 case '7':
281 val = *pos++ - '0';
282 if (*pos >= '0' && *pos <= '7') {
283 val = val * 8 + (*pos++ - '0'); /* 8 */
284 }
285 if (*pos >= '0' && *pos <= '7') {
286 val = val * 8 + (*pos++ - '0'); /* 8 */
287 }
288 buf[len++] = val;
289 break;
290 default:
291 break;
292 }
293
294 *str_pos = pos;
295 *str_len = len;
296 }
297
at_printf_decode(td_u8 * buf,td_u32 maxlen,TD_CONST char * str)298 TD_PRV td_u32 at_printf_decode(td_u8 *buf, td_u32 maxlen, TD_CONST char *str)
299 {
300 TD_CONST char *pos = str;
301 td_u32 len = 0;
302
303 while (*pos) {
304 if (len + 1 >= maxlen) {
305 break;
306 }
307 switch (*pos) {
308 case '\\':
309 at_printf_decode_slash(buf, &pos, &len);
310 break;
311 default:
312 buf[len++] = *pos++;
313 break;
314 }
315 }
316 if (maxlen > len) {
317 buf[len] = '\0';
318 }
319
320 return len;
321 }
322
at_parse_string_normal(TD_CONST char * value,td_u32 * len)323 TD_PRV char *at_parse_string_normal(TD_CONST char *value, td_u32 *len)
324 {
325 TD_CONST char *pos = TD_NULL;
326 TD_CONST char *src = value;
327 char *str = TD_NULL;
328
329 src++;
330 pos = at_strrchr(src, '"');
331 if (pos == TD_NULL || pos[1] != '\0') {
332 return TD_NULL;
333 }
334 *len = pos - src;
335 str = at_dup_binstr(src, *len);
336 if (str == TD_NULL) {
337 return TD_NULL;
338 }
339 return str;
340 }
341
at_parse_string_with_p(TD_CONST char * value,td_u32 * len)342 TD_PRV char *at_parse_string_with_p(TD_CONST char *value, td_u32 *len)
343 {
344 TD_CONST char *pos = TD_NULL;
345 TD_CONST char *src = value;
346 char *tstr = TD_NULL;
347 char *str = TD_NULL;
348 td_u32 tlen;
349
350 src += 2; /* add 2 */
351 pos = at_strrchr(src, '"');
352 if (pos == TD_NULL || pos[1] != '\0') {
353 return TD_NULL;
354 }
355 tlen = pos - src;
356 tstr = at_dup_binstr(src, tlen);
357 if (tstr == TD_NULL) {
358 return TD_NULL;
359 }
360
361 str = osal_kmalloc((td_ulong)(tlen + 1), OSAL_GFP_KERNEL);
362 if (str == TD_NULL) {
363 osal_kfree(tstr);
364 return TD_NULL;
365 }
366
367 *len = at_printf_decode((td_u8 *)str, tlen + 1, tstr);
368 osal_kfree(tstr);
369 return str;
370 }
371
at_parse_string_other(TD_CONST char * value,td_u32 * len)372 TD_PRV char *at_parse_string_other(TD_CONST char *value, td_u32 *len)
373 {
374 td_u8 *str = TD_NULL;
375 td_u32 tlen;
376 td_u32 hlen = at_strlen(value);
377 if (hlen & 1) {
378 return TD_NULL;
379 }
380 tlen = hlen / 2; /* 2 */
381 str = osal_kmalloc((td_ulong)(tlen + 1), OSAL_GFP_KERNEL);
382 if (str == TD_NULL) {
383 return TD_NULL;
384 }
385 if (at_hexstr2bin(value, str, tlen)) {
386 osal_kfree((char*)str);
387 return TD_NULL;
388 }
389 str[tlen] = '\0';
390 *len = tlen;
391 return (char *)str;
392 }
393
at_parse_string(TD_CONST char * value,td_u32 * len)394 char *at_parse_string(TD_CONST char *value, td_u32 *len)
395 {
396 if (len == TD_NULL) {
397 return TD_NULL;
398 }
399 if (*value == '"') {
400 return at_parse_string_normal(value, len);
401 } else if (*value == 'P' && value[1] == '"') {
402 return at_parse_string_with_p(value, len);
403 } else {
404 return at_parse_string_other(value, len);
405 }
406 }
407
convert_bin_to_dec(td_s32 pbin)408 td_s32 convert_bin_to_dec(td_s32 pbin)
409 {
410 td_s32 result = 0;
411
412 while (pbin)
413 {
414 result += pbin % 2;
415 pbin /= 2;
416 }
417
418 return result;
419 }
420
421 /*****************************************************************************
422 函 数 名 : at_str_to_hex
423 功能描述 : 字符串转16进制
424 *****************************************************************************/
at_str_to_hex(TD_CONST td_char * param,td_u32 len,unsigned char * value)425 td_void at_str_to_hex(TD_CONST td_char *param, td_u32 len, unsigned char *value)
426 {
427 td_u16 index;
428 if (param == TD_NULL || len > EXT_AT_CUSTOM_PKT_MAX_LEN) {
429 return;
430 }
431 for (index = 0; index < len; index++) {
432 /* 每2位字符转为一个十六进制,第一位乘以16 */
433 value[index / 2] = (unsigned char)(value[index / 2] * 16 * (index % 2) + at_hex2num(*param));
434 param++;
435 }
436 }
437
438 #ifdef __cplusplus
439 #if __cplusplus
440 }
441 #endif
442 #endif
443