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