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. \n
14 *
15 * Description: Provides AT command source \n
16 */
17
18 #include "at_base.h"
19 #include "at_cmd.h"
20
21 typedef struct at_cmd_list_t {
22 const at_cmd_entry_t *table;
23 uint32_t len;
24 struct at_cmd_list_t *next;
25 } at_cmd_list_t;
26
27 at_cmd_list_t *g_at_cmd_list = NULL;
28 uint32_t g_at_cmd_struct_max_size = 0;
29
at_cmd_get_entry_total(void)30 uint32_t at_cmd_get_entry_total(void)
31 {
32 uint32_t nr_size = 0;
33 at_cmd_list_t *list = g_at_cmd_list;
34
35 if (list == NULL) {
36 return 0;
37 }
38
39 while (list != NULL) {
40 for (uint32_t index = 0; index < list->len; index++) {
41 nr_size++;
42 }
43 list = list->next;
44 }
45 return nr_size;
46 }
47
at_cmd_get_all_entrys(const at_cmd_entry_t ** entrys,uint32_t cnt)48 uint32_t at_cmd_get_all_entrys(const at_cmd_entry_t **entrys, uint32_t cnt)
49 {
50 uint32_t total = 0;
51 at_cmd_list_t *list = g_at_cmd_list;
52
53 if (list == NULL) {
54 return 0;
55 }
56
57 while (list != NULL) {
58 for (uint32_t index = 0; index < list->len; index++) {
59 entrys[total] = &list->table[index];
60 total++;
61 if (total > cnt) {
62 return total;
63 }
64 }
65 list = list->next;
66 }
67 return total;
68 }
69
at_cmd_table_add(const at_cmd_entry_t * table,uint32_t length)70 static errcode_t at_cmd_table_add(const at_cmd_entry_t *table, uint32_t length)
71 {
72 at_cmd_list_t *tail = g_at_cmd_list;
73 at_cmd_list_t *new_node = at_malloc(sizeof(at_cmd_list_t));
74 if (new_node == NULL) {
75 return ERRCODE_MALLOC;
76 }
77 new_node->table = table;
78 new_node->len = length;
79 new_node->next = NULL;
80
81 if (tail == NULL) {
82 g_at_cmd_list = new_node;
83 return ERRCODE_SUCC;
84 }
85
86 while (tail->next != NULL) {
87 tail = tail->next;
88 }
89 tail->next = new_node;
90
91 return ERRCODE_SUCC;
92 }
93
at_cmd_get_name_length(const char * str)94 static uint16_t at_cmd_get_name_length(const char* str)
95 {
96 uint16_t len = 0;
97 const char* ch = str;
98
99 while ((*ch >= 'A' && *ch <= 'Z') ||
100 (*ch >= 'a' && *ch <= 'z') ||
101 (*ch >= '0' && *ch <= '9')) {
102 len++;
103 ch++;
104 }
105
106 return len;
107 }
108
at_cmd_find_entry(char * str,uint16_t * offset)109 const at_cmd_entry_t* at_cmd_find_entry(char *str, uint16_t *offset)
110 {
111 at_cmd_list_t *list = g_at_cmd_list;
112 if (list == NULL || str == NULL) {
113 return NULL;
114 }
115
116 char *name = str + *offset;
117 uint16_t name_len = at_cmd_get_name_length(name);
118 at_base_toupper(name, name_len);
119 while (list != NULL) {
120 for (uint32_t index = 0; index < list->len; index++) {
121 if (list->table[index].name == NULL) { return NULL; }
122 if ((strncmp(list->table[index].name, name, name_len) == 0) &&
123 (name_len == strlen(list->table[index].name))) {
124 *offset = *offset + name_len;
125 return &list->table[index];
126 }
127 }
128 list = list->next;
129 }
130 return NULL;
131 }
132
133 #ifdef CONFIG_AT_SUPPORT_CMD_TABLE_CHECK
at_cmd_find_entry_by_name(const char * name)134 const at_cmd_entry_t* at_cmd_find_entry_by_name(const char *name)
135 {
136 at_cmd_list_t *list = g_at_cmd_list;
137 if (list == NULL) {
138 return NULL;
139 }
140
141 while (list != NULL) {
142 for (uint32_t index = 0; index < list->len; index++) {
143 if (strcmp((char*)list->table[index].name, name) == 0) {
144 return &list->table[index];
145 }
146 }
147 list = list->next;
148 }
149 return NULL;
150 }
151
at_cmd_entry_name_check(const char * name)152 static errcode_t at_cmd_entry_name_check(const char *name)
153 {
154 uint16_t name_len = (uint16_t)strlen(name);
155 if (name_len > AT_CMD_NAME_MAX_LENGTH) {
156 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
157 }
158
159 for (uint16_t index = 0; index < name_len; index++) {
160 if (name[index] < 'A' || name[index] > 'Z') {
161 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
162 }
163 }
164 return ERRCODE_SUCC;
165 }
166
at_cmd_entry_syntax_int_check(const at_para_parse_syntax_t * syntax)167 static errcode_t at_cmd_entry_syntax_int_check(const at_para_parse_syntax_t *syntax)
168 {
169 if (((syntax->attribute & (AT_SYNTAX_ATTR_AT_MIN_VALUE | AT_SYNTAX_ATTR_AT_MAX_VALUE)) != 0) &&
170 ((syntax->attribute & AT_SYNTAX_ATTR_LIST_VALUE) != 0)) {
171 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
172 }
173 return ERRCODE_SUCC;
174 }
175
at_cmd_entry_syntax_string_check(const at_para_parse_syntax_t * syntax)176 static errcode_t at_cmd_entry_syntax_string_check(const at_para_parse_syntax_t *syntax)
177 {
178 if (((syntax->attribute & AT_SYNTAX_ATTR_MAX_LENGTH) != 0) &&
179 ((syntax->attribute & AT_SYNTAX_ATTR_LIST_VALUE) != 0)) {
180 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
181 }
182 return ERRCODE_SUCC;
183 }
184
at_cmd_entry_syntax_bit_string_check(const at_para_parse_syntax_t * syntax)185 static errcode_t at_cmd_entry_syntax_bit_string_check(const at_para_parse_syntax_t *syntax)
186 {
187 if (((syntax->attribute & AT_SYNTAX_ATTR_AT_MAX_VALUE) != 0) &&
188 ((syntax->attribute & AT_SYNTAX_ATTR_LIST_VALUE) != 0)) {
189 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
190 }
191 return ERRCODE_SUCC;
192 }
193
at_cmd_entry_syntax_check(const at_para_parse_syntax_t * syntax)194 static errcode_t at_cmd_entry_syntax_check(const at_para_parse_syntax_t *syntax)
195 {
196 errcode_t err_ret = ERRCODE_SUCC;
197 switch (syntax->type) {
198 case AT_SYNTAX_TYPE_INT:
199 err_ret = at_cmd_entry_syntax_int_check(syntax);
200 break;
201 case AT_SYNTAX_TYPE_STRING:
202 err_ret = at_cmd_entry_syntax_string_check(syntax);
203 break;
204 case AT_SYNTAX_TYPE_BIT_STRING:
205 err_ret = at_cmd_entry_syntax_bit_string_check(syntax);
206 break;
207 default:
208 break;
209 }
210 return err_ret;
211 }
212
at_cmd_entry_syntax_table_check(const at_para_parse_syntax_t * syntax)213 static errcode_t at_cmd_entry_syntax_table_check(const at_para_parse_syntax_t *syntax)
214 {
215 errcode_t err_ret;
216 if (syntax == NULL) {
217 return ERRCODE_SUCC;
218 }
219
220 for (uint16_t index = 0; index < AT_PARA_MAX_NUM; index++) {
221 err_ret = at_cmd_entry_syntax_check(&syntax[index]);
222 if (err_ret != ERRCODE_SUCC) {
223 return err_ret;
224 }
225 if (syntax[index].last == true) {
226 break;
227 }
228 }
229
230 return ERRCODE_SUCC;
231 }
232
at_cmd_entry_table_check(const at_cmd_entry_t * table)233 static errcode_t at_cmd_entry_table_check(const at_cmd_entry_t *table)
234 {
235 if (table->cmd == NULL &&
236 table->set == NULL &&
237 table->read == NULL &&
238 #ifdef CONFIG_AT_SUPPORT_QUERY
239 table->query == NULL &&
240 #endif
241 table->test == NULL) {
242 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
243 }
244
245 if (table->set != NULL && table->syntax == NULL) {
246 return ERRCODE_AT_CMD_TABLE_PARA_ERROR;
247 }
248
249 return ERRCODE_SUCC;
250 }
251
at_cmd_entry_check(const at_cmd_entry_t * table)252 static errcode_t at_cmd_entry_check(const at_cmd_entry_t *table)
253 {
254 errcode_t err_ret;
255 err_ret = at_cmd_entry_table_check(table);
256 if (err_ret != ERRCODE_SUCC) {
257 return err_ret;
258 }
259
260 err_ret = at_cmd_entry_name_check(table->name);
261 if (err_ret != ERRCODE_SUCC) {
262 return err_ret;
263 }
264
265 err_ret = at_cmd_entry_syntax_table_check(table->syntax);
266 if (err_ret != ERRCODE_SUCC) {
267 return err_ret;
268 }
269 return ERRCODE_SUCC;
270 }
271
at_cmd_table_check(const at_cmd_entry_t * table,uint32_t length)272 static errcode_t at_cmd_table_check(const at_cmd_entry_t *table, uint32_t length)
273 {
274 errcode_t ret = ERRCODE_SUCC;
275 for (uint32_t index = 0; index < length; index++) {
276 if (at_cmd_find_entry_by_name(table[index].name) != NULL) {
277 return ERRCODE_AT_CMD_REPEAT;
278 }
279
280 ret = at_cmd_entry_check(&table[index]);
281 if (ret != ERRCODE_SUCC) {
282 return ret;
283 }
284 }
285 return ERRCODE_SUCC;
286 }
287 #endif
288
at_cmd_get_max_struct_size(void)289 uint32_t at_cmd_get_max_struct_size(void)
290 {
291 return g_at_cmd_struct_max_size;
292 }
293
uapi_at_cmd_table_register(const at_cmd_entry_t * table,uint32_t len,uint32_t struct_max_size)294 errcode_t uapi_at_cmd_table_register(const at_cmd_entry_t *table, uint32_t len,
295 uint32_t struct_max_size)
296 {
297 errcode_t ret;
298 if (table == NULL || len == 0) {
299 return ERRCODE_INVALID_PARAM;
300 }
301 #ifdef CONFIG_AT_SUPPORT_CMD_TABLE_CHECK
302 ret = at_cmd_table_check(table, len);
303 if (ret != ERRCODE_SUCC) {
304 return ret;
305 }
306 #endif
307 ret = at_cmd_table_add(table, len);
308 if ((ret == ERRCODE_SUCC) && (g_at_cmd_struct_max_size < struct_max_size)) {
309 g_at_cmd_struct_max_size = struct_max_size;
310 }
311 return ret;
312 }
313