1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lwip/netifapi.h"
17 #include "wifi_hotspot.h"
18 #include "wifi_hotspot_config.h"
19 #include "td_base.h"
20 #include "td_type.h"
21 #include "stdlib.h"
22 #include "uart.h"
23 #include "cmsis_os2.h"
24 #include "app_init.h"
25 #include "soc_osal.h"
26
27 #define WIFI_IFNAME_MAX_SIZE 16
28 #define WIFI_MAX_SSID_LEN 33
29 #define WIFI_SCAN_AP_LIMIT 64
30 #define WIFI_MAC_LEN 6
31 #define WIFI_STA_SAMPLE_LOG "[WIFI_STA_SAMPLE]"
32 #define WIFI_NOT_AVALLIABLE 0
33 #define WIFI_AVALIABE 1
34 #define WIFI_GET_IP_MAX_COUNT 300
35
36 #define WIFI_TASK_PRIO (osPriority_t)(13)
37 #define WIFI_TASK_DURATION_MS 2000
38 #define WIFI_TASK_STACK_SIZE 0x1000
39
40 static td_void wifi_scan_state_changed(td_s32 state, td_s32 size);
41 static td_void wifi_connection_changed(td_s32 state, const wifi_linked_info_stru *info, td_s32 reason_code);
42
43 wifi_event_stru wifi_event_cb = {
44 .wifi_event_connection_changed = wifi_connection_changed,
45 .wifi_event_scan_state_changed = wifi_scan_state_changed,
46 };
47
48 enum {
49 WIFI_STA_SAMPLE_INIT = 0, /* 0:初始态 */
50 WIFI_STA_SAMPLE_SCANING, /* 1:扫描中 */
51 WIFI_STA_SAMPLE_SCAN_DONE, /* 2:扫描完成 */
52 WIFI_STA_SAMPLE_FOUND_TARGET, /* 3:匹配到目标AP */
53 WIFI_STA_SAMPLE_CONNECTING, /* 4:连接中 */
54 WIFI_STA_SAMPLE_CONNECT_DONE, /* 5:关联成功 */
55 WIFI_STA_SAMPLE_GET_IP, /* 6:获取IP */
56 } wifi_state_enum;
57
58 static td_u8 g_wifi_state = WIFI_STA_SAMPLE_INIT;
59
60 /*****************************************************************************
61 STA 扫描事件回调函数
62 *****************************************************************************/
wifi_scan_state_changed(td_s32 state,td_s32 size)63 static td_void wifi_scan_state_changed(td_s32 state, td_s32 size)
64 {
65 UNUSED(state);
66 UNUSED(size);
67 PRINT("%s::Scan done!.\r\n", WIFI_STA_SAMPLE_LOG);
68 g_wifi_state = WIFI_STA_SAMPLE_SCAN_DONE;
69 return;
70 }
71
72 /*****************************************************************************
73 STA 关联事件回调函数
74 *****************************************************************************/
wifi_connection_changed(td_s32 state,const wifi_linked_info_stru * info,td_s32 reason_code)75 static td_void wifi_connection_changed(td_s32 state, const wifi_linked_info_stru *info, td_s32 reason_code)
76 {
77 UNUSED(info);
78 UNUSED(reason_code);
79
80 if (state == WIFI_NOT_AVALLIABLE) {
81 PRINT("%s::Connect fail!. try agin !\r\n", WIFI_STA_SAMPLE_LOG);
82 g_wifi_state = WIFI_STA_SAMPLE_INIT;
83 } else {
84 PRINT("%s::Connect succ!.\r\n", WIFI_STA_SAMPLE_LOG);
85 g_wifi_state = WIFI_STA_SAMPLE_CONNECT_DONE;
86 }
87 }
88
89 /*****************************************************************************
90 STA 匹配目标AP
91 *****************************************************************************/
example_get_match_network(wifi_sta_config_stru * expected_bss)92 td_s32 example_get_match_network(wifi_sta_config_stru *expected_bss)
93 {
94 td_s32 ret;
95 td_u32 num = 64; /* 64:扫描到的Wi-Fi网络数量 */
96 td_char expected_ssid[] = "my_softAP";
97 td_char key[] = "my_password"; /* 待连接的网络接入密码 */
98 td_bool find_ap = TD_FALSE;
99 td_u8 bss_index;
100 /* 获取扫描结果 */
101 td_u32 scan_len = sizeof(wifi_scan_info_stru) * WIFI_SCAN_AP_LIMIT;
102 wifi_scan_info_stru *result = osal_kmalloc(scan_len, OSAL_GFP_ATOMIC);
103 if (result == TD_NULL) {
104 return -1;
105 }
106 memset_s(result, scan_len, 0, scan_len);
107 ret = wifi_sta_get_scan_info(result, &num);
108 if (ret != 0) {
109 osal_kfree(result);
110 return -1;
111 }
112 /* 筛选扫描到的Wi-Fi网络,选择待连接的网络 */
113 for (bss_index = 0; bss_index < num; bss_index ++) {
114 if (strlen(expected_ssid) == strlen(result[bss_index].ssid)) {
115 if (memcmp(expected_ssid, result[bss_index].ssid, strlen(expected_ssid)) == 0) {
116 find_ap = TD_TRUE;
117 break;
118 }
119 }
120 }
121 /* 未找到待连接AP,可以继续尝试扫描或者退出 */
122 if (find_ap == TD_FALSE) {
123 osal_kfree(result);
124 return -1;
125 }
126 /* 找到网络后复制网络信息和接入密码 */
127 if (memcpy_s(expected_bss->ssid, WIFI_MAX_SSID_LEN, expected_ssid, strlen(expected_ssid)) != 0) {
128 osal_kfree(result);
129 return -1;
130 }
131 if (memcpy_s(expected_bss->bssid, WIFI_MAC_LEN, result[bss_index].bssid, WIFI_MAC_LEN) != 0) {
132 osal_kfree(result);
133 return -1;
134 }
135 expected_bss->security_type = result[bss_index].security_type;
136 if (memcpy_s(expected_bss->pre_shared_key, WIFI_MAX_SSID_LEN, key, strlen(key)) != 0) {
137 osal_kfree(result);
138 return -1;
139 }
140 expected_bss->ip_type = 1; /* 1:IP类型为动态DHCP获取 */
141 osal_kfree(result);
142 return 0;
143 }
144
145 /*****************************************************************************
146 STA 关联状态查询
147 *****************************************************************************/
example_check_connect_status(td_void)148 td_bool example_check_connect_status(td_void)
149 {
150 td_u8 index;
151 wifi_linked_info_stru wifi_status;
152 /* 获取网络连接状态,共查询5次,每次间隔500ms */
153 for (index = 0; index < 5; index ++) {
154 (void)osDelay(50); /* 50: 延时500ms */
155 memset_s(&wifi_status, sizeof(wifi_linked_info_stru), 0, sizeof(wifi_linked_info_stru));
156 if (wifi_sta_get_ap_info(&wifi_status) != 0) {
157 continue;
158 }
159 if (wifi_status.conn_state == 1) {
160 return 0; /* 连接成功退出循环 */
161 }
162 }
163 return -1;
164 }
165
166 /*****************************************************************************
167 STA DHCP状态查询
168 *****************************************************************************/
example_check_dhcp_status(struct netif * netif_p,td_u32 * wait_count)169 td_bool example_check_dhcp_status(struct netif *netif_p, td_u32 *wait_count)
170 {
171 if ((ip_addr_isany(&(netif_p->ip_addr)) == 0) && (*wait_count <= WIFI_GET_IP_MAX_COUNT)) {
172 /* DHCP成功 */
173 PRINT("%s::STA DHCP success.\r\n", WIFI_STA_SAMPLE_LOG);
174 return 0;
175 }
176
177 if (*wait_count > WIFI_GET_IP_MAX_COUNT) {
178 PRINT("%s::STA DHCP timeout, try again !.\r\n", WIFI_STA_SAMPLE_LOG);
179 *wait_count = 0;
180 g_wifi_state = WIFI_STA_SAMPLE_INIT;
181 }
182 return -1;
183 }
184
example_sta_function(td_void)185 td_s32 example_sta_function(td_void)
186 {
187 td_char ifname[WIFI_IFNAME_MAX_SIZE + 1] = "wlan0"; /* 创建的STA接口名 */
188 wifi_sta_config_stru expected_bss = {0}; /* 连接请求信息 */
189 struct netif *netif_p = TD_NULL;
190 td_u32 wait_count = 0;
191
192 /* 创建STA接口 */
193 if (wifi_sta_enable() != 0) {
194 return -1;
195 }
196 PRINT("%s::STA enable succ.\r\n", WIFI_STA_SAMPLE_LOG);
197
198 do {
199 (void)osDelay(1); /* 1: 等待10ms后判断状态 */
200 if (g_wifi_state == WIFI_STA_SAMPLE_INIT) {
201 PRINT("%s::Scan start!\r\n", WIFI_STA_SAMPLE_LOG);
202 g_wifi_state = WIFI_STA_SAMPLE_SCANING;
203 /* 启动STA扫描 */
204 if (wifi_sta_scan() != 0) {
205 g_wifi_state = WIFI_STA_SAMPLE_INIT;
206 continue;
207 }
208 } else if (g_wifi_state == WIFI_STA_SAMPLE_SCAN_DONE) {
209 /* 获取待连接的网络 */
210 if (example_get_match_network(&expected_bss) != 0) {
211 PRINT("%s::Do not find AP, try again !\r\n", WIFI_STA_SAMPLE_LOG);
212 g_wifi_state = WIFI_STA_SAMPLE_INIT;
213 continue;
214 }
215 g_wifi_state = WIFI_STA_SAMPLE_FOUND_TARGET;
216 } else if (g_wifi_state == WIFI_STA_SAMPLE_FOUND_TARGET) {
217 PRINT("%s::Connect start.\r\n", WIFI_STA_SAMPLE_LOG);
218 g_wifi_state = WIFI_STA_SAMPLE_CONNECTING;
219 /* 启动连接 */
220 if (wifi_sta_connect(&expected_bss) != 0) {
221 g_wifi_state = WIFI_STA_SAMPLE_INIT;
222 continue;
223 }
224 } else if (g_wifi_state == WIFI_STA_SAMPLE_CONNECT_DONE) {
225 PRINT("%s::DHCP start.\r\n", WIFI_STA_SAMPLE_LOG);
226 g_wifi_state = WIFI_STA_SAMPLE_GET_IP;
227 netif_p = netifapi_netif_find(ifname);
228 if (netif_p == TD_NULL || netifapi_dhcp_start(netif_p) != 0) {
229 PRINT("%s::find netif or start DHCP fail, try again !\r\n", WIFI_STA_SAMPLE_LOG);
230 g_wifi_state = WIFI_STA_SAMPLE_INIT;
231 continue;
232 }
233 } else if (g_wifi_state == WIFI_STA_SAMPLE_GET_IP) {
234 if (example_check_dhcp_status(netif_p, &wait_count) == 0) {
235 break;
236 }
237 wait_count++;
238 }
239 } while (1);
240
241 return 0;
242 }
243
sta_sample_init(void * param)244 int sta_sample_init(void *param)
245 {
246 param = param;
247
248 /* 注册事件回调 */
249 if (wifi_register_event_cb(&wifi_event_cb) != 0) {
250 PRINT("%s::wifi_event_cb register fail.\r\n", WIFI_STA_SAMPLE_LOG);
251 return -1;
252 }
253 PRINT("%s::wifi_event_cb register succ.\r\n", WIFI_STA_SAMPLE_LOG);
254
255 /* 等待wifi初始化完成 */
256 while (wifi_is_wifi_inited() == 0) {
257 (void)osDelay(10); /* 1: 等待100ms后判断状态 */
258 }
259 PRINT("%s::wifi init succ.\r\n", WIFI_STA_SAMPLE_LOG);
260
261 if (example_sta_function() != 0) {
262 PRINT("%s::example_sta_function fail.\r\n", WIFI_STA_SAMPLE_LOG);
263 return -1;
264 }
265 return 0;
266 }
267
sta_sample_entry(void)268 static void sta_sample_entry(void)
269 {
270 osThreadAttr_t attr;
271 attr.name = "sta_sample_task";
272 attr.attr_bits = 0U;
273 attr.cb_mem = NULL;
274 attr.cb_size = 0U;
275 attr.stack_mem = NULL;
276 attr.stack_size = WIFI_TASK_STACK_SIZE;
277 attr.priority = WIFI_TASK_PRIO;
278 if (osThreadNew((osThreadFunc_t)sta_sample_init, NULL, &attr) == NULL) {
279 PRINT("%s::Create sta_sample_task fail.\r\n", WIFI_STA_SAMPLE_LOG);
280 }
281 PRINT("%s::Create sta_sample_task succ.\r\n", WIFI_STA_SAMPLE_LOG);
282 }
283
284 /* Run the sta_sample_task. */
285 app_run(sta_sample_entry);