• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
15 
16 #include <hi_stdlib.h>
17 #include <at.h>
18 #include <at_cmd.h>
19 #include <at_parse.h>
20 #include "hi_config.h"
21 
22 #include "stdio.h"
23 #include "string.h"
24 #include "malloc.h"
25 #include "stdarg.h"
26 #include "securec.h"
27 
28 #ifdef __cplusplus
29 #if __cplusplus
30 extern "C" {
31 #endif
32 #endif
33 
34 #define AT_SSID_MAX_LEN 32
35 
36 at_cmd_ctrl g_at_ctrl = {
37     .at_state = AT_IDLE,
38     .send_len = 0,
39     .trans_len = 0,
40     .is_first_recv_data = HI_TRUE,
41     .is_first_over_data = HI_TRUE,
42     .is_recv_end_char_flag = 0,
43 };
44 
at_cmd_excute(const at_cmd_func * cmd_func,at_cmd_attr * cmd_parsed)45 hi_u32 at_cmd_excute(const at_cmd_func *cmd_func, at_cmd_attr *cmd_parsed)
46 {
47     hi_u32 ret;
48 
49     if (cmd_func == HI_NULL || cmd_parsed == HI_NULL) {
50         return HI_ERR_FAILURE;
51     }
52 
53     if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_TEST) {
54         if (cmd_func->at_test_cmd) {
55             ret = cmd_func->at_test_cmd((hi_s32)cmd_parsed->at_param_cnt,
56                 (const hi_char **)&cmd_parsed->param_array[0]);
57         } else {
58             at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
59             ret = HI_ERR_FAILURE;
60             at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
61         }
62     } else if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_QUERY) {
63         if (cmd_func->at_query_cmd) {
64             ret = cmd_func->at_query_cmd((hi_s32)cmd_parsed->at_param_cnt,
65                 (const hi_char **)&cmd_parsed->param_array[0]);
66         } else {
67             at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
68             ret = HI_ERR_FAILURE;
69             at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
70         }
71     } else if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_SETUP) {
72         if (cmd_func->at_setup_cmd) {
73             ret = cmd_func->at_setup_cmd((hi_s32)cmd_parsed->at_param_cnt,
74                 (const hi_char **)&cmd_parsed->param_array[0]);
75         } else {
76             at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
77             ret = HI_ERR_FAILURE;
78             at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
79         }
80     } else if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_EXE) {
81         if (cmd_func->at_exe_cmd) {
82             ret = cmd_func->at_exe_cmd((hi_s32)cmd_parsed->at_param_cnt,
83                 (const hi_char **)&cmd_parsed->param_array[0]);
84         } else {
85             at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
86             ret = HI_ERR_FAILURE;
87             at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
88         }
89     } else {
90         at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
91         ret = HI_ERR_FAILURE;
92         at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
93     }
94 
95     return ret;
96 }
97 
at_get_cmd_name(hi_char * cmd_line,at_cmd_attr * cmd_parsed)98 static hi_void at_get_cmd_name(hi_char *cmd_line, at_cmd_attr *cmd_parsed)
99 {
100     hi_s8 n = 0;
101 
102     for (hi_u8 i = AT_CMD_MAX_LEN; i > 0; i--) {
103         if ((*cmd_line == '\0') || (*cmd_line == '=') || (*cmd_line == '?')) {
104             cmd_parsed->at_cmd_len = n;
105             return;
106         } else {
107             cmd_parsed->cmd_name[n] = *cmd_line;
108             cmd_line++;
109             n++;
110         }
111     }
112 
113     cmd_parsed->at_cmd_len = -1;
114     memset_s(cmd_parsed->cmd_name, AT_CMD_MAX_LEN, 0, AT_CMD_MAX_LEN);
115 }
116 
at_func_process(hi_char * out_cmd_line,at_cmd_attr * cmd_parsed)117 hi_u32 at_func_process(hi_char *out_cmd_line, at_cmd_attr *cmd_parsed)
118 {
119     hi_u32 ret;
120     at_cmd_func *cmd_func = HI_NULL;
121     at_get_cmd_name(out_cmd_line, cmd_parsed);
122     if (cmd_parsed->at_cmd_len != (-1)) {
123         cmd_func = at_find_proc_func(cmd_parsed);
124     }
125 
126     if (cmd_func != HI_NULL) {
127         ret = at_cmd_parse(out_cmd_line, cmd_parsed);
128         if (ret != HI_ERR_SUCCESS) {
129             at_printf("%s line: %d PARSE CMD FAIL!\r\n", __FUNCTION__, __LINE__);
130             return ret;
131         }
132 
133         ret = at_cmd_excute(cmd_func, cmd_parsed);
134     } else {
135         ret = HI_ERR_FAILURE;
136         at_printf("%s line: %d COMMAND NOT SUPPORT!\r\n", __FUNCTION__, __LINE__);
137     }
138 
139     return ret;
140 }
141 
at_cmd_process(const hi_char * at_cmd_line)142 hi_u32 at_cmd_process(const hi_char *at_cmd_line)
143 {
144     hi_u32 at_cmd_line_len;
145     hi_char *out_cmd_line = HI_NULL;
146     at_cmd_attr cmd_parsed = {0};
147     hi_u32 ret;
148 
149     AT_ENTER;
150     if (at_cmd_line == HI_NULL) {
151         at_printf("INVALID NULL CMD!\r\n");
152         AT_RESPONSE_ERROR;
153         return HI_ERR_FAILURE;
154     }
155 
156     at_cmd_line_len = (hi_u32)strlen(at_cmd_line) + 1;
157     out_cmd_line = (hi_char *)hi_malloc(HI_MOD_ID_SAL_DFX, at_cmd_line_len);
158     if (out_cmd_line == HI_NULL) {
159         at_printf("%s line%d NO ENOUGH MEMORY!\r\n", __FUNCTION__, __LINE__);
160         AT_RESPONSE_ERROR;
161         return HI_ERR_FAILURE;
162     }
163     memset_s(out_cmd_line, at_cmd_line_len, 0, at_cmd_line_len);
164 
165     ret = (hi_u32)strncpy_s(out_cmd_line, at_cmd_line_len, at_cmd_line, at_cmd_line_len - 1);
166     if (ret != EOK) {
167         at_printf("%s,%d strncpy_s failed, err:%d!\n", __FUNCTION__, __LINE__, ret);
168         AT_RESPONSE_ERROR;
169         hi_free(HI_MOD_ID_SAL_DFX, out_cmd_line);
170         return HI_ERR_FAILURE;
171     }
172     out_cmd_line[at_cmd_line_len - 1] = '\0';
173 
174     ret = at_func_process(out_cmd_line, &cmd_parsed);
175     if (ret != HI_ERR_SUCCESS && ret != HI_ERR_RECVING) {
176         at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
177         AT_RESPONSE_ERROR;
178     } else if (ret == HI_ERR_RECVING) {
179         g_at_ctrl.at_state = AT_DATA_RECVING;
180     } else {
181         g_at_ctrl.at_state = AT_IDLE;
182     }
183 
184     hi_free(HI_MOD_ID_SAL_DFX, out_cmd_line);
185     out_cmd_line = HI_NULL;
186 
187     return ret;
188 }
189 
at_param_null_check(hi_s32 argc,const hi_char ** argv)190 hi_u32 at_param_null_check(hi_s32 argc, const hi_char **argv)
191 {
192     for (hi_s32 i = 0; i < argc; i++) {
193         if (argv[i] == HI_NULL) {
194             return HI_ERR_FAILURE;
195         }
196     }
197     return HI_ERR_SUCCESS;
198 }
199 
integer_check(const hi_char * val)200 hi_u32 integer_check(const hi_char *val)
201 {
202     hi_u32 len;
203     hi_u32 i;
204     hi_char *buf = (hi_char *)val;
205     if (buf == HI_NULL) {
206         return HI_ERR_FAILURE;
207     }
208     len = strlen(buf);
209     if ((*buf == '0') && (len != 1)) {
210         return HI_ERR_FAILURE;
211     }
212     for (i = 0; i < len; i++) {
213         if ((*buf < '0') || (*buf > '9')) {
214             return HI_ERR_FAILURE;
215         }
216         buf++;
217     }
218     return HI_ERR_SUCCESS;
219 }
220 
at_check_mac_elem(const hi_char elem)221 static hi_u32 at_check_mac_elem(const hi_char elem)
222 {
223     if (elem >= '0' && elem <= '9') {
224         return HI_ERR_SUCCESS;
225     } else if (elem >= 'A' && elem <= 'F') {
226         return HI_ERR_SUCCESS;
227     } else if (elem >= 'a' && elem <= 'f') {
228         return HI_ERR_SUCCESS;
229     } else if (elem == ':') {
230         return HI_ERR_SUCCESS;
231     }
232 
233     return HI_ERR_FAILURE;
234 }
235 
cmd_strtoaddr(const hi_char * param,hi_uchar * mac_addr,hi_u32 addr_len)236 hi_u32 cmd_strtoaddr(const hi_char *param, hi_uchar *mac_addr, hi_u32 addr_len)
237 {
238     hi_u32 cnt;
239     hi_char *tmp1 = (hi_char *)param;
240     hi_char *tmp2 = NULL;
241     hi_char *tmp3 = NULL;
242 
243     for (cnt = 0; cnt < 17; cnt++) {    /* 17 */
244         if (at_check_mac_elem(param[cnt]) != HI_ERR_SUCCESS) {
245             return HI_ERR_FAILURE;
246         }
247     }
248 
249     for (cnt = 0; cnt < (addr_len - 1); cnt++) {
250         tmp2 = (char*)strsep(&tmp1, ":");
251         if (tmp2 == NULL) {
252             return HI_ERR_APP_INVALID_PARAMETER;
253         }
254         mac_addr[cnt] = (hi_uchar)strtoul(tmp2, &tmp3, 16); /* 16 */
255     }
256 
257     if (tmp1 == NULL) {
258         return HI_ERR_APP_INVALID_PARAMETER;
259     }
260     mac_addr[cnt] = (hi_uchar)strtoul(tmp1, &tmp3, 16); /* 16 */
261     return HI_ERR_SUCCESS;
262 }
263 
at_strrchr(const char * src,int c)264 char *at_strrchr(const char *src, int c)
265 {
266     return strrchr(src, c);
267 }
268 
at_malloc(size_t size)269 void *at_malloc(size_t size)
270 {
271     if (size > 4096) {  /* max alloc mem 4096 */
272         return NULL;
273     }
274     void *ptr = malloc(size);
275     return ptr;
276 }
277 
at_free(char * ptr)278 void at_free(char *ptr)
279 {
280     if (ptr) {
281         free(ptr);
282     }
283 }
284 
at_strlen(const char * src)285 size_t at_strlen(const char *src)
286 {
287     return strlen(src);
288 }
289 
at_pading(char * str,size_t size,const char * format,...)290 int at_pading(char *str, size_t size, const char *format, ...)
291 {
292     va_list ap = NULL;
293     int ret;
294 
295     va_start(ap, format);
296     ret = vsnprintf_s(str, AT_SSID_MAX_LEN * 4 + 1, size, format, ap); /* 4 length */
297     va_end(ap);
298     if (size > 0) {
299         str[size - 1] = '\0';
300     }
301     return ret;
302 }
303 
at_dup_binstr(const char * src,size_t len)304 char* at_dup_binstr(const char *src, size_t len)
305 {
306     char *res = NULL;
307     int ret;
308 
309     if (src == NULL) {
310         return NULL;
311     }
312     res = at_malloc(len + 1);
313     if (res == NULL) {
314         return NULL;
315     }
316     ret = memcpy_s(res, len, src, len);
317     if (ret != EOK) {
318         at_free(res);
319         res = NULL;
320         return NULL;
321     }
322     res[len] = '\0';
323 
324     return res;
325 }
326 
at_hex2num(char c)327 static int at_hex2num(char c)
328 {
329     if (c >= '0' && c <= '9') {
330         return c - '0';
331     }
332     if (c >= 'a' && c <= 'f') {
333         return c - 'a' + 10;    /* add 10 */
334     }
335     if (c >= 'A' && c <= 'F') {
336         return c - 'A' + 10;    /* add 10 */
337     }
338     return -1;
339 }
340 
at_hex2byte(const char * hex)341 int at_hex2byte(const char *hex)
342 {
343     int a, b;
344     a = at_hex2num(*hex++);
345     if (a < 0) {
346         return -1;
347     }
348     b = at_hex2num(*hex++);
349     if (b < 0) {
350         return -1;
351     }
352     return ((hi_u32)a << 4) | (hi_u32)b;    /* 4 */
353 }
354 
355 /**
356  * at_hexstr2bin - Convert ASCII hex string into binary data
357  * @hex: ASCII hex string (e.g., "01ab")
358  * @buf: Buffer for the binary data
359  * @len: Length of the text to convert in bytes (of buf); hex will be double
360  * this size
361  * Returns: 0 on success, -1 on failure (invalid hex string)
362  */
at_hexstr2bin(const char * hex,hi_u8 * buf,size_t len)363 int at_hexstr2bin(const char *hex, hi_u8 *buf, size_t len)
364 {
365     size_t i;
366     const char *ipos = hex;
367     hi_u8 *opos = buf;
368 
369     for (i = 0; i < len; i++) {
370         int a = at_hex2byte(ipos);
371         if (a < 0) {
372             return -1;
373         }
374         *opos++ = a;
375         ipos += 2;  /* add 2 */
376     }
377     return 0;
378 }
379 
at_printf_encode(char * txt,size_t maxlen,const hi_u8 * data,size_t len)380 void at_printf_encode(char *txt, size_t maxlen, const hi_u8 *data, size_t len)
381 {
382     char *end = txt + maxlen;
383     size_t i;
384 
385     for (i = 0; i < len; i++) {
386         if (txt + 4 >= end) {   /* add 4 */
387             break;
388         }
389 
390         switch (data[i]) {
391             case '\"':
392                 *txt++ = '\\';
393                 *txt++ = '\"';
394                 break;
395             case '\\':
396                 *txt++ = '\\';
397                 *txt++ = '\\';
398                 break;
399             case '\033':
400                 *txt++ = '\\';
401                 *txt++ = 'e';
402                 break;
403             case '\n':
404                 *txt++ = '\\';
405                 *txt++ = 'n';
406                 break;
407             case '\r':
408                 *txt++ = '\\';
409                 *txt++ = 'r';
410                 break;
411             case '\t':
412                 *txt++ = '\\';
413                 *txt++ = 't';
414                 break;
415             default:
416                 if (data[i] >= 32 && data[i] <= 126) {  /* range [32,126] */
417                     *txt++ = data[i];
418                 } else {
419                     txt += at_pading(txt, end - txt, "\\x%02x", data[i]);
420                 }
421                 break;
422         }
423     }
424 
425     *txt = '\0';
426 }
427 
at_printf_decode_slash(hi_u8 * buf,const char ** str_pos,size_t * str_len)428 hi_void at_printf_decode_slash(hi_u8 *buf, const char **str_pos, size_t *str_len)
429 {
430     const char *pos = *str_pos;
431     size_t len = *str_len;
432     int val;
433 
434     pos++;
435     switch (*pos) {
436         case '\\':
437             buf[len++] = '\\';
438             pos++;
439             break;
440         case '"':
441             buf[len++] = '"';
442             pos++;
443             break;
444         case 'n':
445             buf[len++] = '\n';
446             pos++;
447             break;
448         case 'r':
449             buf[len++] = '\r';
450             pos++;
451             break;
452         case 't':
453             buf[len++] = '\t';
454             pos++;
455             break;
456         case 'e':
457             buf[len++] = '\033';
458             pos++;
459             break;
460         case 'x':
461             pos++;
462             val = at_hex2byte(pos);
463             if (val < 0) {
464                 val = at_hex2num(*pos);
465                 if (val < 0) {
466                     break;
467                 }
468                 buf[len++] = val;
469                 pos++;
470             } else {
471                 buf[len++] = val;
472                 pos += 2;   /* add 2 */
473             }
474             break;
475         case '0':
476         case '1':
477         case '2':
478         case '3':
479         case '4':
480         case '5':
481         case '6':
482         case '7':
483             val = *pos++ - '0';
484             if (*pos >= '0' && *pos <= '7') {
485                 val = val * 8 + (*pos++ - '0'); /* 8 */
486             }
487             if (*pos >= '0' && *pos <= '7') {
488                 val = val * 8 + (*pos++ - '0'); /* 8 */
489             }
490             buf[len++] = val;
491             break;
492         default:
493             break;
494     }
495 
496     *str_pos = pos;
497     *str_len = len;
498 }
499 
at_printf_decode(hi_u8 * buf,size_t maxlen,const char * str)500 size_t at_printf_decode(hi_u8 *buf, size_t maxlen, const char *str)
501 {
502     const char *pos = str;
503     size_t len = 0;
504 
505     while (*pos) {
506         if (len + 1 >= maxlen) {
507             break;
508         }
509         switch (*pos) {
510             case '\\':
511                 at_printf_decode_slash(buf, &pos, &len);
512                 break;
513             default:
514                 buf[len++] = *pos++;
515                 break;
516         }
517     }
518     if (maxlen > len) {
519         buf[len] = '\0';
520     }
521 
522     return len;
523 }
524 
at_parse_string_normal(const char * value,size_t * len)525 char* at_parse_string_normal(const char *value, size_t *len)
526 {
527     const char *pos = NULL;
528     char *str = NULL;
529 
530     value++;
531     pos = at_strrchr(value, '"');
532     if (pos == NULL || pos[1] != '\0') {
533         return NULL;
534     }
535     *len = pos - value;
536     str = at_dup_binstr(value, *len);
537     if (str == NULL) {
538         return NULL;
539     }
540     return str;
541 }
542 
at_parse_string_with_p(const char * value,size_t * len)543 char* at_parse_string_with_p(const char *value, size_t *len)
544 {
545     const char *pos = NULL;
546     char *tstr = NULL;
547     char *str = NULL;
548     size_t tlen;
549 
550     value += 2;     /* add 2 */
551     pos = at_strrchr(value, '"');
552     if (pos == NULL || pos[1] != '\0') {
553         return NULL;
554     }
555     tlen = pos - value;
556     tstr = at_dup_binstr(value, tlen);
557     if (tstr == NULL) {
558         return NULL;
559     }
560 
561     str = at_malloc(tlen + 1);
562     if (str == NULL) {
563         at_free(tstr);
564         return NULL;
565     }
566 
567     *len = at_printf_decode((hi_u8 *) str, tlen + 1, tstr);
568     at_free(tstr);
569 
570     return str;
571 }
572 
at_parse_string_other(const char * value,size_t * len)573 char* at_parse_string_other(const char *value, size_t *len)
574 {
575     hi_u8 *str = NULL;
576     size_t tlen;
577     size_t hlen = at_strlen(value);
578     if (hlen & 1) {
579         return NULL;
580     }
581     tlen = hlen / 2;    /* 2 */
582     str = at_malloc(tlen + 1);
583     if (str == NULL) {
584         return NULL;
585     }
586     if (at_hexstr2bin(value, str, tlen)) {
587         at_free((char*)str);
588         return NULL;
589     }
590     str[tlen] = '\0';
591     *len = tlen;
592     return (char *) str;
593 }
594 
595 
at_parse_string(const char * value,size_t * len)596 char* at_parse_string(const char *value, size_t *len)
597 {
598     if (len == HI_NULL) {
599         return HI_NULL;
600     }
601     if (*value == '"') {
602         return at_parse_string_normal(value, len);
603     } else if (*value == 'P' && value[1] == '"') {
604         return at_parse_string_with_p(value, len);
605     } else {
606         return at_parse_string_other(value, len);
607     }
608 }
609 
610 /**
611  * at_ssid_txt - Convert SSID to a printable string
612  * @ssid: SSID (32-octet string)
613  * @ssid_len: Length of ssid in octets
614  * Returns: Pointer to a printable string
615  *
616  * This function can be used to convert SSIDs into printable form. In most
617  * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
618  * does not limit the used character set, so anything could be used in an SSID.
619  *
620  * This function uses a static buffer, so only one call can be used at the
621  * time, i.e., this is not re-entrant and the returned buffer must be used
622  * before calling this again.
623  */
at_ssid_txt(const hi_u8 * ssid,size_t ssid_len)624 const char* at_ssid_txt(const hi_u8 *ssid, size_t ssid_len)
625 {
626     static char ssid_txt[AT_SSID_MAX_LEN * 4 + 1]; /* 4 */
627 
628     if (ssid == NULL) {
629         ssid_txt[0] = '\0';
630         return ssid_txt;
631     }
632 
633     at_printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
634     return ssid_txt;
635 }
636 
637 #ifdef __cplusplus
638 #if __cplusplus
639     }
640 #endif
641 #endif
642