]>
Commit | Line | Data |
---|---|---|
774e9b2e MM |
1 | /* |
2 | * Espressif Systems Wireless LAN device driver | |
3 | * | |
4 | * Copyright (C) 2015-2021 Espressif Systems (Shanghai) PTE LTD | |
5 | * | |
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) | |
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 | |
8 | * (the "License"). You may use, redistribute and/or modify this File in | |
9 | * accordance with the terms and conditions of the License, a copy of which | |
10 | * is available by writing to the Free Software Foundation, Inc., | |
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | |
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | |
13 | * | |
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | |
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | |
17 | * this warranty disclaimer. | |
18 | */ | |
19 | ||
20 | #include "esp.h" | |
21 | #include "esp_api.h" | |
22 | #include "esp_cfg80211.h" | |
23 | #include "esp_cmd.h" | |
24 | ||
25 | /** | |
26 | * @brief WiFi PHY rate encodings | |
27 | * | |
28 | */ | |
29 | typedef enum { | |
30 | WIFI_PHY_RATE_1M_L = 0x00, /**< 1 Mbps with long preamble */ | |
31 | WIFI_PHY_RATE_2M_L = 0x01, /**< 2 Mbps with long preamble */ | |
32 | WIFI_PHY_RATE_5M_L = 0x02, /**< 5.5 Mbps with long preamble */ | |
33 | WIFI_PHY_RATE_11M_L = 0x03, /**< 11 Mbps with long preamble */ | |
34 | WIFI_PHY_RATE_2M_S = 0x05, /**< 2 Mbps with short preamble */ | |
35 | WIFI_PHY_RATE_5M_S = 0x06, /**< 5.5 Mbps with short preamble */ | |
36 | WIFI_PHY_RATE_11M_S = 0x07, /**< 11 Mbps with short preamble */ | |
37 | WIFI_PHY_RATE_48M = 0x08, /**< 48 Mbps */ | |
38 | WIFI_PHY_RATE_24M = 0x09, /**< 24 Mbps */ | |
39 | WIFI_PHY_RATE_12M = 0x0A, /**< 12 Mbps */ | |
40 | WIFI_PHY_RATE_6M = 0x0B, /**< 6 Mbps */ | |
41 | WIFI_PHY_RATE_54M = 0x0C, /**< 54 Mbps */ | |
42 | WIFI_PHY_RATE_36M = 0x0D, /**< 36 Mbps */ | |
43 | WIFI_PHY_RATE_18M = 0x0E, /**< 18 Mbps */ | |
44 | WIFI_PHY_RATE_9M = 0x0F, /**< 9 Mbps */ | |
45 | WIFI_PHY_RATE_MCS0_LGI = 0x10, /**< MCS0 with long GI, 6.5 Mbps for 20MHz, 13.5 Mbps for 40MHz */ | |
46 | WIFI_PHY_RATE_MCS1_LGI = 0x11, /**< MCS1 with long GI, 13 Mbps for 20MHz, 27 Mbps for 40MHz */ | |
47 | WIFI_PHY_RATE_MCS2_LGI = 0x12, /**< MCS2 with long GI, 19.5 Mbps for 20MHz, 40.5 Mbps for 40MHz */ | |
48 | WIFI_PHY_RATE_MCS3_LGI = 0x13, /**< MCS3 with long GI, 26 Mbps for 20MHz, 54 Mbps for 40MHz */ | |
49 | WIFI_PHY_RATE_MCS4_LGI = 0x14, /**< MCS4 with long GI, 39 Mbps for 20MHz, 81 Mbps for 40MHz */ | |
50 | WIFI_PHY_RATE_MCS5_LGI = 0x15, /**< MCS5 with long GI, 52 Mbps for 20MHz, 108 Mbps for 40MHz */ | |
51 | WIFI_PHY_RATE_MCS6_LGI = 0x16, /**< MCS6 with long GI, 58.5 Mbps for 20MHz, 121.5 Mbps for 40MHz */ | |
52 | WIFI_PHY_RATE_MCS7_LGI = 0x17, /**< MCS7 with long GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */ | |
53 | WIFI_PHY_RATE_MCS0_SGI = 0x18, /**< MCS0 with short GI, 7.2 Mbps for 20MHz, 15 Mbps for 40MHz */ | |
54 | WIFI_PHY_RATE_MCS1_SGI = 0x19, /**< MCS1 with short GI, 14.4 Mbps for 20MHz, 30 Mbps for 40MHz */ | |
55 | WIFI_PHY_RATE_MCS2_SGI = 0x1A, /**< MCS2 with short GI, 21.7 Mbps for 20MHz, 45 Mbps for 40MHz */ | |
56 | WIFI_PHY_RATE_MCS3_SGI = 0x1B, /**< MCS3 with short GI, 28.9 Mbps for 20MHz, 60 Mbps for 40MHz */ | |
57 | WIFI_PHY_RATE_MCS4_SGI = 0x1C, /**< MCS4 with short GI, 43.3 Mbps for 20MHz, 90 Mbps for 40MHz */ | |
58 | WIFI_PHY_RATE_MCS5_SGI = 0x1D, /**< MCS5 with short GI, 57.8 Mbps for 20MHz, 120 Mbps for 40MHz */ | |
59 | WIFI_PHY_RATE_MCS6_SGI = 0x1E, /**< MCS6 with short GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */ | |
60 | WIFI_PHY_RATE_MCS7_SGI = 0x1F, /**< MCS7 with short GI, 72.2 Mbps for 20MHz, 150 Mbps for 40MHz */ | |
61 | WIFI_PHY_RATE_LORA_250K = 0x29, /**< 250 Kbps */ | |
62 | WIFI_PHY_RATE_LORA_500K = 0x2A, /**< 500 Kbps */ | |
63 | WIFI_PHY_RATE_MAX, | |
64 | } wifi_phy_rate_t; | |
65 | ||
66 | /* Supported rates to be advertised to the cfg80211 */ | |
67 | static struct ieee80211_rate esp_rates[] = { | |
68 | {.bitrate = 10, .hw_value = WIFI_PHY_RATE_1M_L, }, | |
69 | {.bitrate = 20, .hw_value = WIFI_PHY_RATE_2M_L, }, | |
70 | {.bitrate = 55, .hw_value = WIFI_PHY_RATE_5M_L, .hw_value_short = WIFI_PHY_RATE_5M_S}, | |
71 | {.bitrate = 110, .hw_value = WIFI_PHY_RATE_11M_L, .hw_value_short = WIFI_PHY_RATE_11M_S}, | |
72 | {.bitrate = 60, .hw_value = WIFI_PHY_RATE_6M, }, | |
73 | {.bitrate = 90, .hw_value = WIFI_PHY_RATE_9M, }, | |
74 | {.bitrate = 120, .hw_value = WIFI_PHY_RATE_12M, }, | |
75 | {.bitrate = 180, .hw_value = WIFI_PHY_RATE_18M, }, | |
76 | {.bitrate = 240, .hw_value = WIFI_PHY_RATE_24M, }, | |
77 | {.bitrate = 360, .hw_value = WIFI_PHY_RATE_36M, }, | |
78 | {.bitrate = 480, .hw_value = WIFI_PHY_RATE_48M, }, | |
79 | {.bitrate = 540, .hw_value = WIFI_PHY_RATE_54M, }, | |
80 | }; | |
81 | ||
82 | ||
83 | /* Channel definitions to be advertised to cfg80211 */ | |
84 | static struct ieee80211_channel esp_channels_2ghz[] = { | |
85 | {.center_freq = 2412, .hw_value = 1, }, | |
86 | {.center_freq = 2417, .hw_value = 2, }, | |
87 | {.center_freq = 2422, .hw_value = 3, }, | |
88 | {.center_freq = 2427, .hw_value = 4, }, | |
89 | {.center_freq = 2432, .hw_value = 5, }, | |
90 | {.center_freq = 2437, .hw_value = 6, }, | |
91 | {.center_freq = 2442, .hw_value = 7, }, | |
92 | {.center_freq = 2447, .hw_value = 8, }, | |
93 | {.center_freq = 2452, .hw_value = 9, }, | |
94 | {.center_freq = 2457, .hw_value = 10, }, | |
95 | {.center_freq = 2462, .hw_value = 11, }, | |
96 | {.center_freq = 2467, .hw_value = 12, }, | |
97 | {.center_freq = 2472, .hw_value = 13, }, | |
98 | {.center_freq = 2484, .hw_value = 14, }, | |
99 | }; | |
100 | ||
101 | static struct ieee80211_supported_band esp_wifi_bands = { | |
102 | .channels = esp_channels_2ghz, | |
103 | .n_channels = ARRAY_SIZE(esp_channels_2ghz), | |
104 | .bitrates = esp_rates, | |
105 | .n_bitrates = ARRAY_SIZE(esp_rates), | |
106 | }; | |
107 | ||
108 | /* Supported crypto cipher suits to be advertised to cfg80211 */ | |
109 | static const u32 esp_cipher_suites[] = { | |
110 | WLAN_CIPHER_SUITE_WEP40, | |
111 | WLAN_CIPHER_SUITE_WEP104, | |
112 | WLAN_CIPHER_SUITE_TKIP, | |
113 | WLAN_CIPHER_SUITE_CCMP, | |
114 | WLAN_CIPHER_SUITE_SMS4, | |
115 | WLAN_CIPHER_SUITE_AES_CMAC, | |
116 | }; | |
117 | ||
118 | struct wireless_dev *esp_cfg80211_add_iface(struct wiphy *wiphy, | |
119 | const char *name, | |
120 | unsigned char name_assign_type, | |
121 | enum nl80211_iftype type, | |
122 | struct vif_params *params) | |
123 | { | |
124 | struct esp_device *esp_dev = wiphy_priv(wiphy); | |
125 | /* struct wireless_dev *wdev = NULL;*/ | |
126 | struct net_device *ndev; | |
127 | struct esp_wifi_device *esp_wdev; | |
128 | uint8_t esp_nw_if_num = 0; | |
129 | ||
130 | if (NL80211_IFTYPE_STATION == type) { | |
131 | esp_nw_if_num = ESP_STA_NW_IF; | |
132 | } else if (NL80211_IFTYPE_AP == type) { | |
133 | esp_nw_if_num = ESP_AP_NW_IF; | |
134 | } else { | |
135 | printk(KERN_INFO "%s:%u network type[%u] is not supported\n", | |
136 | __func__, __LINE__, type); | |
137 | return NULL; | |
138 | } | |
139 | ||
140 | ndev = alloc_netdev(sizeof(struct esp_wifi_device), name, name_assign_type, | |
141 | ether_setup); | |
142 | ||
143 | if (!ndev) | |
144 | return ERR_PTR(-ENOMEM); | |
145 | ||
225e14eb | 146 | set_bit(ESP_DRIVER_ACTIVE, &esp_dev->adapter->state_flags); |
774e9b2e MM |
147 | esp_wdev = netdev_priv(ndev); |
148 | ||
149 | ndev->ieee80211_ptr = &esp_wdev->wdev; | |
150 | esp_wdev->wdev.wiphy = wiphy; | |
151 | esp_wdev->esp_dev = esp_dev; | |
152 | esp_wdev->ndev = ndev; | |
153 | esp_wdev->adapter = esp_dev->adapter; | |
154 | esp_wdev->adapter->priv[esp_nw_if_num] = esp_wdev; | |
155 | /*printk(KERN_INFO "Updated priv[%u] to %px\n", | |
156 | * esp_nw_if_num, esp_wdev->adapter->priv[esp_nw_if_num]);*/ | |
157 | dev_net_set(ndev, wiphy_net(wiphy)); | |
158 | SET_NETDEV_DEV(ndev, wiphy_dev(esp_wdev->wdev.wiphy)); | |
159 | esp_wdev->wdev.netdev = ndev; | |
160 | esp_wdev->wdev.iftype = type; | |
161 | ||
162 | init_waitqueue_head(&esp_wdev->wait_for_scan_completion); | |
163 | esp_wdev->stop_data = 1; | |
164 | esp_wdev->port_open = 0; | |
165 | ||
166 | if (cmd_init_interface(esp_wdev)) | |
167 | goto free_and_return; | |
168 | ||
169 | if (cmd_get_mac(esp_wdev)) | |
170 | goto free_and_return; | |
171 | ||
172 | /* memcpy(ndev->dev_addr, esp_wdev->mac_address, ETH_ALEN);*/ | |
173 | ether_addr_copy(ndev->dev_addr, esp_wdev->mac_address); | |
174 | ||
175 | esp_init_priv(ndev); | |
176 | ||
177 | if (register_netdevice(ndev)) | |
178 | goto free_and_return; | |
179 | ||
180 | ||
181 | set_bit(ESP_NETWORK_UP, &esp_wdev->priv_flags); | |
225e14eb YM |
182 | clear_bit(ESP_CLEANUP_IN_PROGRESS, &esp_dev->adapter->state_flags); |
183 | ||
774e9b2e MM |
184 | return &esp_wdev->wdev; |
185 | ||
186 | free_and_return: | |
225e14eb | 187 | clear_bit(ESP_DRIVER_ACTIVE, &esp_wdev->adapter->state_flags); |
774e9b2e MM |
188 | dev_net_set(ndev, NULL); |
189 | free_netdev(ndev); | |
190 | esp_wdev->ndev = NULL; | |
191 | esp_wdev->wdev.netdev = NULL; | |
192 | ndev = NULL; | |
193 | return NULL; | |
194 | } | |
195 | ||
196 | #if 0 | |
197 | static int esp_cfg80211_del_iface(struct wiphy *wiphy, | |
198 | struct wireless_dev *wdev) | |
199 | { | |
200 | return 0; | |
201 | } | |
202 | ||
203 | static int esp_cfg80211_change_iface(struct wiphy *wiphy, | |
204 | struct net_device *ndev, | |
205 | enum nl80211_iftype type, | |
206 | struct vif_params *params) | |
207 | { | |
208 | return 0; | |
209 | } | |
210 | #endif | |
211 | ||
212 | static int esp_cfg80211_scan(struct wiphy *wiphy, | |
213 | struct cfg80211_scan_request *request) | |
214 | { | |
215 | struct net_device *ndev = request->wdev->netdev; | |
216 | struct esp_wifi_device *priv = netdev_priv(ndev); | |
217 | ||
218 | if (!priv) { | |
219 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
220 | return -EINVAL; | |
221 | } | |
222 | ||
223 | return cmd_scan_request(priv, request); | |
224 | } | |
225 | ||
226 | static int esp_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |
227 | struct cfg80211_connect_params *sme) | |
228 | { | |
229 | struct esp_wifi_device *priv = netdev_priv(dev); | |
230 | ||
231 | if (!priv) { | |
232 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
233 | return -EINVAL; | |
234 | } | |
235 | ||
236 | return cmd_connect_request(priv, sme); | |
237 | } | |
238 | ||
239 | static int esp_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *dev, | |
240 | struct cfg80211_mgmt_tx_params *params, u64 *cookie) | |
241 | { | |
242 | return 0; | |
243 | } | |
244 | ||
245 | static int esp_cfg80211_set_default_key(struct wiphy *wiphy, | |
246 | struct net_device *dev, u8 key_index, bool unicast, bool multicast) | |
247 | { | |
248 | struct esp_wifi_device *priv = netdev_priv(dev); | |
249 | ||
250 | if (!priv) { | |
251 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
252 | return -EINVAL; | |
253 | } | |
254 | ||
255 | return cmd_set_default_key(priv, key_index); | |
256 | } | |
257 | ||
258 | static int esp_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |
259 | u8 key_index, bool pairwise, const u8 *mac_addr) | |
260 | { | |
261 | struct esp_wifi_device *priv = netdev_priv(dev); | |
262 | ||
263 | if (!priv) { | |
264 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
265 | return -EINVAL; | |
266 | } | |
267 | ||
268 | return cmd_del_key(priv, key_index, pairwise, mac_addr); | |
269 | } | |
270 | ||
271 | static int esp_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |
272 | u8 key_index, bool pairwise, const u8 *mac_addr, | |
273 | struct key_params *params) | |
274 | { | |
275 | struct esp_wifi_device *priv = netdev_priv(dev); | |
276 | ||
277 | if (!priv) { | |
278 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
279 | return -EINVAL; | |
280 | } | |
281 | ||
282 | if (params->key_len == 0) | |
283 | return esp_cfg80211_del_key(wiphy, dev, key_index, pairwise, mac_addr); | |
284 | ||
285 | return cmd_add_key(priv, key_index, pairwise, mac_addr, params); | |
286 | } | |
287 | ||
288 | static int esp_cfg80211_disconnect(struct wiphy *wiphy, | |
289 | struct net_device *dev, u16 reason_code) | |
290 | { | |
291 | struct esp_wifi_device *priv = netdev_priv(dev); | |
292 | ||
293 | if (!priv) { | |
294 | printk(KERN_ERR "%s: empty priv\n", __func__); | |
295 | return 0; | |
296 | } | |
297 | ||
298 | return cmd_disconnect_request(priv, reason_code); | |
299 | } | |
300 | ||
301 | static struct cfg80211_ops esp_cfg80211_ops = { | |
302 | #if 0 | |
303 | .add_virtual_intf = esp_cfg80211_add_iface, | |
304 | .del_virtual_intf = esp_cfg80211_del_iface, | |
305 | .change_virtual_intf = esp_cfg80211_change_iface, | |
306 | #endif | |
307 | .scan = esp_cfg80211_scan, | |
308 | .connect = esp_cfg80211_connect, | |
309 | .disconnect = esp_cfg80211_disconnect, | |
310 | .add_key = esp_cfg80211_add_key, | |
311 | .del_key = esp_cfg80211_del_key, | |
312 | .set_default_key = esp_cfg80211_set_default_key, | |
313 | .mgmt_tx = esp_cfg80211_mgmt_tx, | |
314 | }; | |
315 | ||
316 | int esp_cfg80211_register(struct esp_adapter *adapter) | |
317 | { | |
318 | struct wiphy *wiphy; | |
319 | struct esp_device *esp_dev; | |
320 | int ret = 0; | |
321 | ||
322 | wiphy = wiphy_new(&esp_cfg80211_ops, sizeof(struct esp_device)); | |
323 | ||
324 | if (!wiphy) { | |
325 | printk(KERN_ERR "Failed to create wiphy\n"); | |
326 | return -EFAULT; | |
327 | } | |
328 | ||
329 | adapter->wiphy = wiphy; | |
330 | ||
331 | esp_dev = wiphy_priv(wiphy); | |
332 | esp_dev->wiphy = wiphy; | |
333 | esp_dev->adapter = adapter; | |
334 | ||
335 | esp_dev->dev = adapter->dev; | |
336 | ||
337 | set_wiphy_dev(wiphy, esp_dev->dev); | |
338 | ||
339 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | |
340 | wiphy->bands[NL80211_BAND_2GHZ] = &esp_wifi_bands; | |
341 | ||
342 | /* Initialize cipher suits */ | |
343 | wiphy->cipher_suites = esp_cipher_suites; | |
344 | wiphy->n_cipher_suites = ARRAY_SIZE(esp_cipher_suites); | |
345 | ||
346 | /* TODO: check and finalize the numbers */ | |
347 | wiphy->max_scan_ssids = 10; | |
348 | /* wiphy->max_match_sets = 10;*/ | |
349 | wiphy->max_scan_ie_len = 1000; | |
350 | wiphy->max_sched_scan_ssids = 10; | |
351 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | |
352 | ||
353 | ret = wiphy_register(wiphy); | |
354 | ||
355 | return ret; | |
356 | } | |
357 | ||
225e14eb YM |
358 | int esp_mark_scan_done(struct esp_wifi_device *priv) |
359 | { | |
360 | struct cfg80211_scan_info info = { | |
361 | .aborted = false, | |
362 | }; | |
363 | ||
364 | if (!priv) | |
365 | return -EINVAL; | |
366 | ||
367 | if (priv->request) | |
368 | cfg80211_scan_done(priv->request, &info); | |
369 | ||
370 | priv->scan_in_progress = false; | |
371 | priv->request = NULL; | |
372 | ||
373 | return 0; | |
374 | } | |
375 | ||
376 | int esp_mark_disconnect(struct esp_wifi_device *priv, uint16_t reason, | |
377 | uint8_t locally_disconnect) | |
378 | { | |
379 | if (priv && priv->ndev) | |
380 | cfg80211_disconnected(priv->ndev, reason, NULL, 0, locally_disconnect, | |
381 | GFP_KERNEL); | |
382 | return 0; | |
383 | } | |
384 | ||
385 | int esp_mark_scan_done_and_disconnect(struct esp_wifi_device *priv, | |
386 | uint8_t locally_disconnect) | |
387 | { | |
388 | struct net_device *ndev = NULL; | |
389 | struct cfg80211_scan_info info = { | |
390 | .aborted = false, | |
391 | }; | |
392 | ||
393 | if (!priv) | |
394 | return -EINVAL; | |
395 | ||
396 | if (priv->request) | |
397 | cfg80211_scan_done(priv->request, &info); | |
398 | ||
399 | ESP_CANCEL_SCHED_SCAN(); | |
400 | ||
401 | priv->scan_in_progress = false; | |
402 | priv->request = NULL; | |
403 | ||
404 | /* clear cfg80211 states */ | |
405 | ndev = priv->ndev; | |
406 | if (ndev) { | |
407 | if (ndev->reg_state == NETREG_REGISTERED) { | |
408 | cfg80211_disconnected(ndev, 0, NULL, 0, locally_disconnect, | |
409 | GFP_KERNEL); | |
410 | } | |
411 | } | |
412 | return 0; | |
413 | } |