1 /*
2 * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
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 #include "wifi_event.h"
16 #include "wifi_error_code.h"
17 #include "wifi_device_config.h"
18 #include "wifi_hotspot_config.h"
19 #include "inet.h"
20 #include "wifi_host.h"
21 #include "dhcp.h"
22 #include "dhcps.h"
23 #include "wlan_if.h"
24 #include "wifi_config.h"
25 #include "securec.h"
26 #include "dbg.h"
27
28 #define IP_MASK 0x00FFFFFF
29 #define DEFAULT_AP_VIF 0
30 #define DEFAULT_BAND PHY_BAND_2G4
31 #define DEFAULT_CHANNLE 7
32 #define RSSI_LEVEL_4_2_G (-65)
33 #define RSSI_LEVEL_3_2_G (-75)
34 #define RSSI_LEVEL_2_2_G (-82)
35 #define RSSI_LEVEL_1_2_G (-88)
36 #define RSSI_LEVEL_4_5_G (-65)
37 #define RSSI_LEVEL_3_5_G (-72)
38 #define RSSI_LEVEL_2_5_G (-79)
39 #define RSSI_LEVEL_1_5_G (-85)
40
41 ChipseaWifiApData g_apData = {0};
42
SetApVif()43 static int32_t SetApVif()
44 {
45 struct fhost_vif_tag *fhost_vif;
46 struct fhost_cntrl_link *apLink;
47 ipc_host_cntrl_start();
48
49 apLink = fhost_cntrl_cfgrwnx_link_open();
50 if (apLink == NULL) {
51 dbg("Failed to open link with control task\n");
52 return ERROR_WIFI_UNKNOWN;
53 }
54
55 if (fhost_set_vif_type(apLink, DEFAULT_AP_VIF, VIF_UNKNOWN, false) ||
56 fhost_set_vif_type(apLink, DEFAULT_AP_VIF, VIF_AP, false)) {
57 fhost_cntrl_cfgrwnx_link_close(apLink);
58 return ERROR_WIFI_UNKNOWN;
59 }
60
61 fhost_cntrl_cfgrwnx_link_close(apLink);
62
63 fhost_vif = &fhost_env.vif[DEFAULT_AP_VIF];
64 MAC_ADDR_CPY(&(vif_info_tab[DEFAULT_AP_VIF].mac_addr), &(fhost_vif->mac_addr));
65
66 return WIFI_SUCCESS;
67 }
68
EnableHotspot(void)69 WifiErrorCode EnableHotspot(void)
70 {
71 if (WifiCreateLock() != WIFI_SUCCESS) {
72 return ERROR_WIFI_NOT_AVAILABLE;
73 }
74
75 if (g_apData.state == WIFI_HOTSPOT_ACTIVE) {
76 dbg("ap has enabled\r\n");
77 WifiUnlock();
78 return ERROR_WIFI_UNKNOWN;
79 }
80
81 LOS_ListInit(&g_apData.stationHead);
82
83 if (g_apData.vifApCfg.ssid.length == 0) {
84 dbg("Failed to start AP, check ssid\r\n");
85 goto enable_err;
86 }
87
88 if (SetApVif() != WIFI_SUCCESS) {
89 dbg("SetApVif err\r\n");
90 goto enable_err;
91 }
92
93 if (fhost_ap_cfg(DEFAULT_AP_VIF, &g_apData.vifApCfg)) {
94 dbg("Failed to start AP, check your configuration\r\n");
95 goto enable_err;
96 }
97
98 net_if_t *net_if = fhost_to_net_if(DEFAULT_AP_VIF);
99 if (net_if == NULL) {
100 dbg("[CS] net_if_find_from_wifi_idx fail\r\n");
101 goto enable_err;
102 }
103
104 uint32_t ip_addr = get_ap_ip_addr();
105 net_if_set_ip(net_if, ip_addr, IP_MASK, 0);
106
107 //set up DHCP server
108 dhcpServerStart(net_if);
109
110 // Now that we got an IP address use this interface as default
111 net_if_set_default(net_if);
112
113 fhost_tx_task_init();
114
115 dbg("DHCPS init: ip=%d.%d.%d.%d\r\n", (ip_addr)&0xFF, (ip_addr>>8)&0xFF, (ip_addr>>16)&0xFF, (ip_addr>>24)&0xFF);
116
117 g_apData.state = WIFI_HOTSPOT_ACTIVE;
118 DoApStateCallBack(WIFI_STATE_AVAILABLE);
119 WifiUnlock();
120 return WIFI_SUCCESS;
121 enable_err:
122 DoApStateCallBack(WIFI_STATE_NOT_AVAILABLE);
123 WifiUnlock();
124 return ERROR_WIFI_UNKNOWN;
125 }
126
DisableHotspot(void)127 WifiErrorCode DisableHotspot(void)
128 {
129 WifiStationNode *pos = NULL;
130 if (WifiCreateLock() != WIFI_SUCCESS) {
131 return ERROR_WIFI_NOT_AVAILABLE;
132 }
133 if (g_apData.state == WIFI_HOTSPOT_NOT_ACTIVE) {
134 dbg("wifi ap has closed\r\n");
135 WifiUnlock();
136 return ERROR_WIFI_NOT_AVAILABLE;
137 }
138
139 wlan_stop_ap();
140 LOS_DL_LIST_FOR_EACH_ENTRY(pos, &g_apData.stationHead, WifiStationNode, node) {
141 LOS_ListDelete(&pos->node);
142 rtos_free(pos);
143 }
144 g_apData.stationCnt = 0;
145 g_apData.state = WIFI_HOTSPOT_NOT_ACTIVE;
146 DoApStateCallBack(WIFI_STATE_NOT_AVAILABLE);
147 WifiUnlock();
148 return WIFI_SUCCESS;
149 }
150
SetSecType(WifiSecurityType security_type,struct fhost_vif_ap_cfg * cfg)151 static void SetSecType(WifiSecurityType security_type,struct fhost_vif_ap_cfg *cfg)
152 {
153 cfg->akm = 0;
154 switch (security_type) {
155 case WIFI_SEC_TYPE_WEP:
156 cfg->akm |= CO_BIT(MAC_AKM_PRE_RSN);
157 break;
158 case WIFI_SEC_TYPE_PSK:
159 cfg->akm |= CO_BIT(MAC_AKM_PRE_RSN) | CO_BIT(MAC_AKM_PSK);
160 break;
161 case WIFI_SEC_TYPE_SAE:
162 cfg->akm |= CO_BIT(MAC_AKM_SAE);
163 break;
164 default:
165 cfg->akm |= CO_BIT(MAC_AKM_NONE);
166 break;
167 }
168 dbg("WifiAp:set akm =%d\r\n", cfg->akm);
169 }
170
SetChannel(int channelNum,int band,struct fhost_vif_ap_cfg * cfg)171 static int32_t SetChannel(int channelNum, int band, struct fhost_vif_ap_cfg *cfg)
172 {
173 if (band == HOTSPOT_BAND_TYPE_2G) {
174 cfg->chan.band = PHY_BAND_2G4;
175 } else if (band == HOTSPOT_BAND_TYPE_5G) {
176 cfg->chan.band = PHY_BAND_5G;
177 } else {
178 dbg("Invalid band set default 2G4\r\n");
179 cfg->chan.band = DEFAULT_BAND;
180 }
181
182 channelNum = (channelNum == 0) ? DEFAULT_CHANNLE : channelNum;
183 cfg->chan.prim20_freq = phy_channel_to_freq(cfg->chan.band, channelNum);
184 cfg->chan.type = PHY_CHNL_BW_20;
185 cfg->chan.center1_freq = cfg->chan.prim20_freq;
186 return WIFI_SUCCESS;
187 }
188
SetHotspotConfig(const HotspotConfig * config)189 WifiErrorCode SetHotspotConfig(const HotspotConfig *config)
190 {
191 PARAM_CHECK(config);
192
193 if (WifiCreateLock() != WIFI_SUCCESS) {
194 return ERROR_WIFI_NOT_AVAILABLE;
195 }
196 memset(&g_apData.vifApCfg, 0, sizeof(struct fhost_vif_ap_cfg));
197
198 if (strcpy_s((char *)g_apData.vifApCfg.ssid.array, MAC_SSID_LEN, config->ssid) != EOK) {
199 dbg("Invalid SSID\r\n");
200 WifiUnlock();
201 return ERROR_WIFI_UNKNOWN;
202 }
203 g_apData.vifApCfg.ssid.length = strlen(config->ssid);
204
205 SetSecType(config->securityType, &g_apData.vifApCfg);
206
207 if (SetChannel(config->channelNum, config->band, &g_apData.vifApCfg) != WIFI_SUCCESS) {
208 dbg("set channel err chan = %d.band = %d\r\n", config->channelNum, config->band);
209 WifiUnlock();
210 return ERROR_WIFI_UNKNOWN;
211 }
212
213 if (strcpy_s(g_apData.vifApCfg.key, sizeof(g_apData.vifApCfg.key), config->preSharedKey) != EOK) {
214 dbg("Invalid key\r\n");
215 WifiUnlock();
216 return ERROR_WIFI_UNKNOWN;
217 }
218
219 memcpy(&g_apData.hostpotCfg, config, sizeof(HotspotConfig));
220 WifiUnlock();
221 return WIFI_SUCCESS;
222 }
223
GetHotspotConfig(HotspotConfig * result)224 WifiErrorCode GetHotspotConfig(HotspotConfig *result)
225 {
226 PARAM_CHECK(result);
227 memcpy(result, &g_apData.hostpotCfg, sizeof(HotspotConfig));
228 return WIFI_SUCCESS;
229 }
230
IsHotspotActive(void)231 int IsHotspotActive(void)
232 {
233 return g_apData.state;
234 }
235
GetStationList(StationInfo * result,unsigned int * size)236 WifiErrorCode GetStationList(StationInfo *result, unsigned int *size)
237 {
238 uint8_t cnt = 0;
239 WifiStationNode *pos = NULL;
240
241 if (g_apData.state != WIFI_HOTSPOT_ACTIVE) {
242 dbg("hotspot not enable\r\n");
243 return ERROR_WIFI_UNKNOWN;
244 }
245
246 LOS_DL_LIST_FOR_EACH_ENTRY(pos, &g_apData.stationHead, WifiStationNode, node) {
247 (void)memcpy_s(result, sizeof(StationInfo), &(pos->station), sizeof(StationInfo));
248 cnt++;
249 }
250
251 *size = cnt;
252 return WIFI_SUCCESS;
253 }
254
SetBand(int band)255 WifiErrorCode SetBand(int band)
256 {
257 dbg("SetBand = %d\r\n", band);
258 g_apData.hostpotCfg.band = band;
259 if (band == HOTSPOT_BAND_TYPE_2G) {
260 g_apData.vifApCfg.chan.band = PHY_BAND_2G4;
261 } else if (band == HOTSPOT_BAND_TYPE_5G) {
262 g_apData.vifApCfg.chan.band = PHY_BAND_5G;
263 } else {
264 dbg("Invalid band\r\n");
265 return ERROR_WIFI_UNKNOWN;
266 }
267 return WIFI_SUCCESS;
268 }
269
GetBand(int * result)270 WifiErrorCode GetBand(int *result)
271 {
272 PARAM_CHECK(result);
273 *result = g_apData.hostpotCfg.band;
274 if ((*result != HOTSPOT_BAND_TYPE_2G) && (*result != HOTSPOT_BAND_TYPE_5G)) {
275 dbg("Invalid band = %d\r\n", g_apData.hostpotCfg.band);
276 return ERROR_WIFI_UNKNOWN;
277 }
278 return WIFI_SUCCESS;
279 }
280
GetSignalLevel(int rssi,int band)281 int GetSignalLevel(int rssi, int band)
282 {
283 if (band == HOTSPOT_BAND_TYPE_2G) {
284 if (rssi >= RSSI_LEVEL_4_2_G)
285 return RSSI_LEVEL_4;
286 if (rssi >= RSSI_LEVEL_3_2_G)
287 return RSSI_LEVEL_3;
288 if (rssi >= RSSI_LEVEL_2_2_G)
289 return RSSI_LEVEL_2;
290 if (rssi >= RSSI_LEVEL_1_2_G)
291 return RSSI_LEVEL_1;
292 }
293
294 if (band == HOTSPOT_BAND_TYPE_5G) {
295 if (rssi >= RSSI_LEVEL_4_5_G)
296 return RSSI_LEVEL_4;
297 if (rssi >= RSSI_LEVEL_3_5_G)
298 return RSSI_LEVEL_3;
299 if (rssi >= RSSI_LEVEL_2_5_G)
300 return RSSI_LEVEL_2;
301 if (rssi >= RSSI_LEVEL_1_5_G)
302 return RSSI_LEVEL_1;
303 }
304 return ERROR_WIFI_INVALID_ARGS;
305 }
306
HandleStaConnect(uint8_t * macAddr,ip4_addr_t clientIP)307 void HandleStaConnect(uint8_t *macAddr, ip4_addr_t clientIP)
308 {
309 if (g_apData.state != WIFI_HOTSPOT_ACTIVE) {
310 dbg("ap not enabled\r\n");
311 return;
312 }
313
314 if (macAddr == NULL) {
315 dbg("null check err\r\n");
316 return;
317 }
318 if (WifiCreateLock() != WIFI_SUCCESS) {
319 return;
320 }
321
322 if (g_apData.stationCnt > WIFI_MAX_STA_NUM) {
323 dbg("station cnt over flow\r\n");
324 WifiUnlock();
325 return;
326 }
327
328 WifiStationNode *stationNode = (WifiStationNode *)rtos_calloc(1, sizeof(*stationNode));
329 if (stationNode == NULL) {
330 WifiUnlock();
331 return;
332 }
333 memcpy(&stationNode->station.macAddress, macAddr, WIFI_MAC_LEN);
334 stationNode->station.ipAddress = ntohl(ip4_addr_get_u32(&clientIP));
335
336 LOS_ListTailInsert(&g_apData.stationHead, &stationNode->node);
337 g_apData.stationCnt++;
338 dbg("station join: mac->%02X:%02X:%02X:%02X:%02X:%02X ip-> %s,cnt= %d\r\n", macAddr[0], macAddr[1],
339 macAddr[2], macAddr[3], macAddr[4], macAddr[5], inet_ntoa(clientIP), g_apData.stationCnt);
340 DoStaJoinCallBack(&stationNode->station);
341 WifiUnlock();
342 }
343
HandleStaDisconnect(uint8_t * macAddr)344 void HandleStaDisconnect(uint8_t *macAddr)
345 {
346 if (g_apData.state != WIFI_HOTSPOT_ACTIVE) {
347 dbg("ap not enabled\r\n");
348 return;
349 }
350
351 if (macAddr == NULL) {
352 dbg("null check err\r\n");
353 return;
354 }
355 if (WifiCreateLock() != WIFI_SUCCESS) {
356 return;
357 }
358
359 WifiStationNode *pos = NULL;
360
361 LOS_DL_LIST_FOR_EACH_ENTRY(pos, &g_apData.stationHead, WifiStationNode, node) {
362 if (memcmp(&pos->station.macAddress, macAddr, WIFI_MAC_LEN) == 0) {
363 LOS_ListDelete(&pos->node);
364 rtos_free(pos);
365 g_apData.stationCnt--;
366 DoStaLeaveCallBack(&pos->station);
367 dbg("station leave: %02X:%02X:%02X:%02X:%02X:%02X -> %s,cnt= %d\r\n", macAddr[0],
368 macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5], g_apData.stationCnt);
369 break;
370 }
371 }
372 WifiUnlock();
373 }
374