]> Git Repo - esp-hosted.git/blame - esp_hosted_ng/host/esp_cfg80211.c
fix(esp_hosted_ng): Add support for esp32-c6 SDIO
[esp-hosted.git] / esp_hosted_ng / host / esp_cfg80211.c
CommitLineData
e8b168e8 1// SPDX-License-Identifier: GPL-2.0-only
774e9b2e
MM
2/*
3 * Espressif Systems Wireless LAN device driver
4 *
d7215282 5 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
774e9b2e 6 *
774e9b2e 7 */
057d3956 8#include "utils.h"
774e9b2e
MM
9#include "esp.h"
10#include "esp_api.h"
11#include "esp_cfg80211.h"
12#include "esp_cmd.h"
aad2ae2e 13#include "esp_kernel_port.h"
774e9b2e
MM
14
15/**
16 * @brief WiFi PHY rate encodings
17 *
18 */
19typedef enum {
5a47b073
MM
20 WIFI_PHY_RATE_1M_L = 0x00, /**< 1 Mbps with long preamble */
21 WIFI_PHY_RATE_2M_L = 0x01, /**< 2 Mbps with long preamble */
22 WIFI_PHY_RATE_5M_L = 0x02, /**< 5.5 Mbps with long preamble */
23 WIFI_PHY_RATE_11M_L = 0x03, /**< 11 Mbps with long preamble */
24 WIFI_PHY_RATE_2M_S = 0x05, /**< 2 Mbps with short preamble */
25 WIFI_PHY_RATE_5M_S = 0x06, /**< 5.5 Mbps with short preamble */
26 WIFI_PHY_RATE_11M_S = 0x07, /**< 11 Mbps with short preamble */
27 WIFI_PHY_RATE_48M = 0x08, /**< 48 Mbps */
28 WIFI_PHY_RATE_24M = 0x09, /**< 24 Mbps */
29 WIFI_PHY_RATE_12M = 0x0A, /**< 12 Mbps */
30 WIFI_PHY_RATE_6M = 0x0B, /**< 6 Mbps */
31 WIFI_PHY_RATE_54M = 0x0C, /**< 54 Mbps */
32 WIFI_PHY_RATE_36M = 0x0D, /**< 36 Mbps */
33 WIFI_PHY_RATE_18M = 0x0E, /**< 18 Mbps */
34 WIFI_PHY_RATE_9M = 0x0F, /**< 9 Mbps */
35 WIFI_PHY_RATE_MCS0_LGI = 0x10, /**< MCS0 with long GI, 6.5 Mbps for 20MHz, 13.5 Mbps for 40MHz */
36 WIFI_PHY_RATE_MCS1_LGI = 0x11, /**< MCS1 with long GI, 13 Mbps for 20MHz, 27 Mbps for 40MHz */
37 WIFI_PHY_RATE_MCS2_LGI = 0x12, /**< MCS2 with long GI, 19.5 Mbps for 20MHz, 40.5 Mbps for 40MHz */
38 WIFI_PHY_RATE_MCS3_LGI = 0x13, /**< MCS3 with long GI, 26 Mbps for 20MHz, 54 Mbps for 40MHz */
39 WIFI_PHY_RATE_MCS4_LGI = 0x14, /**< MCS4 with long GI, 39 Mbps for 20MHz, 81 Mbps for 40MHz */
40 WIFI_PHY_RATE_MCS5_LGI = 0x15, /**< MCS5 with long GI, 52 Mbps for 20MHz, 108 Mbps for 40MHz */
41 WIFI_PHY_RATE_MCS6_LGI = 0x16, /**< MCS6 with long GI, 58.5 Mbps for 20MHz, 121.5 Mbps for 40MHz */
42 WIFI_PHY_RATE_MCS7_LGI = 0x17, /**< MCS7 with long GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */
43 WIFI_PHY_RATE_MCS0_SGI = 0x18, /**< MCS0 with short GI, 7.2 Mbps for 20MHz, 15 Mbps for 40MHz */
44 WIFI_PHY_RATE_MCS1_SGI = 0x19, /**< MCS1 with short GI, 14.4 Mbps for 20MHz, 30 Mbps for 40MHz */
45 WIFI_PHY_RATE_MCS2_SGI = 0x1A, /**< MCS2 with short GI, 21.7 Mbps for 20MHz, 45 Mbps for 40MHz */
46 WIFI_PHY_RATE_MCS3_SGI = 0x1B, /**< MCS3 with short GI, 28.9 Mbps for 20MHz, 60 Mbps for 40MHz */
47 WIFI_PHY_RATE_MCS4_SGI = 0x1C, /**< MCS4 with short GI, 43.3 Mbps for 20MHz, 90 Mbps for 40MHz */
48 WIFI_PHY_RATE_MCS5_SGI = 0x1D, /**< MCS5 with short GI, 57.8 Mbps for 20MHz, 120 Mbps for 40MHz */
49 WIFI_PHY_RATE_MCS6_SGI = 0x1E, /**< MCS6 with short GI, 65 Mbps for 20MHz, 135 Mbps for 40MHz */
50 WIFI_PHY_RATE_MCS7_SGI = 0x1F, /**< MCS7 with short GI, 72.2 Mbps for 20MHz, 150 Mbps for 40MHz */
51 WIFI_PHY_RATE_LORA_250K = 0x29, /**< 250 Kbps */
52 WIFI_PHY_RATE_LORA_500K = 0x2A, /**< 500 Kbps */
53 WIFI_PHY_RATE_MAX,
774e9b2e
MM
54} wifi_phy_rate_t;
55
56/* Supported rates to be advertised to the cfg80211 */
57static struct ieee80211_rate esp_rates[] = {
5a47b073
MM
58 {.bitrate = 10, .hw_value = WIFI_PHY_RATE_1M_L, },
59 {.bitrate = 20, .hw_value = WIFI_PHY_RATE_2M_L, },
60 {.bitrate = 55, .hw_value = WIFI_PHY_RATE_5M_L, .hw_value_short = WIFI_PHY_RATE_5M_S},
61 {.bitrate = 110, .hw_value = WIFI_PHY_RATE_11M_L, .hw_value_short = WIFI_PHY_RATE_11M_S},
62 {.bitrate = 60, .hw_value = WIFI_PHY_RATE_6M, },
63 {.bitrate = 90, .hw_value = WIFI_PHY_RATE_9M, },
64 {.bitrate = 120, .hw_value = WIFI_PHY_RATE_12M, },
65 {.bitrate = 180, .hw_value = WIFI_PHY_RATE_18M, },
66 {.bitrate = 240, .hw_value = WIFI_PHY_RATE_24M, },
67 {.bitrate = 360, .hw_value = WIFI_PHY_RATE_36M, },
68 {.bitrate = 480, .hw_value = WIFI_PHY_RATE_48M, },
69 {.bitrate = 540, .hw_value = WIFI_PHY_RATE_54M, },
774e9b2e
MM
70};
71
72
73/* Channel definitions to be advertised to cfg80211 */
74static struct ieee80211_channel esp_channels_2ghz[] = {
5a47b073
MM
75 {.center_freq = 2412, .hw_value = 1, },
76 {.center_freq = 2417, .hw_value = 2, },
77 {.center_freq = 2422, .hw_value = 3, },
78 {.center_freq = 2427, .hw_value = 4, },
79 {.center_freq = 2432, .hw_value = 5, },
80 {.center_freq = 2437, .hw_value = 6, },
81 {.center_freq = 2442, .hw_value = 7, },
82 {.center_freq = 2447, .hw_value = 8, },
83 {.center_freq = 2452, .hw_value = 9, },
84 {.center_freq = 2457, .hw_value = 10, },
85 {.center_freq = 2462, .hw_value = 11, },
86 {.center_freq = 2467, .hw_value = 12, },
87 {.center_freq = 2472, .hw_value = 13, },
88 {.center_freq = 2484, .hw_value = 14, },
774e9b2e
MM
89};
90
91static struct ieee80211_supported_band esp_wifi_bands = {
5a47b073
MM
92 .channels = esp_channels_2ghz,
93 .n_channels = ARRAY_SIZE(esp_channels_2ghz),
94 .bitrates = esp_rates,
95 .n_bitrates = ARRAY_SIZE(esp_rates),
774e9b2e
MM
96};
97
98/* Supported crypto cipher suits to be advertised to cfg80211 */
99static const u32 esp_cipher_suites[] = {
5a47b073
MM
100 WLAN_CIPHER_SUITE_WEP40,
101 WLAN_CIPHER_SUITE_WEP104,
102 WLAN_CIPHER_SUITE_TKIP,
103 WLAN_CIPHER_SUITE_CCMP,
104 WLAN_CIPHER_SUITE_SMS4,
105 WLAN_CIPHER_SUITE_AES_CMAC,
774e9b2e
MM
106};
107
3fef9acf 108static const struct wiphy_wowlan_support esp_wowlan_support = {
5a47b073
MM
109 .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT,
110 .n_patterns = 0,
111 .pattern_max_len = 0,
112 .pattern_min_len = 0,
113 .max_pkt_offset = 0,
3fef9acf
MM
114};
115
7406fe82 116static int esp_inetaddr_event(struct notifier_block *nb,
5a47b073 117 unsigned long event, void *data)
7406fe82 118{
5a47b073
MM
119 struct in_ifaddr *ifa = data;
120 struct net_device *netdev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
7406fe82
MM
121 struct esp_wifi_device *priv = netdev_priv(netdev);
122
6f8fee57 123 /*esp_info("------- IP event -------: %d\n", priv->if_type);*/
5a47b073
MM
124
125 if (!strstr(netdev->name, "espsta")) {
126 return 0;
127 }
128
129 switch (event) {
130
131 case NETDEV_UP:
132 if (priv && (priv->if_type == ESP_STA_IF)) {
133 cmd_set_ip_address(priv, ifa->ifa_local);
a3829bf3 134 esp_info("NETDEV_UP interface %s ip changed to %pi4\n",
6f8fee57 135 netdev->name, &ifa->ifa_local);
5a47b073
MM
136 }
137 break;
138
139 case NETDEV_DOWN:
6f8fee57 140 esp_info("Interface Down: %d\n", priv->if_type);
5a47b073
MM
141 if (priv && (priv->if_type == ESP_STA_IF))
142 cmd_set_ip_address(priv, 0);
143 break;
144 }
145
146 return 0;
7406fe82
MM
147}
148
774e9b2e 149struct wireless_dev *esp_cfg80211_add_iface(struct wiphy *wiphy,
5a47b073
MM
150 const char *name,
151 unsigned char name_assign_type,
152 enum nl80211_iftype type,
153 struct vif_params *params)
774e9b2e 154{
bd131325 155 struct esp_device *esp_dev = NULL;
774e9b2e
MM
156/* struct wireless_dev *wdev = NULL;*/
157 struct net_device *ndev;
158 struct esp_wifi_device *esp_wdev;
159 uint8_t esp_nw_if_num = 0;
160
bd131325 161 if (!wiphy || !name) {
6f8fee57 162 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
163 return NULL;
164 }
165
166 esp_dev = wiphy_priv(wiphy);
167
168 if (!esp_dev || !esp_dev->adapter) {
6f8fee57 169 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
170 return NULL;
171 }
172
a3829bf3 173 if (type == NL80211_IFTYPE_STATION) {
774e9b2e 174 esp_nw_if_num = ESP_STA_NW_IF;
a3829bf3 175 } else if (type == NL80211_IFTYPE_AP) {
774e9b2e
MM
176 esp_nw_if_num = ESP_AP_NW_IF;
177 } else {
6f8fee57
KG
178 esp_info("%u network type[%u] is not supported\n",
179 __LINE__, type);
774e9b2e
MM
180 return NULL;
181 }
182
aad2ae2e 183 ndev = ALLOC_NETDEV(sizeof(struct esp_wifi_device), name, name_assign_type,
774e9b2e
MM
184 ether_setup);
185
186 if (!ndev)
187 return ERR_PTR(-ENOMEM);
188
225e14eb 189 set_bit(ESP_DRIVER_ACTIVE, &esp_dev->adapter->state_flags);
774e9b2e
MM
190 esp_wdev = netdev_priv(ndev);
191
192 ndev->ieee80211_ptr = &esp_wdev->wdev;
193 esp_wdev->wdev.wiphy = wiphy;
194 esp_wdev->esp_dev = esp_dev;
195 esp_wdev->ndev = ndev;
196 esp_wdev->adapter = esp_dev->adapter;
197 esp_wdev->adapter->priv[esp_nw_if_num] = esp_wdev;
6f8fee57 198 /*esp_info("Updated priv[%u] to %px\n",
774e9b2e
MM
199 * esp_nw_if_num, esp_wdev->adapter->priv[esp_nw_if_num]);*/
200 dev_net_set(ndev, wiphy_net(wiphy));
201 SET_NETDEV_DEV(ndev, wiphy_dev(esp_wdev->wdev.wiphy));
202 esp_wdev->wdev.netdev = ndev;
203 esp_wdev->wdev.iftype = type;
204
205 init_waitqueue_head(&esp_wdev->wait_for_scan_completion);
206 esp_wdev->stop_data = 1;
207 esp_wdev->port_open = 0;
208
209 if (cmd_init_interface(esp_wdev))
210 goto free_and_return;
211
212 if (cmd_get_mac(esp_wdev))
213 goto free_and_return;
214
1294f8ac 215 eth_hw_addr_set(ndev, esp_wdev->mac_address);
774e9b2e
MM
216
217 esp_init_priv(ndev);
218
219 if (register_netdevice(ndev))
220 goto free_and_return;
221
222
223 set_bit(ESP_NETWORK_UP, &esp_wdev->priv_flags);
225e14eb
YM
224 clear_bit(ESP_CLEANUP_IN_PROGRESS, &esp_dev->adapter->state_flags);
225
7406fe82
MM
226 esp_wdev->nb.notifier_call = esp_inetaddr_event;
227 register_inetaddr_notifier(&esp_wdev->nb);
228
774e9b2e
MM
229 return &esp_wdev->wdev;
230
231free_and_return:
225e14eb 232 clear_bit(ESP_DRIVER_ACTIVE, &esp_wdev->adapter->state_flags);
774e9b2e
MM
233 dev_net_set(ndev, NULL);
234 free_netdev(ndev);
235 esp_wdev->ndev = NULL;
236 esp_wdev->wdev.netdev = NULL;
237 ndev = NULL;
238 return NULL;
239}
240
241#if 0
242static int esp_cfg80211_del_iface(struct wiphy *wiphy,
243 struct wireless_dev *wdev)
244{
245 return 0;
246}
247
248static int esp_cfg80211_change_iface(struct wiphy *wiphy,
249 struct net_device *ndev,
250 enum nl80211_iftype type,
251 struct vif_params *params)
252{
253 return 0;
254}
255#endif
256
257static int esp_cfg80211_scan(struct wiphy *wiphy,
bd131325 258 struct cfg80211_scan_request *request)
774e9b2e 259{
bd131325
YM
260
261 struct net_device *ndev = NULL;
262 struct esp_wifi_device *priv = NULL;
bd131325 263 if (!wiphy || !request || !request->wdev || !request->wdev->netdev) {
6f8fee57 264 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
265 return -EINVAL;
266 }
267
268 ndev = request->wdev->netdev;
269 priv = netdev_priv(ndev);
774e9b2e 270
e58fd496 271 esp_dbg("\n");
774e9b2e 272 if (!priv) {
6f8fee57 273 esp_err("Empty priv\n");
774e9b2e
MM
274 return -EINVAL;
275 }
276
277 return cmd_scan_request(priv, request);
278}
279
bd131325 280#if 0
774e9b2e
MM
281static 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
e58fd496 286 esp_dbg("\n");
774e9b2e 287 if (!priv) {
6f8fee57 288 esp_err("Empty priv\n");
774e9b2e
MM
289 return -EINVAL;
290 }
291
292 return cmd_connect_request(priv, sme);
293}
bd131325 294#endif
774e9b2e 295
aad2ae2e 296static ESP_MGMT_TX_PROTOTYPE()
774e9b2e
MM
297{
298 return 0;
299}
300
7426e123 301static 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 307 if (!wiphy || !dev) {
6f8fee57 308 esp_err("%u invalid params\n", __LINE__);
bd131325
YM
309 return -EINVAL;
310 }
311
312 priv = netdev_priv(dev);
774e9b2e 313 if (!priv) {
6f8fee57 314 esp_err("Empty priv");
774e9b2e
MM
315 return -EINVAL;
316 }
317
318 return cmd_set_default_key(priv, key_index);
319}
320
7426e123 321static 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{
1c991ada 325 return 0;
774e9b2e
MM
326}
327
7426e123 328static int esp_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
1294f8ac
KG
329 INT_LINK_ID u8 key_index, bool pairwise,
330 const u8 *mac_addr, struct key_params *params)
774e9b2e 331{
bd131325
YM
332 struct esp_wifi_device *priv = NULL;
333
334 if (!wiphy || !dev || !params) {
6f8fee57 335 esp_err("%u invalid params\n", __LINE__);
bd131325
YM
336 return -EINVAL;
337 }
774e9b2e 338
bd131325 339 priv = netdev_priv(dev);
774e9b2e 340 if (!priv) {
6f8fee57 341 esp_err("Empty priv\n");
774e9b2e
MM
342 return -EINVAL;
343 }
e58fd496 344 esp_dbg("\n");
774e9b2e 345
7426e123 346 if (params->key_len == 0) {
1294f8ac 347 return esp_cfg80211_del_key(wiphy, dev, ZERO_LINK_ID key_index, pairwise, mac_addr);
7426e123 348 }
774e9b2e
MM
349 return cmd_add_key(priv, key_index, pairwise, mac_addr, params);
350}
351
352static int esp_cfg80211_disconnect(struct wiphy *wiphy,
353 struct net_device *dev, u16 reason_code)
354{
bd131325
YM
355 struct esp_wifi_device *priv = NULL;
356
357 if (!wiphy || !dev) {
6f8fee57 358 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
359 return -EINVAL;
360 }
361
362 priv = netdev_priv(dev);
774e9b2e
MM
363
364 if (!priv) {
6f8fee57 365 esp_err("empty priv\n");
774e9b2e
MM
366 return 0;
367 }
e58fd496 368 esp_dbg("\n");
774e9b2e
MM
369
370 return cmd_disconnect_request(priv, reason_code);
371}
372
7b6ed49e
MM
373static int esp_cfg80211_authenticate(struct wiphy *wiphy, struct net_device *dev,
374 struct cfg80211_auth_request *req)
375{
bd131325
YM
376 struct esp_wifi_device *priv = NULL;
377
378 if (!wiphy || !dev || !req) {
6f8fee57 379 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
380 return -EINVAL;
381 }
382
e58fd496 383 esp_dbg("\n");
7b6ed49e 384
bd131325
YM
385 priv = netdev_priv(dev);
386
7b6ed49e 387 if (!priv) {
6f8fee57 388 esp_err("Empty priv\n");
7b6ed49e
MM
389 return 0;
390 }
391
392 return cmd_auth_request(priv, req);
393}
394
395
396static int esp_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
397 struct cfg80211_assoc_request *req)
398{
bd131325
YM
399 struct esp_wifi_device *priv = NULL;
400
401 if (!wiphy || !dev || !req) {
6f8fee57 402 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
403 return -EINVAL;
404 }
405
406 priv = netdev_priv(dev);
7b6ed49e 407
e58fd496 408 esp_dbg("\n");
bd131325 409
7b6ed49e 410 if (!priv) {
6f8fee57 411 esp_err("Empty priv\n");
7b6ed49e
MM
412 return 0;
413 }
414
415 return cmd_assoc_request(priv, req);
416}
417
418static int esp_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev,
419 struct cfg80211_deauth_request *req)
420{
bd131325
YM
421 struct esp_wifi_device *priv = NULL;
422
423 if (!wiphy || !dev || !req) {
6f8fee57 424 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
425 return -EINVAL;
426 }
7b6ed49e 427
e58fd496 428 esp_dbg("\n");
bd131325 429 priv = netdev_priv(dev);
7b6ed49e
MM
430
431 if (!priv) {
6f8fee57 432 esp_err("Empty priv\n");
7b6ed49e
MM
433 return 0;
434 }
435
436 return cmd_disconnect_request(priv, req->reason_code);
437}
438
439static int esp_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
440 struct cfg80211_disassoc_request *req)
441{
bd131325
YM
442 struct esp_wifi_device *priv = NULL;
443
444 if (!wiphy || !dev || !req) {
6f8fee57 445 esp_info("%u invalid input\n", __LINE__);
bd131325
YM
446 return -EINVAL;
447 }
7b6ed49e 448
e58fd496 449 esp_dbg("\n");
bd131325 450 priv = netdev_priv(dev);
7b6ed49e
MM
451
452 if (!priv) {
6f8fee57 453 esp_err("Empty priv\n");
7b6ed49e
MM
454 return 0;
455 }
bd131325 456
7b6ed49e
MM
457 return cmd_disconnect_request(priv, req->reason_code);
458}
459
3fef9acf 460static int esp_cfg80211_suspend(struct wiphy *wiphy,
5a47b073 461 struct cfg80211_wowlan *wowlan)
3fef9acf 462{
e58fd496 463 /*esp_dbg("\n");*/
3fef9acf
MM
464 return 0;
465}
466
467static int esp_cfg80211_resume(struct wiphy *wiphy)
468{
e58fd496 469 /*esp_dbg("\n");*/
3fef9acf
MM
470 return 0;
471}
472
473static void esp_cfg80211_set_wakeup(struct wiphy *wiphy,
5a47b073 474 bool enabled)
3fef9acf 475{
e58fd496 476 /*esp_dbg("\n");*/
3fef9acf
MM
477}
478
98f8ece9
KG
479/* TODO get MAX_TX_POWER_MBM from Firmware for future chips */
480#define MAX_TX_POWER_MBM (20 * 100)
9726a3d0
KG
481static bool is_txpwr_valid(int mbm)
482{
98f8ece9 483 if (mbm > MAX_TX_POWER_MBM)
9726a3d0
KG
484 return false;
485
486 return true;
487}
488
489static int mbm_to_esp_pwr(int mbm)
490{
491 return ((mbm * 4) / 100);
492}
493
494static int esp_pwr_to_dbm(int power)
495{
496 return ((power / 4));
497}
498
499static int esp_cfg80211_set_tx_power(struct wiphy *wiphy,
500 struct wireless_dev *wdev,
501 enum nl80211_tx_power_setting type, int mbm)
502{
503 struct esp_adapter *adapter = esp_get_adapter();
504 struct esp_wifi_device *priv = NULL;
505
506 if (!wiphy || !adapter) {
507 esp_info("%u invalid input %p %p \n", __LINE__, wiphy, wdev);
508 return -EINVAL;
509 }
510
511 esp_dbg("\n");
512
513 priv = adapter->priv[0];
514 if (!priv) {
515 esp_err("Empty priv\n");
516 return 0;
517 }
518
519 switch (type) {
520 case NL80211_TX_POWER_AUTOMATIC:
521 priv->tx_pwr_type = NL80211_TX_POWER_AUTOMATIC;
98f8ece9 522 priv->tx_pwr = mbm_to_esp_pwr(MAX_TX_POWER_MBM);
9726a3d0
KG
523 break;
524 case NL80211_TX_POWER_LIMITED:
525 if (!is_txpwr_valid(mbm)) {
526 esp_warn("mbm:%d not support\n", mbm);
527 return -EOPNOTSUPP;
528 }
529 priv->tx_pwr_type = NL80211_TX_POWER_LIMITED;
530 priv->tx_pwr = mbm_to_esp_pwr(mbm);
531 break;
532 case NL80211_TX_POWER_FIXED:
533 return -EOPNOTSUPP;
534 break;
535 default:
536 esp_warn("unknown type:%d\n", type);
537 }
538
539 return cmd_set_tx_power(priv, priv->tx_pwr);
540}
541
542static int esp_cfg80211_get_tx_power(struct wiphy *wiphy,
543 struct wireless_dev *wdev,
544 int *dbm)
545{
546 struct esp_wifi_device *priv = NULL;
547
548 if (!wiphy || !wdev || !dbm || !wdev->netdev) {
549 esp_info("%u invalid input\n", __LINE__);
550 return -EINVAL;
551 }
552
553 esp_dbg("\n");
554 priv = netdev_priv(wdev->netdev);
555
556 if (!priv) {
557 esp_err("Empty priv\n");
558 return -EINVAL;
559 }
560
561 *dbm = esp_pwr_to_dbm(priv->tx_pwr);
562
563 return 0;
564}
565
774e9b2e
MM
566static struct cfg80211_ops esp_cfg80211_ops = {
567#if 0
568 .add_virtual_intf = esp_cfg80211_add_iface,
569 .del_virtual_intf = esp_cfg80211_del_iface,
570 .change_virtual_intf = esp_cfg80211_change_iface,
571#endif
572 .scan = esp_cfg80211_scan,
bd131325 573 /*.connect = esp_cfg80211_connect,*/
774e9b2e
MM
574 .disconnect = esp_cfg80211_disconnect,
575 .add_key = esp_cfg80211_add_key,
576 .del_key = esp_cfg80211_del_key,
577 .set_default_key = esp_cfg80211_set_default_key,
578 .mgmt_tx = esp_cfg80211_mgmt_tx,
7b6ed49e
MM
579 .auth = esp_cfg80211_authenticate,
580 .deauth = esp_cfg80211_deauth,
581 .disassoc = esp_cfg80211_disassoc,
582 .assoc = esp_cfg80211_associate,
3fef9acf
MM
583 .suspend = esp_cfg80211_suspend,
584 .resume = esp_cfg80211_resume,
585 .set_wakeup = esp_cfg80211_set_wakeup,
9726a3d0
KG
586 .set_tx_power = esp_cfg80211_set_tx_power,
587 .get_tx_power = esp_cfg80211_get_tx_power,
774e9b2e
MM
588};
589
f7ac1df4
KG
590static void esp_reg_notifier(struct wiphy *wiphy,
591 struct regulatory_request *request)
592{
593 struct esp_wifi_device *priv = NULL;
594 struct esp_device *esp_dev = NULL;
012db46c 595 struct esp_adapter *adapter = esp_get_adapter();
f7ac1df4
KG
596
597 if (!wiphy || !request) {
598 esp_info("%u invalid input\n", __LINE__);
599 return;
600 }
601
366297f9
KG
602 if (!test_bit(ESP_INIT_DONE, &adapter->state_flags)) {
603 esp_info("Driver init is ongoing\n");
604 return;
605 }
606 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &adapter->state_flags)) {
607 esp_info("Driver cleanup is ongoing\n");
608 return;
609 }
610
f7ac1df4
KG
611 esp_dev = wiphy_priv(wiphy);
612
613 if (!esp_dev || !esp_dev->adapter) {
614 esp_info("%u esp_dev not initialized yet \n", __LINE__);
615 return;
616 }
012db46c 617
f7ac1df4
KG
618 priv = esp_dev->adapter->priv[0];
619
620 if (!priv) {
621 esp_info("%u esp_wifi_device not initialized yet \n", __LINE__);
622 return;
623 }
624 esp_info("cfg80211 regulatory domain callback for %c%c, current=%c%c\n",
625 request->alpha2[0], request->alpha2[1], priv->country_code[0], priv->country_code[1]);
626
627 switch (request->initiator) {
628 case NL80211_REGDOM_SET_BY_DRIVER:
629 case NL80211_REGDOM_SET_BY_CORE:
630 case NL80211_REGDOM_SET_BY_USER:
631 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
632 break;
633 default:
634 esp_dbg("unknown regdom initiator: %d\n", request->initiator);
635 return;
636 }
637
638 /* Don't send same regdom info to firmware */
639 if (strncmp(request->alpha2, priv->country_code, strlen(request->alpha2))) {
640 strlcpy(priv->country_code, request->alpha2, MAX_COUNTRY_LEN);
641 cmd_set_reg_domain(priv);
642 }
643}
644
774e9b2e
MM
645int esp_cfg80211_register(struct esp_adapter *adapter)
646{
647 struct wiphy *wiphy;
648 struct esp_device *esp_dev;
649 int ret = 0;
650
651 wiphy = wiphy_new(&esp_cfg80211_ops, sizeof(struct esp_device));
652
653 if (!wiphy) {
6f8fee57 654 esp_err("Failed to create wiphy\n");
774e9b2e
MM
655 return -EFAULT;
656 }
657
658 adapter->wiphy = wiphy;
659
660 esp_dev = wiphy_priv(wiphy);
661 esp_dev->wiphy = wiphy;
662 esp_dev->adapter = adapter;
663
664 esp_dev->dev = adapter->dev;
665
666 set_wiphy_dev(wiphy, esp_dev->dev);
667
668 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
669 wiphy->bands[NL80211_BAND_2GHZ] = &esp_wifi_bands;
670
671 /* Initialize cipher suits */
672 wiphy->cipher_suites = esp_cipher_suites;
673 wiphy->n_cipher_suites = ARRAY_SIZE(esp_cipher_suites);
674
675 /* TODO: check and finalize the numbers */
676 wiphy->max_scan_ssids = 10;
677 /* wiphy->max_match_sets = 10;*/
678 wiphy->max_scan_ie_len = 1000;
679 wiphy->max_sched_scan_ssids = 10;
680 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
cb55e27a 681#ifdef CONFIG_PM
3fef9acf 682 wiphy->wowlan = &esp_wowlan_support;
cb55e27a 683#endif
774e9b2e 684
7b6ed49e
MM
685 /* Advertise SAE support */
686 wiphy->features |= NL80211_FEATURE_SAE;
687
f7ac1df4
KG
688 wiphy->reg_notifier = esp_reg_notifier;
689
774e9b2e
MM
690 ret = wiphy_register(wiphy);
691
692 return ret;
693}
694
225e14eb
YM
695int esp_mark_disconnect(struct esp_wifi_device *priv, uint16_t reason,
696 uint8_t locally_disconnect)
697{
698 if (priv && priv->ndev)
aad2ae2e
YM
699 if (priv->ndev->reg_state == NETREG_REGISTERED)
700 CFG80211_DISCONNECTED(priv->ndev, reason, NULL, 0, locally_disconnect,
701 GFP_KERNEL);
225e14eb
YM
702 return 0;
703}
704
705int esp_mark_scan_done_and_disconnect(struct esp_wifi_device *priv,
706 uint8_t locally_disconnect)
707{
225e14eb
YM
708
709 if (!priv)
710 return -EINVAL;
711
0af9c02e 712 ESP_MARK_SCAN_DONE(priv, true);
225e14eb
YM
713
714 ESP_CANCEL_SCHED_SCAN();
715
aad2ae2e 716 esp_mark_disconnect(priv, 0, locally_disconnect);
225e14eb 717
225e14eb
YM
718 return 0;
719}
This page took 0.15069 seconds and 4 git commands to generate.