1 /*
2 * File : wifi_config.c
3 * This file is part of RT-Thread RTOS
4 * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Change Logs:
21 * Date Author Notes
22 * 2018-09-04 ZeroFree first implementation
23 * 2019-06-14 armink add easyflash v4.0 support
24 */
25
26 #include <rtthread.h>
27
28 #ifdef BSP_USING_WIFI
29
30 #include <dev_wlan_mgnt.h>
31 #include <dev_wlan_cfg.h>
32 #include <dev_wlan_prot.h>
33
34 #include <easyflash.h>
35 #include <fal.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39
40 #if (EF_SW_VERSION_NUM < 0x40000)
41
42 static char *str_base64_encode_len(const void *src, char *out, int input_length);
43 static int str_base64_decode(const char *data, int input_length, char *decoded_data);
44
45 static const unsigned char base64_table[65] =
46 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
47
48 static const char base64_decode_table[256] =
49 {
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
53 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
55 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
57 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 };
67
str_base64_encode_len(const void * src,char * out,int len)68 static char *str_base64_encode_len(const void *src, char *out, int len)
69 {
70 unsigned char *pos;
71 const unsigned char *end, *in;
72 size_t olen;
73
74 olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
75 olen += olen / 72; /* line feeds */
76 olen++; /* nul termination */
77
78 end = (const unsigned char *)src + len;
79 in = (const unsigned char *)src;
80 pos = (unsigned char *)out;
81 while (end - in >= 3)
82 {
83 *pos++ = base64_table[in[0] >> 2];
84 *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
85 *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
86 *pos++ = base64_table[in[2] & 0x3f];
87 in += 3;
88 }
89
90 if (end - in)
91 {
92 *pos++ = base64_table[in[0] >> 2];
93
94 if (end - in == 1)
95 {
96 *pos++ = base64_table[(in[0] & 0x03) << 4];
97 *pos++ = '=';
98 }
99 else
100 {
101 *pos++ = base64_table[((in[0] & 0x03) << 4) |
102 (in[1] >> 4)];
103 *pos++ = base64_table[(in[1] & 0x0f) << 2];
104 }
105 *pos++ = '=';
106 }
107
108 *pos = '\0';
109 return (char *)out;
110 }
111
112 /*
113 * return: length, 0 is error.
114 */
str_base64_decode(const char * data,int input_length,char * decoded_data)115 static int str_base64_decode(const char *data, int input_length, char *decoded_data)
116 {
117 int out_len;
118 int i, j;
119
120 if (input_length % 4 != 0) return 0;
121
122 out_len = input_length / 4 * 3;
123
124 if (data[input_length - 1] == '=') out_len--;
125 if (data[input_length - 2] == '=') out_len--;
126
127 for (i = 0, j = 0; i < input_length;)
128 {
129 uint32_t sextet_a = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
130 uint32_t sextet_b = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
131 uint32_t sextet_c = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
132 uint32_t sextet_d = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
133
134 uint32_t triple = (sextet_a << 3 * 6)
135 + (sextet_b << 2 * 6)
136 + (sextet_c << 1 * 6)
137 + (sextet_d << 0 * 6);
138
139 if (j < out_len) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
140 if (j < out_len) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
141 if (j < out_len) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
142 }
143
144 return out_len;
145 }
146
read_cfg(void * buff,int len)147 static int read_cfg(void *buff, int len)
148 {
149 char *wlan_cfg_info = RT_NULL;
150
151 wlan_cfg_info = ef_get_env("wlan_cfg_info");
152 if (wlan_cfg_info != RT_NULL)
153 {
154 str_base64_decode(wlan_cfg_info, rt_strlen(wlan_cfg_info), buff);
155 return len;
156 }
157 else
158 {
159 return 0;
160 }
161 }
162
get_len(void)163 static int get_len(void)
164 {
165 int len;
166 char *wlan_cfg_len = RT_NULL;
167
168 wlan_cfg_len = ef_get_env("wlan_cfg_len");
169 if (wlan_cfg_len == RT_NULL)
170 {
171 len = 0;
172 }
173 else
174 {
175 len = atoi(wlan_cfg_len);
176 }
177
178 return len;
179 }
180
write_cfg(void * buff,int len)181 static int write_cfg(void *buff, int len)
182 {
183 char wlan_cfg_len[12] = {0};
184 char *base64_buf = RT_NULL;
185
186 base64_buf = rt_malloc(len * 4 / 3 + 4); /* 3-byte blocks to 4-byte, and the end. */
187 if (base64_buf == RT_NULL)
188 {
189 return -RT_ENOMEM;
190 }
191 rt_memset(base64_buf, 0, len);
192
193 /* interger to string */
194 sprintf(wlan_cfg_len, "%d", len);
195 /* set and store the wlan config lengths to Env */
196 ef_set_env("wlan_cfg_len", wlan_cfg_len);
197 str_base64_encode_len(buff, base64_buf, len);
198 /* set and store the wlan config information to Env */
199 ef_set_env("wlan_cfg_info", base64_buf);
200 ef_save_env();
201 rt_free(base64_buf);
202
203 return len;
204 }
205
206 #else
207
read_cfg(void * buff,int len)208 static int read_cfg(void *buff, int len)
209 {
210 size_t saved_len;
211
212 ef_get_env_blob("wlan_cfg_info", buff, len, &saved_len);
213 if (saved_len == 0)
214 {
215 return 0;
216 }
217 return len;
218 }
219
get_len(void)220 static int get_len(void)
221 {
222 int len;
223 size_t saved_len;
224
225 ef_get_env_blob("wlan_cfg_len", &len, sizeof(len), &saved_len);
226 if (saved_len == 0)
227 {
228 return 0;
229 }
230
231 return len;
232 }
233
write_cfg(void * buff,int len)234 static int write_cfg(void *buff, int len)
235 {
236 /* set and store the wlan config lengths to Env */
237 ef_set_env_blob("wlan_cfg_len", &len, sizeof(len));
238
239 /* set and store the wlan config information to Env */
240 ef_set_env_blob("wlan_cfg_info", buff, len);
241
242 return len;
243 }
244
245 #endif /* (EF_SW_VERSION_NUM < 0x40000) */
246
247 static const struct rt_wlan_cfg_ops ops =
248 {
249 read_cfg,
250 get_len,
251 write_cfg
252 };
253
wlan_autoconnect_init(void)254 void wlan_autoconnect_init(void)
255 {
256 fal_init();
257 easyflash_init();
258
259 rt_wlan_cfg_set_ops(&ops);
260 rt_wlan_cfg_cache_refresh();
261 }
262
263 #endif
264