]>
Commit | Line | Data |
---|---|---|
774e9b2e MM |
1 | /* |
2 | * Espressif Systems Wireless LAN device driver | |
3 | * | |
d7215282 | 4 | * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD |
774e9b2e | 5 | * |
d7215282 | 6 | * SPDX-License-Identifier: GPL-2.0-only |
774e9b2e | 7 | */ |
774e9b2e MM |
8 | #include "esp.h" |
9 | #include "esp_api.h" | |
10 | #include "esp_cfg80211.h" | |
11 | #include "esp_cmd.h" | |
aad2ae2e | 12 | #include "esp_kernel_port.h" |
774e9b2e MM |
13 | |
14 | /** | |
15 | * @brief WiFi PHY rate encodings | |
16 | * | |
17 | */ | |
18 | typedef enum { | |
5a47b073 MM |
19 | WIFI_PHY_RATE_1M_L = 0x00, /**< 1 Mbps with long preamble */ |
20 | WIFI_PHY_RATE_2M_L = 0x01, /**< 2 Mbps with long preamble */ | |
21 | WIFI_PHY_RATE_5M_L = 0x02, /**< 5.5 Mbps with long preamble */ | |
22 | WIFI_PHY_RATE_11M_L = 0x03, /**< 11 Mbps with long preamble */ | |
23 | WIFI_PHY_RATE_2M_S = 0x05, /**< 2 Mbps with short preamble */ | |
24 | WIFI_PHY_RATE_5M_S = 0x06, /**< 5.5 Mbps with short preamble */ | |
25 | WIFI_PHY_RATE_11M_S = 0x07, /**< 11 Mbps with short preamble */ | |
26 | WIFI_PHY_RATE_48M = 0x08, /**< 48 Mbps */ | |
27 | WIFI_PHY_RATE_24M = 0x09, /**< 24 Mbps */ | |
28 | WIFI_PHY_RATE_12M = 0x0A, /**< 12 Mbps */ | |
29 | WIFI_PHY_RATE_6M = 0x0B, /**< 6 Mbps */ | |
30 | WIFI_PHY_RATE_54M = 0x0C, /**< 54 Mbps */ | |
31 | WIFI_PHY_RATE_36M = 0x0D, /**< 36 Mbps */ | |
32 | WIFI_PHY_RATE_18M = 0x0E, /**< 18 Mbps */ | |
33 | WIFI_PHY_RATE_9M = 0x0F, /**< 9 Mbps */ | |
34 | WIFI_PHY_RATE_MCS0_LGI = 0x10, /**< MCS0 with long GI, 6.5 Mbps for 20MHz, 13.5 Mbps for 40MHz */ | |
35 | WIFI_PHY_RATE_MCS1_LGI = 0x11, /**< MCS1 with long GI, 13 Mbps for 20MHz, 27 Mbps for 40MHz */ | |
36 | WIFI_PHY_RATE_MCS2_LGI = 0x12, /**< MCS2 with long GI, 19.5 Mbps for 20MHz, 40.5 Mbps for 40MHz */ | |
37 | WIFI_PHY_RATE_MCS3_LGI = 0x13, /**< MCS3 with long GI, 26 Mbps for 20MHz, 54 Mbps for 40MHz */ | |
38 | WIFI_PHY_RATE_MCS4_LGI = 0x14, /**< MCS4 with long GI, 39 Mbps for 20MHz, 81 Mbps for 40MHz */ | |
39 | WIFI_PHY_RATE_MCS5_LGI = 0x15, /**< MCS5 with long GI, 52 Mbps for 20MHz, 108 Mbps for 40MHz */ | |
40 | WIFI_PHY_RATE_MCS6_LGI = 0x16, /**< MCS6 with long GI, 58.5 Mbps for 20MHz, 121.5 Mbps for 40MHz */ | |
41 | WIFI_PHY_RATE_MCS7_LGI = 0x17, /**< MCS7 with long GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */ | |
42 | WIFI_PHY_RATE_MCS0_SGI = 0x18, /**< MCS0 with short GI, 7.2 Mbps for 20MHz, 15 Mbps for 40MHz */ | |
43 | WIFI_PHY_RATE_MCS1_SGI = 0x19, /**< MCS1 with short GI, 14.4 Mbps for 20MHz, 30 Mbps for 40MHz */ | |
44 | WIFI_PHY_RATE_MCS2_SGI = 0x1A, /**< MCS2 with short GI, 21.7 Mbps for 20MHz, 45 Mbps for 40MHz */ | |
45 | WIFI_PHY_RATE_MCS3_SGI = 0x1B, /**< MCS3 with short GI, 28.9 Mbps for 20MHz, 60 Mbps for 40MHz */ | |
46 | WIFI_PHY_RATE_MCS4_SGI = 0x1C, /**< MCS4 with short GI, 43.3 Mbps for 20MHz, 90 Mbps for 40MHz */ | |
47 | WIFI_PHY_RATE_MCS5_SGI = 0x1D, /**< MCS5 with short GI, 57.8 Mbps for 20MHz, 120 Mbps for 40MHz */ | |
48 | WIFI_PHY_RATE_MCS6_SGI = 0x1E, /**< MCS6 with short GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */ | |
49 | WIFI_PHY_RATE_MCS7_SGI = 0x1F, /**< MCS7 with short GI, 72.2 Mbps for 20MHz, 150 Mbps for 40MHz */ | |
50 | WIFI_PHY_RATE_LORA_250K = 0x29, /**< 250 Kbps */ | |
51 | WIFI_PHY_RATE_LORA_500K = 0x2A, /**< 500 Kbps */ | |
52 | WIFI_PHY_RATE_MAX, | |
774e9b2e MM |
53 | } wifi_phy_rate_t; |
54 | ||
55 | /* Supported rates to be advertised to the cfg80211 */ | |
56 | static struct ieee80211_rate esp_rates[] = { | |
5a47b073 MM |
57 | {.bitrate = 10, .hw_value = WIFI_PHY_RATE_1M_L, }, |
58 | {.bitrate = 20, .hw_value = WIFI_PHY_RATE_2M_L, }, | |
59 | {.bitrate = 55, .hw_value = WIFI_PHY_RATE_5M_L, .hw_value_short = WIFI_PHY_RATE_5M_S}, | |
60 | {.bitrate = 110, .hw_value = WIFI_PHY_RATE_11M_L, .hw_value_short = WIFI_PHY_RATE_11M_S}, | |
61 | {.bitrate = 60, .hw_value = WIFI_PHY_RATE_6M, }, | |
62 | {.bitrate = 90, .hw_value = WIFI_PHY_RATE_9M, }, | |
63 | {.bitrate = 120, .hw_value = WIFI_PHY_RATE_12M, }, | |
64 | {.bitrate = 180, .hw_value = WIFI_PHY_RATE_18M, }, | |
65 | {.bitrate = 240, .hw_value = WIFI_PHY_RATE_24M, }, | |
66 | {.bitrate = 360, .hw_value = WIFI_PHY_RATE_36M, }, | |
67 | {.bitrate = 480, .hw_value = WIFI_PHY_RATE_48M, }, | |
68 | {.bitrate = 540, .hw_value = WIFI_PHY_RATE_54M, }, | |
774e9b2e MM |
69 | }; |
70 | ||
71 | ||
72 | /* Channel definitions to be advertised to cfg80211 */ | |
73 | static struct ieee80211_channel esp_channels_2ghz[] = { | |
5a47b073 MM |
74 | {.center_freq = 2412, .hw_value = 1, }, |
75 | {.center_freq = 2417, .hw_value = 2, }, | |
76 | {.center_freq = 2422, .hw_value = 3, }, | |
77 | {.center_freq = 2427, .hw_value = 4, }, | |
78 | {.center_freq = 2432, .hw_value = 5, }, | |
79 | {.center_freq = 2437, .hw_value = 6, }, | |
80 | {.center_freq = 2442, .hw_value = 7, }, | |
81 | {.center_freq = 2447, .hw_value = 8, }, | |
82 | {.center_freq = 2452, .hw_value = 9, }, | |
83 | {.center_freq = 2457, .hw_value = 10, }, | |
84 | {.center_freq = 2462, .hw_value = 11, }, | |
85 | {.center_freq = 2467, .hw_value = 12, }, | |
86 | {.center_freq = 2472, .hw_value = 13, }, | |
87 | {.center_freq = 2484, .hw_value = 14, }, | |
774e9b2e MM |
88 | }; |
89 | ||
90 | static struct ieee80211_supported_band esp_wifi_bands = { | |
5a47b073 MM |
91 | .channels = esp_channels_2ghz, |
92 | .n_channels = ARRAY_SIZE(esp_channels_2ghz), | |
93 | .bitrates = esp_rates, | |
94 | .n_bitrates = ARRAY_SIZE(esp_rates), | |
774e9b2e MM |
95 | }; |
96 | ||
97 | /* Supported crypto cipher suits to be advertised to cfg80211 */ | |
98 | static const u32 esp_cipher_suites[] = { | |
5a47b073 MM |
99 | WLAN_CIPHER_SUITE_WEP40, |
100 | WLAN_CIPHER_SUITE_WEP104, | |
101 | WLAN_CIPHER_SUITE_TKIP, | |
102 | WLAN_CIPHER_SUITE_CCMP, | |
103 | WLAN_CIPHER_SUITE_SMS4, | |
104 | WLAN_CIPHER_SUITE_AES_CMAC, | |
774e9b2e MM |
105 | }; |
106 | ||
3fef9acf | 107 | static const struct wiphy_wowlan_support esp_wowlan_support = { |
5a47b073 MM |
108 | .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT, |
109 | .n_patterns = 0, | |
110 | .pattern_max_len = 0, | |
111 | .pattern_min_len = 0, | |
112 | .max_pkt_offset = 0, | |
3fef9acf MM |
113 | }; |
114 | ||
7406fe82 | 115 | static int esp_inetaddr_event(struct notifier_block *nb, |
5a47b073 | 116 | unsigned long event, void *data) |
7406fe82 | 117 | { |
5a47b073 MM |
118 | struct in_ifaddr *ifa = data; |
119 | struct net_device *netdev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; | |
7406fe82 MM |
120 | struct esp_wifi_device *priv = netdev_priv(netdev); |
121 | ||
5a47b073 MM |
122 | /*printk(KERN_INFO "------- IP event -------: %d\n", priv->if_type);*/ |
123 | ||
124 | if (!strstr(netdev->name, "espsta")) { | |
125 | return 0; | |
126 | } | |
127 | ||
128 | switch (event) { | |
129 | ||
130 | case NETDEV_UP: | |
131 | if (priv && (priv->if_type == ESP_STA_IF)) { | |
132 | cmd_set_ip_address(priv, ifa->ifa_local); | |
133 | printk(KERN_INFO "%s: NETDEV_UP interface %s ip changed to %pi4 \n", | |
134 | __func__, netdev->name, &ifa->ifa_local); | |
135 | } | |
136 | break; | |
137 | ||
138 | case NETDEV_DOWN: | |
139 | printk(KERN_INFO "Interface Down: %d\n", priv->if_type); | |
140 | if (priv && (priv->if_type == ESP_STA_IF)) | |
141 | cmd_set_ip_address(priv, 0); | |
142 | break; | |
143 | } | |
144 | ||
145 | return 0; | |
7406fe82 MM |
146 | } |
147 | ||
774e9b2e | 148 | struct wireless_dev *esp_cfg80211_add_iface(struct wiphy *wiphy, |
5a47b073 MM |
149 | const char *name, |
150 | unsigned char name_assign_type, | |
151 | enum nl80211_iftype type, | |
152 | struct vif_params *params) | |
774e9b2e | 153 | { |
bd131325 | 154 | struct esp_device *esp_dev = NULL; |
774e9b2e MM |
155 | /* struct wireless_dev *wdev = NULL;*/ |
156 | struct net_device *ndev; | |
157 | struct esp_wifi_device *esp_wdev; | |
158 | uint8_t esp_nw_if_num = 0; | |
159 | ||
bd131325 YM |
160 | if (!wiphy || !name) { |
161 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
162 | return NULL; | |
163 | } | |
164 | ||
165 | esp_dev = wiphy_priv(wiphy); | |
166 | ||
167 | if (!esp_dev || !esp_dev->adapter) { | |
168 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
169 | return NULL; | |
170 | } | |
171 | ||
774e9b2e MM |
172 | if (NL80211_IFTYPE_STATION == type) { |
173 | esp_nw_if_num = ESP_STA_NW_IF; | |
174 | } else if (NL80211_IFTYPE_AP == type) { | |
175 | esp_nw_if_num = ESP_AP_NW_IF; | |
176 | } else { | |
177 | printk(KERN_INFO "%s:%u network type[%u] is not supported\n", | |
178 | __func__, __LINE__, type); | |
179 | return NULL; | |
180 | } | |
181 | ||
aad2ae2e | 182 | ndev = ALLOC_NETDEV(sizeof(struct esp_wifi_device), name, name_assign_type, |
774e9b2e MM |
183 | ether_setup); |
184 | ||
185 | if (!ndev) | |
186 | return ERR_PTR(-ENOMEM); | |
187 | ||
225e14eb | 188 | set_bit(ESP_DRIVER_ACTIVE, &esp_dev->adapter->state_flags); |
774e9b2e MM |
189 | esp_wdev = netdev_priv(ndev); |
190 | ||
191 | ndev->ieee80211_ptr = &esp_wdev->wdev; | |
192 | esp_wdev->wdev.wiphy = wiphy; | |
193 | esp_wdev->esp_dev = esp_dev; | |
194 | esp_wdev->ndev = ndev; | |
195 | esp_wdev->adapter = esp_dev->adapter; | |
196 | esp_wdev->adapter->priv[esp_nw_if_num] = esp_wdev; | |
197 | /*printk(KERN_INFO "Updated priv[%u] to %px\n", | |
198 | * esp_nw_if_num, esp_wdev->adapter->priv[esp_nw_if_num]);*/ | |
199 | dev_net_set(ndev, wiphy_net(wiphy)); | |
200 | SET_NETDEV_DEV(ndev, wiphy_dev(esp_wdev->wdev.wiphy)); | |
201 | esp_wdev->wdev.netdev = ndev; | |
202 | esp_wdev->wdev.iftype = type; | |
203 | ||
204 | init_waitqueue_head(&esp_wdev->wait_for_scan_completion); | |
205 | esp_wdev->stop_data = 1; | |
206 | esp_wdev->port_open = 0; | |
207 | ||
208 | if (cmd_init_interface(esp_wdev)) | |
209 | goto free_and_return; | |
210 | ||
211 | if (cmd_get_mac(esp_wdev)) | |
212 | goto free_and_return; | |
213 | ||
1294f8ac | 214 | eth_hw_addr_set(ndev, esp_wdev->mac_address); |
774e9b2e MM |
215 | |
216 | esp_init_priv(ndev); | |
217 | ||
218 | if (register_netdevice(ndev)) | |
219 | goto free_and_return; | |
220 | ||
221 | ||
222 | set_bit(ESP_NETWORK_UP, &esp_wdev->priv_flags); | |
225e14eb YM |
223 | clear_bit(ESP_CLEANUP_IN_PROGRESS, &esp_dev->adapter->state_flags); |
224 | ||
7406fe82 MM |
225 | esp_wdev->nb.notifier_call = esp_inetaddr_event; |
226 | register_inetaddr_notifier(&esp_wdev->nb); | |
227 | ||
774e9b2e MM |
228 | return &esp_wdev->wdev; |
229 | ||
230 | free_and_return: | |
225e14eb | 231 | clear_bit(ESP_DRIVER_ACTIVE, &esp_wdev->adapter->state_flags); |
774e9b2e MM |
232 | dev_net_set(ndev, NULL); |
233 | free_netdev(ndev); | |
234 | esp_wdev->ndev = NULL; | |
235 | esp_wdev->wdev.netdev = NULL; | |
236 | ndev = NULL; | |
237 | return NULL; | |
238 | } | |
239 | ||
240 | #if 0 | |
241 | static int esp_cfg80211_del_iface(struct wiphy *wiphy, | |
242 | struct wireless_dev *wdev) | |
243 | { | |
244 | return 0; | |
245 | } | |
246 | ||
247 | static int esp_cfg80211_change_iface(struct wiphy *wiphy, | |
248 | struct net_device *ndev, | |
249 | enum nl80211_iftype type, | |
250 | struct vif_params *params) | |
251 | { | |
252 | return 0; | |
253 | } | |
254 | #endif | |
255 | ||
256 | static int esp_cfg80211_scan(struct wiphy *wiphy, | |
bd131325 | 257 | struct cfg80211_scan_request *request) |
774e9b2e | 258 | { |
bd131325 YM |
259 | |
260 | struct net_device *ndev = NULL; | |
261 | struct esp_wifi_device *priv = NULL; | |
262 | ||
263 | if (!wiphy || !request || !request->wdev || !request->wdev->netdev) { | |
264 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
265 | return -EINVAL; | |
266 | } | |
267 | ||
268 | ndev = request->wdev->netdev; | |
269 | priv = netdev_priv(ndev); | |
774e9b2e | 270 | |
7b6ed49e | 271 | printk(KERN_INFO "%s\n", __func__); |
774e9b2e MM |
272 | if (!priv) { |
273 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
274 | return -EINVAL; | |
275 | } | |
276 | ||
277 | return cmd_scan_request(priv, request); | |
278 | } | |
279 | ||
bd131325 | 280 | #if 0 |
774e9b2e MM |
281 | static int esp_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, |
282 | struct cfg80211_connect_params *sme) | |
283 | { | |
284 | struct esp_wifi_device *priv = netdev_priv(dev); | |
285 | ||
bd131325 | 286 | printk(KERN_INFO "%s\n", __func__); |
774e9b2e MM |
287 | if (!priv) { |
288 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
289 | return -EINVAL; | |
290 | } | |
291 | ||
292 | return cmd_connect_request(priv, sme); | |
293 | } | |
bd131325 | 294 | #endif |
774e9b2e | 295 | |
aad2ae2e | 296 | static ESP_MGMT_TX_PROTOTYPE() |
774e9b2e MM |
297 | { |
298 | return 0; | |
299 | } | |
300 | ||
7426e123 | 301 | static int esp_cfg80211_set_default_key(struct wiphy *wiphy, |
1294f8ac KG |
302 | struct net_device *dev, INT_LINK_ID |
303 | u8 key_index, bool unicast, bool multicast) | |
774e9b2e | 304 | { |
bd131325 | 305 | struct esp_wifi_device *priv = NULL; |
774e9b2e | 306 | |
bd131325 YM |
307 | if (!wiphy || !dev) { |
308 | printk(KERN_ERR "%s:%u invalid params\n", __func__, __LINE__); | |
309 | return -EINVAL; | |
310 | } | |
311 | ||
312 | priv = netdev_priv(dev); | |
774e9b2e MM |
313 | if (!priv) { |
314 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
315 | return -EINVAL; | |
316 | } | |
317 | ||
318 | return cmd_set_default_key(priv, key_index); | |
319 | } | |
320 | ||
7426e123 | 321 | static int esp_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
1294f8ac KG |
322 | INT_LINK_ID u8 key_index, bool pairwise, |
323 | const u8 *mac_addr) | |
774e9b2e | 324 | { |
bd131325 | 325 | struct esp_wifi_device *priv = NULL; |
774e9b2e | 326 | |
bd131325 YM |
327 | if (!wiphy || !dev) { |
328 | printk(KERN_ERR "%s:%u invalid params\n", __func__, __LINE__); | |
329 | return -EINVAL; | |
330 | } | |
331 | ||
332 | priv = netdev_priv(dev); | |
774e9b2e MM |
333 | if (!priv) { |
334 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
335 | return -EINVAL; | |
336 | } | |
5a47b073 | 337 | printk(KERN_INFO "%s\n", __func__); |
774e9b2e MM |
338 | |
339 | return cmd_del_key(priv, key_index, pairwise, mac_addr); | |
340 | } | |
341 | ||
7426e123 | 342 | static int esp_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
1294f8ac KG |
343 | INT_LINK_ID u8 key_index, bool pairwise, |
344 | const u8 *mac_addr, struct key_params *params) | |
774e9b2e | 345 | { |
bd131325 YM |
346 | struct esp_wifi_device *priv = NULL; |
347 | ||
348 | if (!wiphy || !dev || !params) { | |
349 | printk(KERN_ERR "%s:%u invalid params\n", __func__, __LINE__); | |
350 | return -EINVAL; | |
351 | } | |
774e9b2e | 352 | |
bd131325 | 353 | priv = netdev_priv(dev); |
774e9b2e MM |
354 | if (!priv) { |
355 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
356 | return -EINVAL; | |
357 | } | |
5a47b073 | 358 | printk(KERN_INFO "%s\n", __func__); |
774e9b2e | 359 | |
7426e123 | 360 | if (params->key_len == 0) { |
1294f8ac | 361 | return esp_cfg80211_del_key(wiphy, dev, ZERO_LINK_ID key_index, pairwise, mac_addr); |
7426e123 | 362 | } |
774e9b2e MM |
363 | return cmd_add_key(priv, key_index, pairwise, mac_addr, params); |
364 | } | |
365 | ||
366 | static int esp_cfg80211_disconnect(struct wiphy *wiphy, | |
367 | struct net_device *dev, u16 reason_code) | |
368 | { | |
bd131325 YM |
369 | struct esp_wifi_device *priv = NULL; |
370 | ||
371 | if (!wiphy || !dev) { | |
372 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
373 | return -EINVAL; | |
374 | } | |
375 | ||
376 | priv = netdev_priv(dev); | |
774e9b2e MM |
377 | |
378 | if (!priv) { | |
379 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
380 | return 0; | |
381 | } | |
5a47b073 | 382 | printk(KERN_INFO "%s\n", __func__); |
774e9b2e MM |
383 | |
384 | return cmd_disconnect_request(priv, reason_code); | |
385 | } | |
386 | ||
7b6ed49e MM |
387 | static int esp_cfg80211_authenticate(struct wiphy *wiphy, struct net_device *dev, |
388 | struct cfg80211_auth_request *req) | |
389 | { | |
bd131325 YM |
390 | struct esp_wifi_device *priv = NULL; |
391 | ||
392 | if (!wiphy || !dev || !req) { | |
393 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
394 | return -EINVAL; | |
395 | } | |
396 | ||
7b6ed49e MM |
397 | printk(KERN_INFO "%s\n", __func__); |
398 | ||
bd131325 YM |
399 | priv = netdev_priv(dev); |
400 | ||
7b6ed49e MM |
401 | if (!priv) { |
402 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
403 | return 0; | |
404 | } | |
405 | ||
406 | return cmd_auth_request(priv, req); | |
407 | } | |
408 | ||
409 | ||
410 | static int esp_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev, | |
411 | struct cfg80211_assoc_request *req) | |
412 | { | |
bd131325 YM |
413 | struct esp_wifi_device *priv = NULL; |
414 | ||
415 | if (!wiphy || !dev || !req) { | |
416 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
417 | return -EINVAL; | |
418 | } | |
419 | ||
420 | priv = netdev_priv(dev); | |
7b6ed49e MM |
421 | |
422 | printk(KERN_INFO "%s\n", __func__); | |
bd131325 | 423 | |
7b6ed49e MM |
424 | if (!priv) { |
425 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
426 | return 0; | |
427 | } | |
428 | ||
429 | return cmd_assoc_request(priv, req); | |
430 | } | |
431 | ||
432 | static int esp_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, | |
433 | struct cfg80211_deauth_request *req) | |
434 | { | |
bd131325 YM |
435 | struct esp_wifi_device *priv = NULL; |
436 | ||
437 | if (!wiphy || !dev || !req) { | |
438 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
439 | return -EINVAL; | |
440 | } | |
7b6ed49e MM |
441 | |
442 | printk(KERN_INFO "%s\n", __func__); | |
bd131325 | 443 | priv = netdev_priv(dev); |
7b6ed49e MM |
444 | |
445 | if (!priv) { | |
446 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
447 | return 0; | |
448 | } | |
449 | ||
450 | return cmd_disconnect_request(priv, req->reason_code); | |
451 | } | |
452 | ||
453 | static int esp_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, | |
454 | struct cfg80211_disassoc_request *req) | |
455 | { | |
bd131325 YM |
456 | struct esp_wifi_device *priv = NULL; |
457 | ||
458 | if (!wiphy || !dev || !req) { | |
459 | printk(KERN_INFO "%s:%u invalid input\n", __func__, __LINE__); | |
460 | return -EINVAL; | |
461 | } | |
7b6ed49e MM |
462 | |
463 | printk(KERN_INFO "%s\n", __func__); | |
bd131325 | 464 | priv = netdev_priv(dev); |
7b6ed49e MM |
465 | |
466 | if (!priv) { | |
467 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
468 | return 0; | |
469 | } | |
bd131325 | 470 | |
7b6ed49e MM |
471 | return cmd_disconnect_request(priv, req->reason_code); |
472 | } | |
473 | ||
3fef9acf | 474 | static int esp_cfg80211_suspend(struct wiphy *wiphy, |
5a47b073 | 475 | struct cfg80211_wowlan *wowlan) |
3fef9acf | 476 | { |
5a47b073 | 477 | /*printk(KERN_INFO "%s\n", __func__);*/ |
3fef9acf MM |
478 | return 0; |
479 | } | |
480 | ||
481 | static int esp_cfg80211_resume(struct wiphy *wiphy) | |
482 | { | |
5a47b073 | 483 | /*printk(KERN_INFO "%s\n", __func__);*/ |
3fef9acf MM |
484 | return 0; |
485 | } | |
486 | ||
487 | static void esp_cfg80211_set_wakeup(struct wiphy *wiphy, | |
5a47b073 | 488 | bool enabled) |
3fef9acf | 489 | { |
5a47b073 | 490 | /*printk(KERN_INFO "%s\n", __func__);*/ |
3fef9acf MM |
491 | } |
492 | ||
774e9b2e MM |
493 | static struct cfg80211_ops esp_cfg80211_ops = { |
494 | #if 0 | |
495 | .add_virtual_intf = esp_cfg80211_add_iface, | |
496 | .del_virtual_intf = esp_cfg80211_del_iface, | |
497 | .change_virtual_intf = esp_cfg80211_change_iface, | |
498 | #endif | |
499 | .scan = esp_cfg80211_scan, | |
bd131325 | 500 | /*.connect = esp_cfg80211_connect,*/ |
774e9b2e MM |
501 | .disconnect = esp_cfg80211_disconnect, |
502 | .add_key = esp_cfg80211_add_key, | |
503 | .del_key = esp_cfg80211_del_key, | |
504 | .set_default_key = esp_cfg80211_set_default_key, | |
505 | .mgmt_tx = esp_cfg80211_mgmt_tx, | |
7b6ed49e MM |
506 | .auth = esp_cfg80211_authenticate, |
507 | .deauth = esp_cfg80211_deauth, | |
508 | .disassoc = esp_cfg80211_disassoc, | |
509 | .assoc = esp_cfg80211_associate, | |
3fef9acf MM |
510 | .suspend = esp_cfg80211_suspend, |
511 | .resume = esp_cfg80211_resume, | |
512 | .set_wakeup = esp_cfg80211_set_wakeup, | |
774e9b2e MM |
513 | }; |
514 | ||
515 | int esp_cfg80211_register(struct esp_adapter *adapter) | |
516 | { | |
517 | struct wiphy *wiphy; | |
518 | struct esp_device *esp_dev; | |
519 | int ret = 0; | |
520 | ||
521 | wiphy = wiphy_new(&esp_cfg80211_ops, sizeof(struct esp_device)); | |
522 | ||
523 | if (!wiphy) { | |
524 | printk(KERN_ERR "Failed to create wiphy\n"); | |
525 | return -EFAULT; | |
526 | } | |
527 | ||
528 | adapter->wiphy = wiphy; | |
529 | ||
530 | esp_dev = wiphy_priv(wiphy); | |
531 | esp_dev->wiphy = wiphy; | |
532 | esp_dev->adapter = adapter; | |
533 | ||
534 | esp_dev->dev = adapter->dev; | |
535 | ||
536 | set_wiphy_dev(wiphy, esp_dev->dev); | |
537 | ||
538 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | |
539 | wiphy->bands[NL80211_BAND_2GHZ] = &esp_wifi_bands; | |
540 | ||
541 | /* Initialize cipher suits */ | |
542 | wiphy->cipher_suites = esp_cipher_suites; | |
543 | wiphy->n_cipher_suites = ARRAY_SIZE(esp_cipher_suites); | |
544 | ||
545 | /* TODO: check and finalize the numbers */ | |
546 | wiphy->max_scan_ssids = 10; | |
547 | /* wiphy->max_match_sets = 10;*/ | |
548 | wiphy->max_scan_ie_len = 1000; | |
549 | wiphy->max_sched_scan_ssids = 10; | |
550 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | |
3fef9acf | 551 | wiphy->wowlan = &esp_wowlan_support; |
774e9b2e | 552 | |
7b6ed49e MM |
553 | /* Advertise SAE support */ |
554 | wiphy->features |= NL80211_FEATURE_SAE; | |
555 | ||
774e9b2e MM |
556 | ret = wiphy_register(wiphy); |
557 | ||
558 | return ret; | |
559 | } | |
560 | ||
225e14eb YM |
561 | int esp_mark_disconnect(struct esp_wifi_device *priv, uint16_t reason, |
562 | uint8_t locally_disconnect) | |
563 | { | |
564 | if (priv && priv->ndev) | |
aad2ae2e YM |
565 | if (priv->ndev->reg_state == NETREG_REGISTERED) |
566 | CFG80211_DISCONNECTED(priv->ndev, reason, NULL, 0, locally_disconnect, | |
567 | GFP_KERNEL); | |
225e14eb YM |
568 | return 0; |
569 | } | |
570 | ||
571 | int esp_mark_scan_done_and_disconnect(struct esp_wifi_device *priv, | |
572 | uint8_t locally_disconnect) | |
573 | { | |
225e14eb YM |
574 | |
575 | if (!priv) | |
576 | return -EINVAL; | |
577 | ||
0af9c02e | 578 | ESP_MARK_SCAN_DONE(priv, true); |
225e14eb YM |
579 | |
580 | ESP_CANCEL_SCHED_SCAN(); | |
581 | ||
aad2ae2e | 582 | esp_mark_disconnect(priv, 0, locally_disconnect); |
225e14eb | 583 | |
225e14eb YM |
584 | return 0; |
585 | } |