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 */ 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 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 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 */ 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 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 230 int rt_wlan_cfg_get_num(void) 231 { 232 rt_wlan_cfg_init(); 233 234 return cfg_cache->num; 235 } 236 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 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 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 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 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 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