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