1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-08-06 tyx the first version
9 */
10
11 #include <rtthread.h>
12 #include <dev_wlan_cfg.h>
13
14 #define DBG_TAG "WLAN.cfg"
15 #ifdef RT_WLAN_CFG_DEBUG
16 #define DBG_LVL DBG_LOG
17 #else
18 #define DBG_LVL DBG_INFO
19 #endif /* RT_WLAN_CFG_DEBUG */
20 #include <rtdbg.h>
21
22 #ifdef RT_WLAN_CFG_ENABLE
23
24 #define WLAN_CFG_LOCK() (rt_mutex_take(&cfg_mutex, RT_WAITING_FOREVER))
25 #define WLAN_CFG_UNLOCK() (rt_mutex_release(&cfg_mutex))
26
27 #if RT_WLAN_CFG_INFO_MAX < 1
28 #error "The minimum configuration is 1"
29 #endif
30
31 struct cfg_save_info_head
32 {
33 rt_uint32_t magic;
34 rt_uint32_t len;
35 rt_uint32_t num;
36 rt_uint32_t crc;
37 };
38
39 struct rt_wlan_cfg_des
40 {
41 rt_uint32_t num;
42 struct rt_wlan_cfg_info *cfg_info;
43 };
44
45 static struct rt_wlan_cfg_des *cfg_cache;
46 static const struct rt_wlan_cfg_ops *cfg_ops;
47 static struct rt_mutex cfg_mutex;
48
49 /*
50 * CRC16_CCITT
51 */
rt_wlan_cal_crc(rt_uint8_t * buff,int len)52 static rt_uint16_t rt_wlan_cal_crc(rt_uint8_t *buff, int len)
53 {
54 rt_uint16_t wCRCin = 0x0000;
55 rt_uint16_t wCPoly = 0x1021;
56 rt_uint8_t wChar = 0;
57
58 while (len--)
59 {
60 int i;
61
62 wChar = *(buff++);
63 wCRCin ^= (wChar << 8);
64
65 for (i = 0; i < 8; i++)
66 {
67 if (wCRCin & 0x8000)
68 wCRCin = (wCRCin << 1) ^ wCPoly;
69 else
70 wCRCin = wCRCin << 1;
71 }
72 }
73 return wCRCin;
74 }
75
rt_wlan_cfg_init(void)76 void rt_wlan_cfg_init(void)
77 {
78 /* init cache memory */
79 if (cfg_cache == RT_NULL)
80 {
81 cfg_cache = rt_malloc(sizeof(struct rt_wlan_cfg_des));
82 if (cfg_cache != RT_NULL)
83 {
84 rt_memset(cfg_cache, 0, sizeof(struct rt_wlan_cfg_des));
85 }
86 /* init mutex lock */
87 rt_mutex_init(&cfg_mutex, "wlan_cfg", RT_IPC_FLAG_PRIO);
88 }
89 }
90
rt_wlan_cfg_set_ops(const struct rt_wlan_cfg_ops * ops)91 void rt_wlan_cfg_set_ops(const struct rt_wlan_cfg_ops *ops)
92 {
93 rt_wlan_cfg_init();
94
95 WLAN_CFG_LOCK();
96 /* save ops pointer */
97 cfg_ops = ops;
98 WLAN_CFG_UNLOCK();
99 }
100
101 /* save config data */
rt_wlan_cfg_cache_save(void)102 rt_err_t rt_wlan_cfg_cache_save(void)
103 {
104 rt_err_t err = RT_EOK;
105 struct cfg_save_info_head *info_pkg;
106 int len = 0;
107
108 if ((cfg_ops == RT_NULL) || (cfg_ops->write_cfg == RT_NULL))
109 return RT_EOK;
110
111 WLAN_CFG_LOCK();
112 len = sizeof(struct cfg_save_info_head) + sizeof(struct rt_wlan_cfg_info) * cfg_cache->num;
113 info_pkg = rt_malloc(len);
114 if (info_pkg == RT_NULL)
115 {
116 WLAN_CFG_UNLOCK();
117 return -RT_ENOMEM;
118 }
119 info_pkg->magic = RT_WLAN_CFG_MAGIC;
120 info_pkg->len = len;
121 info_pkg->num = cfg_cache->num;
122 /* CRC */
123 info_pkg->crc = rt_wlan_cal_crc((rt_uint8_t *)cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * cfg_cache->num);
124 rt_memcpy(((rt_uint8_t *)info_pkg) + sizeof(struct cfg_save_info_head),
125 cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * cfg_cache->num);
126 if (cfg_ops->write_cfg(info_pkg, len) != len)
127 err = -RT_ERROR;
128 rt_free(info_pkg);
129 WLAN_CFG_UNLOCK();
130 return err;
131 }
132
rt_wlan_cfg_cache_refresh(void)133 rt_err_t rt_wlan_cfg_cache_refresh(void)
134 {
135 int len = 0, i, j;
136 struct cfg_save_info_head *head;
137 void *data;
138 struct rt_wlan_cfg_info *t_info, *cfg_info;
139 rt_uint32_t crc;
140 rt_bool_t equal_flag;
141
142 /* cache is full! exit */
143 if (cfg_cache == RT_NULL || cfg_cache->num >= RT_WLAN_CFG_INFO_MAX)
144 return -RT_ERROR;
145
146 /* check callback */
147 if ((cfg_ops == RT_NULL) ||
148 (cfg_ops->get_len == RT_NULL) ||
149 (cfg_ops->read_cfg == RT_NULL))
150 return -RT_ERROR;
151
152 WLAN_CFG_LOCK();
153 /* get data len */
154 if ((len = cfg_ops->get_len()) <= 0)
155 {
156 WLAN_CFG_UNLOCK();
157 return -RT_ERROR;
158 }
159
160 head = rt_malloc(len);
161 if (head == RT_NULL)
162 {
163 WLAN_CFG_UNLOCK();
164 return -RT_ERROR;
165 }
166 /* get data */
167 if (cfg_ops->read_cfg(head, len) != len)
168 {
169 rt_free(head);
170 WLAN_CFG_UNLOCK();
171 return -RT_ERROR;
172 }
173 /* get config */
174 data = ((rt_uint8_t *)head) + sizeof(struct cfg_save_info_head);
175 crc = rt_wlan_cal_crc((rt_uint8_t *)data, len - sizeof(struct cfg_save_info_head));
176 LOG_D("head->magic:0x%08x RT_WLAN_CFG_MAGIC:0x%08x", head->magic, RT_WLAN_CFG_MAGIC);
177 LOG_D("head->len:%d len:%d", head->len, len);
178 LOG_D("head->num:%d num:%d", head->num, (len - sizeof(struct cfg_save_info_head)) / sizeof(struct rt_wlan_cfg_info));
179 LOG_D("hred->crc:0x%04x crc:0x%04x", head->crc, crc);
180 /* check */
181 if ((head->magic != RT_WLAN_CFG_MAGIC) ||
182 (head->len != len) ||
183 (head->num != (len - sizeof(struct cfg_save_info_head)) / sizeof(struct rt_wlan_cfg_info)) ||
184 (head->crc != crc))
185 {
186 rt_free(head);
187 WLAN_CFG_UNLOCK();
188 return -RT_ERROR;
189 }
190
191 /* remove duplicate config */
192 cfg_info = (struct rt_wlan_cfg_info *)data;
193 for (i = 0; i < head->num; i++)
194 {
195 equal_flag = RT_FALSE;
196 for (j = 0; j < cfg_cache->num; j++)
197 {
198 if ((cfg_cache->cfg_info[j].info.ssid.len == cfg_info[i].info.ssid.len) &&
199 (rt_memcmp(&cfg_cache->cfg_info[j].info.ssid.val[0], &cfg_info[i].info.ssid.val[0],
200 cfg_cache->cfg_info[j].info.ssid.len) == 0) &&
201 (rt_memcmp(&cfg_cache->cfg_info[j].info.bssid[0], &cfg_info[i].info.bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0))
202 {
203 equal_flag = RT_TRUE;
204 break;
205 }
206 }
207
208 if (cfg_cache->num >= RT_WLAN_CFG_INFO_MAX)
209 {
210 break;
211 }
212
213 if (equal_flag == RT_FALSE)
214 {
215 t_info = rt_realloc(cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * (cfg_cache->num + 1));
216 if (t_info == RT_NULL)
217 {
218 rt_free(head);
219 WLAN_CFG_UNLOCK();
220 return -RT_ERROR;
221 }
222 cfg_cache->cfg_info = t_info;
223 cfg_cache->cfg_info[cfg_cache->num] = cfg_info[i];
224 cfg_cache->num ++;
225 }
226 }
227
228 rt_free(head);
229 WLAN_CFG_UNLOCK();
230 return RT_EOK;
231 }
232
rt_wlan_cfg_get_num(void)233 int rt_wlan_cfg_get_num(void)
234 {
235 rt_wlan_cfg_init();
236
237 return cfg_cache->num;
238 }
239
rt_wlan_cfg_read(struct rt_wlan_cfg_info * cfg_info,int num)240 int rt_wlan_cfg_read(struct rt_wlan_cfg_info *cfg_info, int num)
241 {
242 rt_wlan_cfg_init();
243
244 if ((cfg_info == RT_NULL) || (num <= 0))
245 return 0;
246 /* copy data */
247 WLAN_CFG_LOCK();
248 num = cfg_cache->num > num ? num : cfg_cache->num;
249 rt_memcpy(&cfg_cache->cfg_info[0], cfg_info, sizeof(struct rt_wlan_cfg_info) * num);
250 WLAN_CFG_UNLOCK();
251
252 return num;
253 }
254
rt_wlan_cfg_save(struct rt_wlan_cfg_info * cfg_info)255 rt_err_t rt_wlan_cfg_save(struct rt_wlan_cfg_info *cfg_info)
256 {
257 rt_err_t err = RT_EOK;
258 struct rt_wlan_cfg_info *t_info;
259 int idx = -1, i = 0;
260
261 rt_wlan_cfg_init();
262
263 /* parameter check */
264 if ((cfg_info == RT_NULL) || (cfg_info->info.ssid.len == 0))
265 {
266 return -RT_EINVAL;
267 }
268 /* if (iteam == cache) exit */
269 WLAN_CFG_LOCK();
270 for (i = 0; i < cfg_cache->num; i++)
271 {
272 if ((cfg_cache->cfg_info[i].info.ssid.len == cfg_info->info.ssid.len) &&
273 (rt_memcmp(&cfg_cache->cfg_info[i].info.ssid.val[0], &cfg_info->info.ssid.val[0],
274 cfg_cache->cfg_info[i].info.ssid.len) == 0) &&
275 (rt_memcmp(&cfg_cache->cfg_info[i].info.bssid[0], &cfg_info->info.bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0))
276 {
277 idx = i;
278 break;
279 }
280 }
281
282 if ((idx == 0) && (cfg_cache->cfg_info[i].key.len == cfg_info->key.len) &&
283 (rt_memcmp(&cfg_cache->cfg_info[i].key.val[0], &cfg_info->key.val[0], cfg_info->key.len) == 0))
284 {
285 WLAN_CFG_UNLOCK();
286 return RT_EOK;
287 }
288
289 /* not find iteam with cache, Add iteam to the head */
290 if ((idx == -1) && (cfg_cache->num < RT_WLAN_CFG_INFO_MAX))
291 {
292 t_info = rt_realloc(cfg_cache->cfg_info, sizeof(struct rt_wlan_cfg_info) * (cfg_cache->num + 1));
293 if (t_info == RT_NULL)
294 {
295 WLAN_CFG_UNLOCK();
296 return -RT_ENOMEM;
297 }
298 cfg_cache->cfg_info = t_info;
299 cfg_cache->num ++;
300 }
301
302 /* move cache info */
303 i = (i >= RT_WLAN_CFG_INFO_MAX ? RT_WLAN_CFG_INFO_MAX - 1 : i);
304 for (; i; i--)
305 {
306 cfg_cache->cfg_info[i] = cfg_cache->cfg_info[i - 1];
307 }
308 /* add iteam to head */
309 cfg_cache->cfg_info[i] = *cfg_info;
310 WLAN_CFG_UNLOCK();
311
312 /* save info to flash */
313 err = rt_wlan_cfg_cache_save();
314
315 return err;
316 }
317
rt_wlan_cfg_read_index(struct rt_wlan_cfg_info * cfg_info,int index)318 int rt_wlan_cfg_read_index(struct rt_wlan_cfg_info *cfg_info, int index)
319 {
320 rt_wlan_cfg_init();
321
322 if ((cfg_info == RT_NULL) || (index < 0))
323 return 0;
324
325 WLAN_CFG_LOCK();
326 if (index >= cfg_cache->num)
327 {
328 WLAN_CFG_UNLOCK();
329 return 0;
330 }
331 /* copy data */
332 *cfg_info = cfg_cache->cfg_info[index];
333 WLAN_CFG_UNLOCK();
334 return 1;
335 }
336
rt_wlan_cfg_delete_index(int index)337 int rt_wlan_cfg_delete_index(int index)
338 {
339 struct rt_wlan_cfg_info *cfg_info;
340 int i;
341
342 rt_wlan_cfg_init();
343
344 if (index < 0)
345 return -1;
346
347 WLAN_CFG_LOCK();
348 if (index >= cfg_cache->num)
349 {
350 WLAN_CFG_UNLOCK();
351 return -1;
352 }
353
354 /* malloc new mem */
355 cfg_info = rt_malloc(sizeof(struct rt_wlan_cfg_info) * (cfg_cache->num - 1));
356 if (cfg_info == RT_NULL)
357 {
358 WLAN_CFG_UNLOCK();
359 return -1;
360 }
361 /* copy data to new mem */
362 for (i = 0; i < cfg_cache->num; i++)
363 {
364 if (i < index)
365 {
366 cfg_info[i] = cfg_cache->cfg_info[i];
367 }
368 else if (i > index)
369 {
370 cfg_info[i - 1] = cfg_cache->cfg_info[i];
371 }
372 }
373 rt_free(cfg_cache->cfg_info);
374 cfg_cache->cfg_info = cfg_info;
375 cfg_cache->num --;
376 WLAN_CFG_UNLOCK();
377
378 return 0;
379 }
380
rt_wlan_cfg_delete_all(void)381 void rt_wlan_cfg_delete_all(void)
382 {
383 rt_wlan_cfg_init();
384
385 /* delete all iteam */
386 WLAN_CFG_LOCK();
387 cfg_cache->num = 0;
388 rt_free(cfg_cache->cfg_info);
389 cfg_cache->cfg_info = RT_NULL;
390 WLAN_CFG_UNLOCK();
391 }
392
rt_wlan_cfg_dump(void)393 void rt_wlan_cfg_dump(void)
394 {
395 int index = 0;
396 struct rt_wlan_info *info;
397 struct rt_wlan_key *key;
398 char *security;
399
400 rt_wlan_cfg_init();
401
402 rt_kprintf(" SSID PASSWORD MAC security chn\n");
403 rt_kprintf("------------------------------- ------------------------------- ----------------- -------------- ---\n");
404 for (index = 0; index < cfg_cache->num; index ++)
405 {
406 info = &cfg_cache->cfg_info[index].info;
407 key = &cfg_cache->cfg_info[index].key;
408
409 if (info->ssid.len)
410 rt_kprintf("%-32.32s", &info->ssid.val[0]);
411 else
412 rt_kprintf("%-32.32s", " ");
413
414 if (key->len)
415 rt_kprintf("%-32.32s", &key->val[0]);
416 else
417 rt_kprintf("%-32.32s", " ");
418
419 rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x ",
420 info->bssid[0],
421 info->bssid[1],
422 info->bssid[2],
423 info->bssid[3],
424 info->bssid[4],
425 info->bssid[5]
426 );
427 switch (info->security)
428 {
429 case SECURITY_OPEN:
430 security = "OPEN";
431 break;
432 case SECURITY_WEP_PSK:
433 security = "WEP_PSK";
434 break;
435 case SECURITY_WEP_SHARED:
436 security = "WEP_SHARED";
437 break;
438 case SECURITY_WPA_TKIP_PSK:
439 security = "WPA_TKIP_PSK";
440 break;
441 case SECURITY_WPA_AES_PSK:
442 security = "WPA_AES_PSK";
443 break;
444 case SECURITY_WPA2_AES_PSK:
445 security = "WPA2_AES_PSK";
446 break;
447 case SECURITY_WPA2_TKIP_PSK:
448 security = "WPA2_TKIP_PSK";
449 break;
450 case SECURITY_WPA2_MIXED_PSK:
451 security = "WPA2_MIXED_PSK";
452 break;
453 case SECURITY_WPS_OPEN:
454 security = "WPS_OPEN";
455 break;
456 case SECURITY_WPS_SECURE:
457 security = "WPS_SECURE";
458 break;
459 default:
460 security = "UNKNOWN";
461 break;
462 }
463 rt_kprintf("%-14.14s ", security);
464 rt_kprintf("%3d \n", info->channel);
465 }
466 }
467
468 #endif
469