blob: edfc6805e0128e6c6001756342babff0b63e6593 [file] [log] [blame]
Larry Finger2865d422010-08-20 10:15:30 -05001/******************************************************************************
2 * rtl871x_ioctl_linux.c
3 *
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
22 *
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
26 *
27 ******************************************************************************/
28
29#define _RTL871X_IOCTL_LINUX_C_
Larry Fingere3dc8962011-01-14 14:54:13 -060030#define _RTL871X_MP_IOCTL_C_
Larry Finger2865d422010-08-20 10:15:30 -050031
32#include "osdep_service.h"
33#include "drv_types.h"
34#include "wlan_bssdef.h"
35#include "rtl871x_debug.h"
36#include "wifi.h"
37#include "rtl871x_mlme.h"
38#include "rtl871x_ioctl.h"
39#include "rtl871x_ioctl_set.h"
40#include "rtl871x_mp_ioctl.h"
41#include "mlme_osdep.h"
Ali Bahar359140a2011-09-04 03:14:11 +080042#include <linux/wireless.h>
43#include <linux/module.h>
44#include <linux/kernel.h>
Ali Bahar359140a2011-09-04 03:14:11 +080045#include <linux/io.h>
46#include <linux/semaphore.h>
47#include <net/iw_handler.h>
48#include <linux/if_arp.h>
Aya Mahfouz22905b82015-03-04 09:00:02 +020049#include <linux/etherdevice.h>
50
Larry Finger2865d422010-08-20 10:15:30 -050051
Ali Baharc6dc0012011-09-04 03:14:20 +080052#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
Larry Finger2865d422010-08-20 10:15:30 -050053
54#define SCAN_ITEM_SIZE 768
55#define MAX_CUSTOM_LEN 64
56#define RATE_COUNT 4
57
58
59static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
60 6000000, 9000000, 12000000, 18000000,
61 24000000, 36000000, 48000000, 54000000};
62
63static const long ieee80211_wlan_frequencies[] = {
64 2412, 2417, 2422, 2427,
65 2432, 2437, 2442, 2447,
66 2452, 2457, 2462, 2467,
67 2472, 2484
68};
69
70static const char * const iw_operation_mode[] = {
71 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
72 "Monitor"
73};
74
Larry Finger2865d422010-08-20 10:15:30 -050075void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
76{
77 union iwreq_data wrqu;
78 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
79
80 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
81 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
82 ETH_ALEN);
83 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
84}
85
86void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
87{
88 union iwreq_data wrqu;
89
90 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
Aya Mahfouz22905b82015-03-04 09:00:02 +020091 eth_zero_addr(wrqu.ap_addr.sa_data);
Larry Finger2865d422010-08-20 10:15:30 -050092 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
93}
94
95static inline void handle_pairwise_key(struct sta_info *psta,
96 struct ieee_param *param,
97 struct _adapter *padapter)
98{
99 /* pairwise key */
100 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
101 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
102 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
103 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
104 key[16]), 8);
105 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
106 key[24]), 8);
107 padapter->securitypriv. busetkipkey = false;
Vaishali Thakkar875b7de2015-02-25 09:35:32 +0530108 mod_timer(&padapter->securitypriv.tkip_timer,
109 jiffies + msecs_to_jiffies(50));
Larry Finger2865d422010-08-20 10:15:30 -0500110 }
111 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
112}
113
114static inline void handle_group_key(struct ieee_param *param,
115 struct _adapter *padapter)
116{
Alison Schofield29b1b612015-10-06 14:40:58 -0700117 if (param->u.crypt.idx > 0 &&
Larry Finger2865d422010-08-20 10:15:30 -0500118 param->u.crypt.idx < 3) {
119 /* group key idx is 1 or 2 */
120 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100121 idx - 1].skey, param->u.crypt.key,
122 (param->u.crypt.key_len > 16 ? 16 :
123 param->u.crypt.key_len));
Larry Finger2865d422010-08-20 10:15:30 -0500124 memcpy(padapter->securitypriv.XGrptxmickey[param->
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100125 u.crypt.idx - 1].skey, &(param->u.crypt.key[16]), 8);
Larry Finger2865d422010-08-20 10:15:30 -0500126 memcpy(padapter->securitypriv. XGrprxmickey[param->
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100127 u.crypt.idx - 1].skey, &(param->u.crypt.key[24]), 8);
Larry Finger2865d422010-08-20 10:15:30 -0500128 padapter->securitypriv.binstallGrpkey = true;
129 r8712_set_key(padapter, &padapter->securitypriv,
130 param->u.crypt.idx);
131 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
132 if (padapter->registrypriv.power_mgnt != padapter->
133 pwrctrlpriv.pwr_mode)
Vaishali Thakkar875b7de2015-02-25 09:35:32 +0530134 mod_timer(&padapter->mlmepriv.dhcp_timer,
135 jiffies + msecs_to_jiffies(60000));
Larry Finger2865d422010-08-20 10:15:30 -0500136 }
137 }
138}
139
140static inline char *translate_scan(struct _adapter *padapter,
141 struct iw_request_info *info,
142 struct wlan_network *pnetwork,
143 char *start, char *stop)
144{
145 struct iw_event iwe;
146 struct ieee80211_ht_cap *pht_capie;
147 char *current_val;
Larry Finger2865d422010-08-20 10:15:30 -0500148 s8 *p;
149 u32 i = 0, ht_ielen = 0;
150 u16 cap, ht_cap = false, mcs_rate;
Sudip Mukherjeee29d3eb2014-10-27 17:42:25 +0530151 u8 rssi;
Larry Finger2865d422010-08-20 10:15:30 -0500152
153 if ((pnetwork->network.Configuration.DSConfig < 1) ||
154 (pnetwork->network.Configuration.DSConfig > 14)) {
155 if (pnetwork->network.Configuration.DSConfig < 1)
156 pnetwork->network.Configuration.DSConfig = 1;
157 else
158 pnetwork->network.Configuration.DSConfig = 14;
159 }
160 /* AP MAC address */
161 iwe.cmd = SIOCGIWAP;
162 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
Haneen Mohammede0e982b2015-03-16 18:41:31 +0300163 ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
Larry Finger2865d422010-08-20 10:15:30 -0500164 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
165 /* Add the ESSID */
166 iwe.cmd = SIOCGIWESSID;
167 iwe.u.data.flags = 1;
Przemo Firszt0024a1e2012-12-10 23:21:22 +0000168 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
Larry Finger2865d422010-08-20 10:15:30 -0500169 start = iwe_stream_add_point(info, start, stop, &iwe,
170 pnetwork->network.Ssid.Ssid);
171 /* parsing HT_CAP_IE */
172 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
173 &ht_ielen, pnetwork->network.IELength - 12);
174 if (p && ht_ielen > 0) {
175 ht_cap = true;
176 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
Max Perepelitsyn0636b462015-01-02 14:08:08 +0600177 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
Larry Finger2865d422010-08-20 10:15:30 -0500178 }
179 /* Add the protocol name */
180 iwe.cmd = SIOCGIWNAME;
Joshua Clayton7fb539e2015-08-05 17:17:21 -0700181 if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100182 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500183 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
184 else
185 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
Joshua Clayton7fb539e2015-08-05 17:17:21 -0700186 } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100187 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500188 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
189 else
190 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
191 } else {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100192 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500193 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
194 else
195 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
196 }
197 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
198 /* Add mode */
199 iwe.cmd = SIOCGIWMODE;
200 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
201 2);
202 cap = le16_to_cpu(cap);
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100203 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
Larry Finger2865d422010-08-20 10:15:30 -0500204 if (cap & WLAN_CAPABILITY_BSS)
205 iwe.u.mode = (u32)IW_MODE_MASTER;
206 else
207 iwe.u.mode = (u32)IW_MODE_ADHOC;
208 start = iwe_stream_add_event(info, start, stop, &iwe,
209 IW_EV_UINT_LEN);
210 }
211 /* Add frequency/channel */
212 iwe.cmd = SIOCGIWFREQ;
213 {
Justin P. Mattockbe10ac22012-05-07 07:38:22 -0700214 /* check legal index */
Larry Finger2865d422010-08-20 10:15:30 -0500215 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530216
Larry Finger2865d422010-08-20 10:15:30 -0500217 if (dsconfig >= 1 && dsconfig <= sizeof(
218 ieee80211_wlan_frequencies) / sizeof(long))
219 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
220 pnetwork->network.Configuration.
221 DSConfig - 1] * 100000);
222 else
223 iwe.u.freq.m = 0;
224 }
225 iwe.u.freq.e = (s16)1;
226 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
227 start = iwe_stream_add_event(info, start, stop, &iwe,
228 IW_EV_FREQ_LEN);
229 /* Add encryption capability */
230 iwe.cmd = SIOCGIWENCODE;
231 if (cap & WLAN_CAPABILITY_PRIVACY)
232 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
233 IW_ENCODE_NOKEY);
234 else
235 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
236 iwe.u.data.length = (u16)0;
237 start = iwe_stream_add_point(info, start, stop, &iwe,
238 pnetwork->network.Ssid.Ssid);
239 /*Add basic and extended rates */
240 current_val = start + iwe_stream_lcp_len(info);
241 iwe.cmd = SIOCGIWRATE;
242 iwe.u.bitrate.fixed = 0;
243 iwe.u.bitrate.disabled = 0;
244 iwe.u.bitrate.value = 0;
245 i = 0;
Joshua Clayton7fb539e2015-08-05 17:17:21 -0700246 while (pnetwork->network.rates[i] != 0) {
Larry Finger2865d422010-08-20 10:15:30 -0500247 /* Bit rate given in 500 kb/s units */
Joshua Clayton7fb539e2015-08-05 17:17:21 -0700248 iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
Larry Finger2865d422010-08-20 10:15:30 -0500249 0x7F) * 500000;
250 current_val = iwe_stream_add_value(info, start, current_val,
251 stop, &iwe, IW_EV_PARAM_LEN);
252 }
253 /* Check if we added any event */
254 if ((current_val - start) > iwe_stream_lcp_len(info))
255 start = current_val;
256 /* parsing WPA/WPA2 IE */
257 {
Ali Baharc13b6f22011-09-04 03:14:15 +0800258 u8 buf[MAX_WPA_IE_LEN];
259 u8 wpa_ie[255], rsn_ie[255];
Larry Finger2865d422010-08-20 10:15:30 -0500260 u16 wpa_len = 0, rsn_len = 0;
Dan Carpenterd9364352011-02-09 01:45:13 +0300261 int n;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530262
Sudip Mukherjeee29d3eb2014-10-27 17:42:25 +0530263 r8712_get_sec_ie(pnetwork->network.IEs,
264 pnetwork->network.IELength, rsn_ie, &rsn_len,
265 wpa_ie, &wpa_len);
Larry Finger2865d422010-08-20 10:15:30 -0500266 if (wpa_len > 0) {
Larry Finger2865d422010-08-20 10:15:30 -0500267 memset(buf, 0, MAX_WPA_IE_LEN);
Dan Carpenterd9364352011-02-09 01:45:13 +0300268 n = sprintf(buf, "wpa_ie=");
269 for (i = 0; i < wpa_len; i++) {
Javier M. Mellid2657c302011-04-02 03:02:12 +0200270 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
271 "%02x", wpa_ie[i]);
Dan Carpenterd9364352011-02-09 01:45:13 +0300272 if (n >= MAX_WPA_IE_LEN)
273 break;
274 }
Larry Finger2865d422010-08-20 10:15:30 -0500275 memset(&iwe, 0, sizeof(iwe));
276 iwe.cmd = IWEVCUSTOM;
277 iwe.u.data.length = (u16)strlen(buf);
278 start = iwe_stream_add_point(info, start, stop,
279 &iwe, buf);
280 memset(&iwe, 0, sizeof(iwe));
281 iwe.cmd = IWEVGENIE;
282 iwe.u.data.length = (u16)wpa_len;
283 start = iwe_stream_add_point(info, start, stop,
284 &iwe, wpa_ie);
285 }
286 if (rsn_len > 0) {
Larry Finger2865d422010-08-20 10:15:30 -0500287 memset(buf, 0, MAX_WPA_IE_LEN);
Dan Carpenterd9364352011-02-09 01:45:13 +0300288 n = sprintf(buf, "rsn_ie=");
289 for (i = 0; i < rsn_len; i++) {
Javier M. Mellid2657c302011-04-02 03:02:12 +0200290 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
291 "%02x", rsn_ie[i]);
Dan Carpenterd9364352011-02-09 01:45:13 +0300292 if (n >= MAX_WPA_IE_LEN)
293 break;
294 }
Larry Finger2865d422010-08-20 10:15:30 -0500295 memset(&iwe, 0, sizeof(iwe));
296 iwe.cmd = IWEVCUSTOM;
297 iwe.u.data.length = strlen(buf);
298 start = iwe_stream_add_point(info, start, stop,
299 &iwe, buf);
300 memset(&iwe, 0, sizeof(iwe));
301 iwe.cmd = IWEVGENIE;
302 iwe.u.data.length = rsn_len;
303 start = iwe_stream_add_point(info, start, stop, &iwe,
304 rsn_ie);
305 }
306 }
307
308 { /* parsing WPS IE */
Ali Baharc13b6f22011-09-04 03:14:15 +0800309 u8 wps_ie[512];
Larry Finger2865d422010-08-20 10:15:30 -0500310 uint wps_ielen;
311
312 if (r8712_get_wps_ie(pnetwork->network.IEs,
313 pnetwork->network.IELength,
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100314 wps_ie, &wps_ielen)) {
Larry Finger2865d422010-08-20 10:15:30 -0500315 if (wps_ielen > 2) {
316 iwe.cmd = IWEVGENIE;
317 iwe.u.data.length = (u16)wps_ielen;
318 start = iwe_stream_add_point(info, start, stop,
319 &iwe, wps_ie);
320 }
321 }
322 }
323 /* Add quality statistics */
324 iwe.cmd = IWEVQUAL;
325 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
326 /* we only update signal_level (signal strength) that is rssi. */
327 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
328 IW_QUAL_NOISE_INVALID);
329 iwe.u.qual.level = rssi; /* signal strength */
330 iwe.u.qual.qual = 0; /* signal quality */
331 iwe.u.qual.noise = 0; /* noise level */
332 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
333 /* how to translate rssi to ?% */
Larry Finger2865d422010-08-20 10:15:30 -0500334 return start;
335}
336
337static int wpa_set_auth_algs(struct net_device *dev, u32 value)
338{
Julia Lawall8f47c282015-03-29 14:54:12 +0200339 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500340 int ret = 0;
341
342 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
343 padapter->securitypriv.ndisencryptstatus =
344 Ndis802_11Encryption1Enabled;
345 padapter->securitypriv.ndisauthtype =
346 Ndis802_11AuthModeAutoSwitch;
347 padapter->securitypriv.AuthAlgrthm = 3;
348 } else if (value & AUTH_ALG_SHARED_KEY) {
349 padapter->securitypriv.ndisencryptstatus =
350 Ndis802_11Encryption1Enabled;
351 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
352 padapter->securitypriv.AuthAlgrthm = 1;
353 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
354 if (padapter->securitypriv.ndisauthtype <
355 Ndis802_11AuthModeWPAPSK) {
356 padapter->securitypriv.ndisauthtype =
357 Ndis802_11AuthModeOpen;
358 padapter->securitypriv.AuthAlgrthm = 0;
359 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100360 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500361 ret = -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100362 }
Larry Finger2865d422010-08-20 10:15:30 -0500363 return ret;
364}
365
366static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
367 u32 param_len)
368{
369 int ret = 0;
370 u32 wep_key_idx, wep_key_len = 0;
371 struct NDIS_802_11_WEP *pwep = NULL;
Julia Lawall8f47c282015-03-29 14:54:12 +0200372 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500373 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
374 struct security_priv *psecuritypriv = &padapter->securitypriv;
375
376 param->u.crypt.err = 0;
377 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
378 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
379 param->u.crypt.key_len)
380 return -EINVAL;
Wei Yongjun779477f2012-08-26 09:22:33 +0800381 if (is_broadcast_ether_addr(param->sta_addr)) {
Larry Finger2865d422010-08-20 10:15:30 -0500382 if (param->u.crypt.idx >= WEP_KEYS) {
383 /* for large key indices, set the default (0) */
384 param->u.crypt.idx = 0;
385 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100386 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500387 return -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100388 }
Larry Finger2865d422010-08-20 10:15:30 -0500389 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
Przemo Firszt87a573a2012-12-10 23:21:21 +0000390 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -0500391 padapter->securitypriv.ndisencryptstatus =
392 Ndis802_11Encryption1Enabled;
393 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
394 padapter->securitypriv.XGrpPrivacy = _WEP40_;
395 wep_key_idx = param->u.crypt.idx;
396 wep_key_len = param->u.crypt.key_len;
397 if (wep_key_idx >= WEP_KEYS)
398 wep_key_idx = 0;
399 if (wep_key_len > 0) {
400 wep_key_len = wep_key_len <= 5 ? 5 : 13;
Vitaly Osipov91d435f2014-05-24 18:19:27 +1000401 pwep = kmalloc((u32)(wep_key_len +
Tapasweni Pathak57b66862014-09-21 06:42:21 +0530402 FIELD_OFFSET(struct NDIS_802_11_WEP,
403 KeyMaterial)), GFP_ATOMIC);
Larry Finger2865d422010-08-20 10:15:30 -0500404 if (pwep == NULL)
405 return -ENOMEM;
406 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
407 pwep->KeyLength = wep_key_len;
408 pwep->Length = wep_key_len +
409 FIELD_OFFSET(struct NDIS_802_11_WEP,
410 KeyMaterial);
411 if (wep_key_len == 13) {
412 padapter->securitypriv.PrivacyAlgrthm =
413 _WEP104_;
414 padapter->securitypriv.XGrpPrivacy =
415 _WEP104_;
416 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100417 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500418 return -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100419 }
Larry Finger2865d422010-08-20 10:15:30 -0500420 pwep->KeyIndex = wep_key_idx;
421 pwep->KeyIndex |= 0x80000000;
422 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
423 if (param->u.crypt.set_tx) {
424 if (r8712_set_802_11_add_wep(padapter, pwep) ==
425 (u8)_FAIL)
426 ret = -EOPNOTSUPP;
427 } else {
428 /* don't update "psecuritypriv->PrivacyAlgrthm" and
429 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
430 * r8712_set_key to fw/cam
431 */
432 if (wep_key_idx >= WEP_KEYS) {
433 ret = -EOPNOTSUPP;
434 goto exit;
435 }
436 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
437 skey[0]), pwep->KeyMaterial,
438 pwep->KeyLength);
439 psecuritypriv->DefKeylen[wep_key_idx] =
440 pwep->KeyLength;
441 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
442 }
443 goto exit;
444 }
445 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
446 struct sta_info *psta, *pbcmc_sta;
447 struct sta_priv *pstapriv = &padapter->stapriv;
448
449 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100450 WIFI_MP_STATE)) { /* sta mode */
Larry Finger2865d422010-08-20 10:15:30 -0500451 psta = r8712_get_stainfo(pstapriv,
452 get_bssid(pmlmepriv));
453 if (psta) {
454 psta->ieee8021x_blocked = false;
455 if ((padapter->securitypriv.ndisencryptstatus ==
456 Ndis802_11Encryption2Enabled) ||
457 (padapter->securitypriv.ndisencryptstatus ==
458 Ndis802_11Encryption3Enabled))
459 psta->XPrivacy = padapter->
460 securitypriv.PrivacyAlgrthm;
461 if (param->u.crypt.set_tx == 1)
462 handle_pairwise_key(psta, param,
463 padapter);
464 else /* group key */
465 handle_group_key(param, padapter);
466 }
467 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
468 if (pbcmc_sta) {
469 pbcmc_sta->ieee8021x_blocked = false;
470 if ((padapter->securitypriv.ndisencryptstatus ==
471 Ndis802_11Encryption2Enabled) ||
472 (padapter->securitypriv.ndisencryptstatus ==
473 Ndis802_11Encryption3Enabled))
474 pbcmc_sta->XPrivacy =
475 padapter->securitypriv.
476 PrivacyAlgrthm;
477 }
478 }
479 }
480exit:
Tapasweni Pathak646da832014-10-08 20:41:26 +0530481 kfree(pwep);
Larry Finger2865d422010-08-20 10:15:30 -0500482 return ret;
483}
484
485static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
486 unsigned short ielen)
487{
Sudip Mukherjeee29d3eb2014-10-27 17:42:25 +0530488 u8 *buf = NULL;
Larry Finger2865d422010-08-20 10:15:30 -0500489 int group_cipher = 0, pairwise_cipher = 0;
490 int ret = 0;
491
492 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
493 return -EINVAL;
494 if (ielen) {
Vitaly Osipov91d435f2014-05-24 18:19:27 +1000495 buf = kmemdup(pie, ielen, GFP_ATOMIC);
Larry Finger2865d422010-08-20 10:15:30 -0500496 if (buf == NULL)
497 return -ENOMEM;
Larry Finger2865d422010-08-20 10:15:30 -0500498 if (ielen < RSN_HEADER_LEN) {
Ali Bahar2192e602011-09-04 03:14:24 +0800499 ret = -EINVAL;
Larry Finger2865d422010-08-20 10:15:30 -0500500 goto exit;
501 }
502 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
503 &pairwise_cipher) == _SUCCESS) {
504 padapter->securitypriv.AuthAlgrthm = 2;
505 padapter->securitypriv.ndisauthtype =
506 Ndis802_11AuthModeWPAPSK;
507 }
508 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
509 &pairwise_cipher) == _SUCCESS) {
510 padapter->securitypriv.AuthAlgrthm = 2;
511 padapter->securitypriv.ndisauthtype =
512 Ndis802_11AuthModeWPA2PSK;
513 }
514 switch (group_cipher) {
515 case WPA_CIPHER_NONE:
516 padapter->securitypriv.XGrpPrivacy =
517 _NO_PRIVACY_;
518 padapter->securitypriv.ndisencryptstatus =
519 Ndis802_11EncryptionDisabled;
520 break;
521 case WPA_CIPHER_WEP40:
522 padapter->securitypriv.XGrpPrivacy = _WEP40_;
523 padapter->securitypriv.ndisencryptstatus =
524 Ndis802_11Encryption1Enabled;
525 break;
526 case WPA_CIPHER_TKIP:
527 padapter->securitypriv.XGrpPrivacy = _TKIP_;
528 padapter->securitypriv.ndisencryptstatus =
529 Ndis802_11Encryption2Enabled;
530 break;
531 case WPA_CIPHER_CCMP:
532 padapter->securitypriv.XGrpPrivacy = _AES_;
533 padapter->securitypriv.ndisencryptstatus =
534 Ndis802_11Encryption3Enabled;
535 break;
536 case WPA_CIPHER_WEP104:
537 padapter->securitypriv.XGrpPrivacy = _WEP104_;
538 padapter->securitypriv.ndisencryptstatus =
539 Ndis802_11Encryption1Enabled;
540 break;
541 }
542 switch (pairwise_cipher) {
543 case WPA_CIPHER_NONE:
544 padapter->securitypriv.PrivacyAlgrthm =
545 _NO_PRIVACY_;
546 padapter->securitypriv.ndisencryptstatus =
547 Ndis802_11EncryptionDisabled;
548 break;
549 case WPA_CIPHER_WEP40:
550 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
551 padapter->securitypriv.ndisencryptstatus =
552 Ndis802_11Encryption1Enabled;
553 break;
554 case WPA_CIPHER_TKIP:
555 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
556 padapter->securitypriv.ndisencryptstatus =
557 Ndis802_11Encryption2Enabled;
558 break;
559 case WPA_CIPHER_CCMP:
560 padapter->securitypriv.PrivacyAlgrthm = _AES_;
561 padapter->securitypriv.ndisencryptstatus =
562 Ndis802_11Encryption3Enabled;
563 break;
564 case WPA_CIPHER_WEP104:
565 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
566 padapter->securitypriv.ndisencryptstatus =
567 Ndis802_11Encryption1Enabled;
568 break;
569 }
570 padapter->securitypriv.wps_phase = false;
571 {/* set wps_ie */
572 u16 cnt = 0;
573 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
574
575 while (cnt < ielen) {
576 eid = buf[cnt];
577
578 if ((eid == _VENDOR_SPECIFIC_IE_) &&
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100579 (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
Przemo Firszt87a573a2012-12-10 23:21:21 +0000580 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
Larry Finger2865d422010-08-20 10:15:30 -0500581 padapter->securitypriv.wps_ie_len =
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100582 ((buf[cnt + 1] + 2) <
Larry Finger2865d422010-08-20 10:15:30 -0500583 (MAX_WPA_IE_LEN << 2)) ?
584 (buf[cnt + 1] + 2) :
585 (MAX_WPA_IE_LEN << 2);
586 memcpy(padapter->securitypriv.wps_ie,
587 &buf[cnt],
588 padapter->securitypriv.wps_ie_len);
589 padapter->securitypriv.wps_phase =
590 true;
Przemo Firszt87a573a2012-12-10 23:21:21 +0000591 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100592 cnt += buf[cnt + 1] + 2;
Larry Finger2865d422010-08-20 10:15:30 -0500593 break;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100594 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500595 cnt += buf[cnt + 1] + 2;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100596 }
Larry Finger2865d422010-08-20 10:15:30 -0500597 }
598 }
599 }
600exit:
601 kfree(buf);
602 return ret;
603}
604
605static int r8711_wx_get_name(struct net_device *dev,
606 struct iw_request_info *info,
607 union iwreq_data *wrqu, char *extra)
608{
Julia Lawall8f47c282015-03-29 14:54:12 +0200609 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500610 u32 ht_ielen = 0;
611 char *p;
612 u8 ht_cap = false;
613 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
Joshua Clayton44367872015-08-05 17:17:18 -0700614 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Joshua Claytondb55b162015-08-05 17:17:20 -0700615 u8 *prates;
Larry Finger2865d422010-08-20 10:15:30 -0500616
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100617 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
Larry Finger2865d422010-08-20 10:15:30 -0500618 true) {
619 /* parsing HT_CAP_IE */
620 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
621 &ht_ielen, pcur_bss->IELength - 12);
622 if (p && ht_ielen > 0)
623 ht_cap = true;
Joshua Clayton7fb539e2015-08-05 17:17:21 -0700624 prates = pcur_bss->rates;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100625 if (r8712_is_cckratesonly_included(prates)) {
626 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500627 snprintf(wrqu->name, IFNAMSIZ,
628 "IEEE 802.11bn");
629 else
630 snprintf(wrqu->name, IFNAMSIZ,
631 "IEEE 802.11b");
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100632 } else if (r8712_is_cckrates_included(prates)) {
633 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500634 snprintf(wrqu->name, IFNAMSIZ,
635 "IEEE 802.11bgn");
636 else
637 snprintf(wrqu->name, IFNAMSIZ,
638 "IEEE 802.11bg");
639 } else {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100640 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500641 snprintf(wrqu->name, IFNAMSIZ,
642 "IEEE 802.11gn");
643 else
644 snprintf(wrqu->name, IFNAMSIZ,
645 "IEEE 802.11g");
646 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100647 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500648 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100649 }
Larry Finger2865d422010-08-20 10:15:30 -0500650 return 0;
651}
652
653static const long frequency_list[] = {
654 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
655 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
656 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
657 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
658 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
659 5825
660};
661
662static int r8711_wx_set_freq(struct net_device *dev,
663 struct iw_request_info *info,
664 union iwreq_data *wrqu, char *extra)
665{
Julia Lawall8f47c282015-03-29 14:54:12 +0200666 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500667 struct iw_freq *fwrq = &wrqu->freq;
668 int rc = 0;
669
670/* If setting by frequency, convert to a channel */
671 if ((fwrq->e == 1) &&
672 (fwrq->m >= (int) 2.412e8) &&
673 (fwrq->m <= (int) 2.487e8)) {
674 int f = fwrq->m / 100000;
675 int c = 0;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530676
Larry Finger2865d422010-08-20 10:15:30 -0500677 while ((c < 14) && (f != frequency_list[c]))
678 c++;
679 fwrq->e = 0;
680 fwrq->m = c + 1;
681 }
682 /* Setting by channel number */
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100683 if ((fwrq->m > 14) || (fwrq->e > 0)) {
Larry Finger2865d422010-08-20 10:15:30 -0500684 rc = -EOPNOTSUPP;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100685 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500686 int channel = fwrq->m;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530687
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100688 if ((channel < 1) || (channel > 14)) {
Larry Finger2865d422010-08-20 10:15:30 -0500689 rc = -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100690 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500691 /* Yes ! We can set it !!! */
692 padapter->registrypriv.channel = channel;
693 }
694 }
695 return rc;
696}
697
698static int r8711_wx_get_freq(struct net_device *dev,
699 struct iw_request_info *info,
700 union iwreq_data *wrqu, char *extra)
701{
Julia Lawall8f47c282015-03-29 14:54:12 +0200702 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500703 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -0700704 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -0500705
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100706 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
Larry Finger2865d422010-08-20 10:15:30 -0500707 wrqu->freq.m = ieee80211_wlan_frequencies[
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100708 pcur_bss->Configuration.DSConfig - 1] * 100000;
Larry Finger2865d422010-08-20 10:15:30 -0500709 wrqu->freq.e = 1;
710 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
Ali Bahar2192e602011-09-04 03:14:24 +0800711 } else {
712 return -ENOLINK;
713 }
Larry Finger2865d422010-08-20 10:15:30 -0500714 return 0;
715}
716
717static int r8711_wx_set_mode(struct net_device *dev,
718 struct iw_request_info *a,
719 union iwreq_data *wrqu, char *b)
720{
Julia Lawall8f47c282015-03-29 14:54:12 +0200721 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500722 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
723
724 switch (wrqu->mode) {
725 case IW_MODE_AUTO:
726 networkType = Ndis802_11AutoUnknown;
727 break;
728 case IW_MODE_ADHOC:
729 networkType = Ndis802_11IBSS;
730 break;
731 case IW_MODE_MASTER:
732 networkType = Ndis802_11APMode;
733 break;
734 case IW_MODE_INFRA:
735 networkType = Ndis802_11Infrastructure;
736 break;
737 default:
738 return -EINVAL;
739 }
740 if (Ndis802_11APMode == networkType)
741 r8712_setopmode_cmd(padapter, networkType);
742 else
743 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
Ali Bahar2192e602011-09-04 03:14:24 +0800744
745 r8712_set_802_11_infrastructure_mode(padapter, networkType);
Larry Finger2865d422010-08-20 10:15:30 -0500746 return 0;
747}
748
749static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
750 union iwreq_data *wrqu, char *b)
751{
Julia Lawall8f47c282015-03-29 14:54:12 +0200752 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500753 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
754
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100755 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
Larry Finger2865d422010-08-20 10:15:30 -0500756 wrqu->mode = IW_MODE_INFRA;
757 else if (check_fwstate(pmlmepriv,
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100758 WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
Larry Finger2865d422010-08-20 10:15:30 -0500759 wrqu->mode = IW_MODE_ADHOC;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100760 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
Larry Finger2865d422010-08-20 10:15:30 -0500761 wrqu->mode = IW_MODE_MASTER;
762 else
763 wrqu->mode = IW_MODE_AUTO;
764 return 0;
765}
766
767static int r871x_wx_set_pmkid(struct net_device *dev,
768 struct iw_request_info *a,
769 union iwreq_data *wrqu, char *extra)
770{
Julia Lawall8f47c282015-03-29 14:54:12 +0200771 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500772 struct security_priv *psecuritypriv = &padapter->securitypriv;
773 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
774 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
775 u8 strIssueBssid[ETH_ALEN] = {0x00};
776 u8 j, blInserted = false;
777 int intReturn = false;
778
779/*
Punit Varad32c16d2015-10-14 23:55:54 +0530780 * There are the BSSID information in the bssid.sa_data array.
781 * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
782 * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
783 * wpa_supplicant wants to add a PMKID/BSSID to driver.
784 * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
785 * remove a PMKID/BSSID from driver.
786 */
Larry Finger2865d422010-08-20 10:15:30 -0500787 if (pPMK == NULL)
788 return -EINVAL;
789 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
790 switch (pPMK->cmd) {
791 case IW_PMKSA_ADD:
792 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
793 return intReturn;
Dogukan Ergun07e9e612015-06-13 15:04:26 +0300794 intReturn = true;
Larry Finger2865d422010-08-20 10:15:30 -0500795 blInserted = false;
796 /* overwrite PMKID */
Thomas Cort77e73e82013-10-01 11:26:55 -0400797 for (j = 0; j < NUM_PMKID_CACHE; j++) {
Larry Finger2865d422010-08-20 10:15:30 -0500798 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
799 strIssueBssid, ETH_ALEN)) {
800 /* BSSID is matched, the same AP => rewrite
Punit Varad32c16d2015-10-14 23:55:54 +0530801 * with new PMKID.
802 */
Przemo Firszt87a573a2012-12-10 23:21:21 +0000803 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
804 __func__);
Larry Finger2865d422010-08-20 10:15:30 -0500805 memcpy(psecuritypriv->PMKIDList[j].PMKID,
806 pPMK->pmkid, IW_PMKID_LEN);
807 psecuritypriv->PMKIDList[j].bUsed = true;
808 psecuritypriv->PMKIDIndex = j + 1;
809 blInserted = true;
810 break;
811 }
812 }
813 if (!blInserted) {
814 /* Find a new entry */
Przemo Firszt87a573a2012-12-10 23:21:21 +0000815 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
816 __func__, psecuritypriv->PMKIDIndex);
Larry Finger2865d422010-08-20 10:15:30 -0500817 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
818 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
819 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
820 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
821 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
822 bUsed = true;
Thomas Cort77e73e82013-10-01 11:26:55 -0400823 psecuritypriv->PMKIDIndex++;
Larry Finger2865d422010-08-20 10:15:30 -0500824 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
825 psecuritypriv->PMKIDIndex = 0;
826 }
827 break;
828 case IW_PMKSA_REMOVE:
829 intReturn = true;
830 for (j = 0; j < NUM_PMKID_CACHE; j++) {
831 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
832 strIssueBssid, ETH_ALEN)) {
833 /* BSSID is matched, the same AP => Remove
Punit Varad32c16d2015-10-14 23:55:54 +0530834 * this PMKID information and reset it.
835 */
Aya Mahfouz22905b82015-03-04 09:00:02 +0200836 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
Larry Finger2865d422010-08-20 10:15:30 -0500837 psecuritypriv->PMKIDList[j].bUsed = false;
838 break;
839 }
840 }
841 break;
842 case IW_PMKSA_FLUSH:
843 memset(psecuritypriv->PMKIDList, 0,
844 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
845 psecuritypriv->PMKIDIndex = 0;
846 intReturn = true;
847 break;
848 default:
Przemo Firszt87a573a2012-12-10 23:21:21 +0000849 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -0500850 intReturn = false;
851 break;
852 }
853 return intReturn;
854}
855
856static int r8711_wx_get_sens(struct net_device *dev,
857 struct iw_request_info *info,
858 union iwreq_data *wrqu, char *extra)
859{
860 wrqu->sens.value = 0;
861 wrqu->sens.fixed = 0; /* no auto select */
862 wrqu->sens.disabled = 1;
863 return 0;
864}
865
866static int r8711_wx_get_range(struct net_device *dev,
867 struct iw_request_info *info,
868 union iwreq_data *wrqu, char *extra)
869{
870 struct iw_range *range = (struct iw_range *)extra;
871 u16 val;
872 int i;
873
874 wrqu->data.length = sizeof(*range);
875 memset(range, 0, sizeof(*range));
876 /* Let's try to keep this struct in the same order as in
877 * linux/include/wireless.h
878 */
879
880 /* TODO: See what values we can set, and remove the ones we can't
881 * set, or fill them with some default data.
882 */
883 /* ~5 Mb/s real (802.11b) */
884 range->throughput = 5 * 1000 * 1000;
885 /* TODO: 8711 sensitivity ? */
886 /* signal level threshold range */
887 /* percent values between 0 and 100. */
888 range->max_qual.qual = 100;
889 range->max_qual.level = 100;
890 range->max_qual.noise = 100;
891 range->max_qual.updated = 7; /* Updated all three */
892 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
Justin P. Mattockbe10ac22012-05-07 07:38:22 -0700893 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
Luis de Bethencourt681cd982015-10-11 14:16:57 +0100894 range->avg_qual.level = 0x100 - 78;
Larry Finger2865d422010-08-20 10:15:30 -0500895 range->avg_qual.noise = 0;
896 range->avg_qual.updated = 7; /* Updated all three */
897 range->num_bitrates = RATE_COUNT;
898 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
899 range->bitrate[i] = rtl8180_rates[i];
900 range->min_frag = MIN_FRAG_THRESHOLD;
901 range->max_frag = MAX_FRAG_THRESHOLD;
902 range->pm_capa = 0;
903 range->we_version_compiled = WIRELESS_EXT;
904 range->we_version_source = 16;
905 range->num_channels = 14;
906 for (i = 0, val = 0; i < 14; i++) {
907 /* Include only legal frequencies for some countries */
908 range->freq[val].i = i + 1;
909 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
910 range->freq[val].e = 1;
911 val++;
912 if (val == IW_MAX_FREQUENCIES)
913 break;
914 }
915 range->num_frequency = val;
916 range->enc_capa = IW_ENC_CAPA_WPA |
917 IW_ENC_CAPA_WPA2 |
918 IW_ENC_CAPA_CIPHER_TKIP |
919 IW_ENC_CAPA_CIPHER_CCMP;
920 return 0;
921}
922
Ali Baharc6dc0012011-09-04 03:14:20 +0800923static int r8711_wx_get_rate(struct net_device *dev,
924 struct iw_request_info *info,
925 union iwreq_data *wrqu, char *extra);
926
Larry Finger2865d422010-08-20 10:15:30 -0500927static int r871x_wx_set_priv(struct net_device *dev,
928 struct iw_request_info *info,
929 union iwreq_data *awrq,
930 char *extra)
931{
932 int ret = 0, len = 0;
933 char *ext;
Ali Baharc6dc0012011-09-04 03:14:20 +0800934 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500935 struct iw_point *dwrq = (struct iw_point *)awrq;
936
937 len = dwrq->length;
Vitaly Osipov91d435f2014-05-24 18:19:27 +1000938 ext = memdup_user(dwrq->pointer, len);
939 if (IS_ERR(ext))
940 return PTR_ERR(ext);
Ali Baharc6dc0012011-09-04 03:14:20 +0800941
Alison Schofield29b1b612015-10-06 14:40:58 -0700942 if (!strcasecmp(ext, "RSSI")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800943 /*Return received signal strength indicator in -db for */
944 /* current AP */
945 /*<ssid> Rssi xx */
946 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
947 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
948 /*static u8 xxxx; */
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100949 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800950 sprintf(ext, "%s rssi %d",
951 pcur_network->network.Ssid.Ssid,
952 /*(xxxx=xxxx+10) */
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100953 ((padapter->recvpriv.fw_rssi) >> 1) - 95
Ali Baharc6dc0012011-09-04 03:14:20 +0800954 /*pcur_network->network.Rssi */
955 );
956 } else {
957 sprintf(ext, "OK");
958 }
Alison Schofield29b1b612015-10-06 14:40:58 -0700959 } else if (!strcasecmp(ext, "LINKSPEED")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800960 /*Return link speed in MBPS */
961 /*LinkSpeed xx */
962 union iwreq_data wrqd;
963 int ret_inner;
964 int mbps;
965
966 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
Alison Schofield29b1b612015-10-06 14:40:58 -0700967 if (ret_inner != 0)
Ali Baharc6dc0012011-09-04 03:14:20 +0800968 mbps = 0;
969 else
970 mbps = wrqd.bitrate.value / 1000000;
971 sprintf(ext, "LINKSPEED %d", mbps);
Alison Schofield29b1b612015-10-06 14:40:58 -0700972 } else if (!strcasecmp(ext, "MACADDR")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800973 /*Return mac address of the station */
Andy Shevchenko87fa05e2013-07-10 17:27:21 +0300974 /* Macaddr = xx:xx:xx:xx:xx:xx */
975 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
Alison Schofield29b1b612015-10-06 14:40:58 -0700976 } else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800977 /*Set scan type to active */
978 /*OK if successful */
979 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530980
Ali Baharc6dc0012011-09-04 03:14:20 +0800981 pmlmepriv->passive_mode = 1;
982 sprintf(ext, "OK");
Alison Schofield29b1b612015-10-06 14:40:58 -0700983 } else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800984 /*Set scan type to passive */
985 /*OK if successful */
986 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530987
Ali Baharc6dc0012011-09-04 03:14:20 +0800988 pmlmepriv->passive_mode = 0;
989 sprintf(ext, "OK");
Alison Schofield29b1b612015-10-06 14:40:58 -0700990 } else if (!strncmp(ext, "DCE-E", 5)) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800991 /*Set scan type to passive */
992 /*OK if successful */
993 r8712_disconnectCtrlEx_cmd(padapter
994 , 1 /*u32 enableDrvCtrl */
995 , 5 /*u32 tryPktCnt */
996 , 100 /*u32 tryPktInterval */
997 , 5000 /*u32 firstStageTO */
998 );
999 sprintf(ext, "OK");
Alison Schofield29b1b612015-10-06 14:40:58 -07001000 } else if (!strncmp(ext, "DCE-D", 5)) {
Ali Baharc6dc0012011-09-04 03:14:20 +08001001 /*Set scan type to passive */
1002 /*OK if successfu */
1003 r8712_disconnectCtrlEx_cmd(padapter
1004 , 0 /*u32 enableDrvCtrl */
1005 , 5 /*u32 tryPktCnt */
1006 , 100 /*u32 tryPktInterval */
1007 , 5000 /*u32 firstStageTO */
1008 );
1009 sprintf(ext, "OK");
1010 } else {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001011 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1012 __func__, ext);
Ali Baharc6dc0012011-09-04 03:14:20 +08001013 goto FREE_EXT;
1014 }
1015 if (copy_to_user(dwrq->pointer, ext,
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001016 min(dwrq->length, (__u16)(strlen(ext) + 1))))
Ali Baharc6dc0012011-09-04 03:14:20 +08001017 ret = -EFAULT;
1018
1019FREE_EXT:
Larry Finger2865d422010-08-20 10:15:30 -05001020 kfree(ext);
1021 return ret;
1022}
1023
1024/* set bssid flow
1025 * s1. set_802_11_infrastructure_mode()
1026 * s2. set_802_11_authentication_mode()
1027 * s3. set_802_11_encryption_mode()
1028 * s4. set_802_11_bssid()
Ali Bahard1661df2011-07-12 23:10:55 +08001029 *
1030 * This function intends to handle the Set AP command, which specifies the
1031 * MAC# of a preferred Access Point.
1032 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1033 *
Justin P. Mattockbe10ac22012-05-07 07:38:22 -07001034 * For this operation to succeed, there is no need for the interface to be up.
Ali Bahard1661df2011-07-12 23:10:55 +08001035 *
Larry Finger2865d422010-08-20 10:15:30 -05001036 */
1037static int r8711_wx_set_wap(struct net_device *dev,
1038 struct iw_request_info *info,
1039 union iwreq_data *awrq,
1040 char *extra)
1041{
1042 int ret = -EINPROGRESS;
Julia Lawall8f47c282015-03-29 14:54:12 +02001043 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001044 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1045 struct __queue *queue = &pmlmepriv->scanned_queue;
1046 struct sockaddr *temp = (struct sockaddr *)awrq;
1047 unsigned long irqL;
1048 struct list_head *phead;
1049 u8 *dst_bssid;
1050 struct wlan_network *pnetwork = NULL;
1051 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1052
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001053 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
Ali Bahar2192e602011-09-04 03:14:24 +08001054 return -EBUSY;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001055 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
Larry Finger2865d422010-08-20 10:15:30 -05001056 return ret;
1057 if (temp->sa_family != ARPHRD_ETHER)
1058 return -EINVAL;
1059 authmode = padapter->securitypriv.ndisauthtype;
1060 spin_lock_irqsave(&queue->lock, irqL);
James A Shackleforde99a4282014-06-24 22:52:39 -04001061 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001062 pmlmepriv->pscanned = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001063 while (1) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001064 if (end_of_queue_search(phead, pmlmepriv->pscanned))
Larry Finger2865d422010-08-20 10:15:30 -05001065 break;
1066 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1067 struct wlan_network, list);
James A Shackleford849fb0a2014-06-24 22:52:38 -04001068 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
Larry Finger2865d422010-08-20 10:15:30 -05001069 dst_bssid = pnetwork->network.MacAddress;
1070 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
Ali Bahar2192e602011-09-04 03:14:24 +08001071 r8712_set_802_11_infrastructure_mode(padapter,
1072 pnetwork->network.InfrastructureMode);
Larry Finger2865d422010-08-20 10:15:30 -05001073 break;
1074 }
1075 }
1076 spin_unlock_irqrestore(&queue->lock, irqL);
1077 if (!ret) {
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001078 if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
Ali Bahar2192e602011-09-04 03:14:24 +08001079 ret = -ENOMEM;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001080 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001081 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1082 ret = -1;
1083 }
1084 }
1085 return ret;
1086}
1087
1088static int r8711_wx_get_wap(struct net_device *dev,
1089 struct iw_request_info *info,
1090 union iwreq_data *wrqu, char *extra)
1091{
Julia Lawall8f47c282015-03-29 14:54:12 +02001092 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001093 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -07001094 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -05001095
1096 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
Cyril Roelandt2df29e72012-12-11 01:20:48 +01001097 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1098 WIFI_AP_STATE))
Haneen Mohammede0e982b2015-03-16 18:41:31 +03001099 ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
Cyril Roelandt2df29e72012-12-11 01:20:48 +01001100 else
Aya Mahfouz22905b82015-03-04 09:00:02 +02001101 eth_zero_addr(wrqu->ap_addr.sa_data);
Larry Finger2865d422010-08-20 10:15:30 -05001102 return 0;
1103}
1104
1105static int r871x_wx_set_mlme(struct net_device *dev,
1106 struct iw_request_info *info,
1107 union iwreq_data *wrqu, char *extra)
1108{
1109 int ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02001110 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001111 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1112
1113 if (mlme == NULL)
1114 return -1;
Larry Finger2865d422010-08-20 10:15:30 -05001115 switch (mlme->cmd) {
1116 case IW_MLME_DEAUTH:
1117 if (!r8712_set_802_11_disassociate(padapter))
1118 ret = -1;
1119 break;
1120 case IW_MLME_DISASSOC:
1121 if (!r8712_set_802_11_disassociate(padapter))
1122 ret = -1;
1123 break;
1124 default:
1125 return -EOPNOTSUPP;
1126 }
1127 return ret;
1128}
1129
Ali Bahard1661df2011-07-12 23:10:55 +08001130/**
1131 *
1132 * This function intends to handle the Set Scan command.
1133 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1134 *
1135 * For this operation to succeed, the interface is brought Up beforehand.
1136 *
1137 */
Larry Finger2865d422010-08-20 10:15:30 -05001138static int r8711_wx_set_scan(struct net_device *dev,
1139 struct iw_request_info *a,
1140 union iwreq_data *wrqu, char *extra)
1141{
Julia Lawall8f47c282015-03-29 14:54:12 +02001142 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001143 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1144 u8 status = true;
1145
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001146 if (padapter->bDriverStopped) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001147 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1148 __func__, padapter->bDriverStopped);
Larry Finger2865d422010-08-20 10:15:30 -05001149 return -1;
1150 }
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001151 if (!padapter->bup)
Ali Bahar2192e602011-09-04 03:14:24 +08001152 return -ENETDOWN;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001153 if (!padapter->hw_init_completed)
Larry Finger2865d422010-08-20 10:15:30 -05001154 return -1;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001155 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001156 (pmlmepriv->sitesurveyctrl.traffic_busy))
Larry Finger2865d422010-08-20 10:15:30 -05001157 return 0;
1158 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1159 struct iw_scan_req *req = (struct iw_scan_req *)extra;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +05301160
Larry Finger2865d422010-08-20 10:15:30 -05001161 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1162 struct ndis_802_11_ssid ssid;
1163 unsigned long irqL;
Przemo Firszt0024a1e2012-12-10 23:21:22 +00001164 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
Tapasweni Pathak02a29d22014-09-24 16:34:56 +05301165
Larry Finger2865d422010-08-20 10:15:30 -05001166 memset((unsigned char *)&ssid, 0,
1167 sizeof(struct ndis_802_11_ssid));
1168 memcpy(ssid.Ssid, req->essid, len);
1169 ssid.SsidLength = len;
1170 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1171 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1172 _FW_UNDER_LINKING)) ||
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001173 (pmlmepriv->sitesurveyctrl.traffic_busy)) {
Larry Finger2865d422010-08-20 10:15:30 -05001174 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1175 status = false;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001176 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001177 status = r8712_sitesurvey_cmd(padapter, &ssid);
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001178 }
Larry Finger2865d422010-08-20 10:15:30 -05001179 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1180 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001181 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001182 status = r8712_set_802_11_bssid_list_scan(padapter);
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001183 }
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001184 if (!status)
Larry Finger2865d422010-08-20 10:15:30 -05001185 return -1;
1186 return 0;
1187}
1188
1189static int r8711_wx_get_scan(struct net_device *dev,
1190 struct iw_request_info *a,
1191 union iwreq_data *wrqu, char *extra)
1192{
Julia Lawall8f47c282015-03-29 14:54:12 +02001193 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001194 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1195 struct __queue *queue = &pmlmepriv->scanned_queue;
1196 struct wlan_network *pnetwork = NULL;
1197 unsigned long irqL;
1198 struct list_head *plist, *phead;
1199 char *ev = extra;
1200 char *stop = ev + wrqu->data.length;
1201 u32 ret = 0, cnt = 0;
1202
1203 if (padapter->bDriverStopped)
1204 return -EINVAL;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001205 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1206 _FW_UNDER_LINKING)) {
Larry Finger2865d422010-08-20 10:15:30 -05001207 msleep(30);
1208 cnt++;
Ali Baharc6dc0012011-09-04 03:14:20 +08001209 if (cnt > 100)
Larry Finger2865d422010-08-20 10:15:30 -05001210 break;
1211 }
1212 spin_lock_irqsave(&queue->lock, irqL);
James A Shackleforde99a4282014-06-24 22:52:39 -04001213 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001214 plist = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001215 while (1) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001216 if (end_of_queue_search(phead, plist))
Larry Finger2865d422010-08-20 10:15:30 -05001217 break;
1218 if ((stop - ev) < SCAN_ITEM_SIZE) {
1219 ret = -E2BIG;
1220 break;
1221 }
1222 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1223 ev = translate_scan(padapter, a, pnetwork, ev, stop);
James A Shackleford849fb0a2014-06-24 22:52:38 -04001224 plist = plist->next;
Larry Finger2865d422010-08-20 10:15:30 -05001225 }
1226 spin_unlock_irqrestore(&queue->lock, irqL);
1227 wrqu->data.length = ev - extra;
1228 wrqu->data.flags = 0;
1229 return ret;
1230}
1231
1232/* set ssid flow
1233 * s1. set_802_11_infrastructure_mode()
1234 * s2. set_802_11_authenticaion_mode()
1235 * s3. set_802_11_encryption_mode()
1236 * s4. set_802_11_ssid()
Ali Bahard1661df2011-07-12 23:10:55 +08001237 *
1238 * This function intends to handle the Set ESSID command.
1239 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1240 *
1241 * For this operation to succeed, there is no need for the interface to be Up.
1242 *
Larry Finger2865d422010-08-20 10:15:30 -05001243 */
1244static int r8711_wx_set_essid(struct net_device *dev,
1245 struct iw_request_info *a,
1246 union iwreq_data *wrqu, char *extra)
1247{
Julia Lawall8f47c282015-03-29 14:54:12 +02001248 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001249 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1250 struct __queue *queue = &pmlmepriv->scanned_queue;
1251 struct wlan_network *pnetwork = NULL;
1252 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1253 struct ndis_802_11_ssid ndis_ssid;
1254 u8 *dst_ssid, *src_ssid;
1255 struct list_head *phead;
1256 u32 len;
1257
Larry Finger2865d422010-08-20 10:15:30 -05001258 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
Ali Bahar2192e602011-09-04 03:14:24 +08001259 return -EBUSY;
Larry Finger2865d422010-08-20 10:15:30 -05001260 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1261 return 0;
1262 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1263 return -E2BIG;
1264 authmode = padapter->securitypriv.ndisauthtype;
1265 if (wrqu->essid.flags && wrqu->essid.length) {
1266 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1267 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1268 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1269 ndis_ssid.SsidLength = len;
1270 memcpy(ndis_ssid.Ssid, extra, len);
1271 src_ssid = ndis_ssid.Ssid;
James A Shackleforde99a4282014-06-24 22:52:39 -04001272 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001273 pmlmepriv->pscanned = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001274 while (1) {
1275 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1276 break;
1277 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1278 struct wlan_network, list);
James A Shackleford849fb0a2014-06-24 22:52:38 -04001279 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
Larry Finger2865d422010-08-20 10:15:30 -05001280 dst_ssid = pnetwork->network.Ssid.Ssid;
1281 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1282 && (pnetwork->network.Ssid.SsidLength ==
1283 ndis_ssid.SsidLength)) {
Ali Baharc6dc0012011-09-04 03:14:20 +08001284 if (check_fwstate(pmlmepriv,
1285 WIFI_ADHOC_STATE)) {
1286 if (pnetwork->network.
1287 InfrastructureMode
1288 !=
1289 padapter->mlmepriv.
1290 cur_network.network.
1291 InfrastructureMode)
1292 continue;
1293 }
1294
Ali Bahar2192e602011-09-04 03:14:24 +08001295 r8712_set_802_11_infrastructure_mode(
Larry Finger2865d422010-08-20 10:15:30 -05001296 padapter,
Ali Bahar2192e602011-09-04 03:14:24 +08001297 pnetwork->network.InfrastructureMode);
Larry Finger2865d422010-08-20 10:15:30 -05001298 break;
1299 }
1300 }
1301 r8712_set_802_11_authentication_mode(padapter, authmode);
1302 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1303 }
1304 return -EINPROGRESS;
1305}
1306
1307static int r8711_wx_get_essid(struct net_device *dev,
1308 struct iw_request_info *a,
1309 union iwreq_data *wrqu, char *extra)
1310{
Julia Lawall8f47c282015-03-29 14:54:12 +02001311 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001312 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -07001313 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -05001314 u32 len, ret = 0;
1315
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001316 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
Larry Finger2865d422010-08-20 10:15:30 -05001317 len = pcur_bss->Ssid.SsidLength;
1318 wrqu->essid.length = len;
1319 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1320 wrqu->essid.flags = 1;
Ali Bahar2192e602011-09-04 03:14:24 +08001321 } else {
1322 ret = -ENOLINK;
1323 }
Larry Finger2865d422010-08-20 10:15:30 -05001324 return ret;
1325}
1326
1327static int r8711_wx_set_rate(struct net_device *dev,
1328 struct iw_request_info *a,
1329 union iwreq_data *wrqu, char *extra)
1330{
Julia Lawall8f47c282015-03-29 14:54:12 +02001331 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001332 u32 target_rate = wrqu->bitrate.value;
1333 u32 fixed = wrqu->bitrate.fixed;
1334 u32 ratevalue = 0;
1335 u8 datarates[NumRates];
1336 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1337 int i, ret = 0;
1338
1339 if (target_rate == -1) {
1340 ratevalue = 11;
1341 goto set_rate;
1342 }
1343 target_rate = target_rate / 100000;
1344 switch (target_rate) {
1345 case 10:
1346 ratevalue = 0;
1347 break;
1348 case 20:
1349 ratevalue = 1;
1350 break;
1351 case 55:
1352 ratevalue = 2;
1353 break;
1354 case 60:
1355 ratevalue = 3;
1356 break;
1357 case 90:
1358 ratevalue = 4;
1359 break;
1360 case 110:
1361 ratevalue = 5;
1362 break;
1363 case 120:
1364 ratevalue = 6;
1365 break;
1366 case 180:
1367 ratevalue = 7;
1368 break;
1369 case 240:
1370 ratevalue = 8;
1371 break;
1372 case 360:
1373 ratevalue = 9;
1374 break;
1375 case 480:
1376 ratevalue = 10;
1377 break;
1378 case 540:
1379 ratevalue = 11;
1380 break;
1381 default:
1382 ratevalue = 11;
1383 break;
1384 }
1385set_rate:
1386 for (i = 0; i < NumRates; i++) {
1387 if (ratevalue == mpdatarate[i]) {
1388 datarates[i] = mpdatarate[i];
1389 if (fixed == 0)
1390 break;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001391 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001392 datarates[i] = 0xff;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001393 }
Larry Finger2865d422010-08-20 10:15:30 -05001394 }
1395 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
Ali Bahar2192e602011-09-04 03:14:24 +08001396 ret = -ENOMEM;
Larry Finger2865d422010-08-20 10:15:30 -05001397 return ret;
1398}
1399
1400static int r8711_wx_get_rate(struct net_device *dev,
1401 struct iw_request_info *info,
1402 union iwreq_data *wrqu, char *extra)
1403{
Julia Lawall8f47c282015-03-29 14:54:12 +02001404 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001405 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -07001406 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -05001407 struct ieee80211_ht_cap *pht_capie;
Ali Baharc6dc0012011-09-04 03:14:20 +08001408 unsigned char rf_type = padapter->registrypriv.rf_config;
Larry Finger2865d422010-08-20 10:15:30 -05001409 int i;
1410 u8 *p;
1411 u16 rate, max_rate = 0, ht_cap = false;
1412 u32 ht_ielen = 0;
1413 u8 bw_40MHz = 0, short_GI = 0;
1414 u16 mcs_rate = 0;
1415
1416 i = 0;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001417 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
Larry Finger2865d422010-08-20 10:15:30 -05001418 p = r8712_get_ie(&pcur_bss->IEs[12],
1419 _HT_CAPABILITY_IE_, &ht_ielen,
1420 pcur_bss->IELength - 12);
1421 if (p && ht_ielen > 0) {
1422 ht_cap = true;
1423 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
Max Perepelitsyn0636b462015-01-02 14:08:08 +06001424 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
Larry Finger2865d422010-08-20 10:15:30 -05001425 bw_40MHz = (pht_capie->cap_info &
1426 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1427 short_GI = (pht_capie->cap_info &
1428 (IEEE80211_HT_CAP_SGI_20 |
1429 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1430 }
Joshua Clayton7fb539e2015-08-05 17:17:21 -07001431 while ((pcur_bss->rates[i] != 0) &&
1432 (pcur_bss->rates[i] != 0xFF)) {
1433 rate = pcur_bss->rates[i] & 0x7F;
Larry Finger2865d422010-08-20 10:15:30 -05001434 if (rate > max_rate)
1435 max_rate = rate;
1436 wrqu->bitrate.fixed = 0; /* no auto select */
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001437 wrqu->bitrate.value = rate * 500000;
Larry Finger2865d422010-08-20 10:15:30 -05001438 i++;
1439 }
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001440 if (ht_cap) {
Ali Baharc6dc0012011-09-04 03:14:20 +08001441 if (mcs_rate & 0x8000 /* MCS15 */
1442 &&
Alison Schofield29b1b612015-10-06 14:40:58 -07001443 rf_type == RTL8712_RF_2T2R)
Larry Finger2865d422010-08-20 10:15:30 -05001444 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1445 270) : ((short_GI) ? 144 : 130);
Larry Finger2865d422010-08-20 10:15:30 -05001446 else /* default MCS7 */
1447 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1448 135) : ((short_GI) ? 72 : 65);
1449 max_rate *= 2; /* Mbps/2 */
Larry Finger2865d422010-08-20 10:15:30 -05001450 }
Rickard Strandqvist3ae70742014-06-15 19:20:58 +02001451 wrqu->bitrate.value = max_rate * 500000;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001452 } else {
Ali Bahar2192e602011-09-04 03:14:24 +08001453 return -ENOLINK;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001454 }
Larry Finger2865d422010-08-20 10:15:30 -05001455 return 0;
1456}
1457
1458static int r8711_wx_get_rts(struct net_device *dev,
1459 struct iw_request_info *info,
1460 union iwreq_data *wrqu, char *extra)
1461{
Julia Lawall8f47c282015-03-29 14:54:12 +02001462 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001463
1464 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1465 wrqu->rts.fixed = 0; /* no auto select */
1466 return 0;
1467}
1468
1469static int r8711_wx_set_frag(struct net_device *dev,
1470 struct iw_request_info *info,
1471 union iwreq_data *wrqu, char *extra)
1472{
Julia Lawall8f47c282015-03-29 14:54:12 +02001473 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001474
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001475 if (wrqu->frag.disabled) {
Larry Finger2865d422010-08-20 10:15:30 -05001476 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001477 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001478 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1479 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1480 return -EINVAL;
1481 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1482 }
1483 return 0;
1484}
1485
1486static int r8711_wx_get_frag(struct net_device *dev,
1487 struct iw_request_info *info,
1488 union iwreq_data *wrqu, char *extra)
1489{
Julia Lawall8f47c282015-03-29 14:54:12 +02001490 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001491
1492 wrqu->frag.value = padapter->xmitpriv.frag_len;
1493 wrqu->frag.fixed = 0; /* no auto select */
1494 return 0;
1495}
1496
1497static int r8711_wx_get_retry(struct net_device *dev,
1498 struct iw_request_info *info,
1499 union iwreq_data *wrqu, char *extra)
1500{
1501 wrqu->retry.value = 7;
1502 wrqu->retry.fixed = 0; /* no auto select */
1503 wrqu->retry.disabled = 1;
1504 return 0;
1505}
1506
1507static int r8711_wx_set_enc(struct net_device *dev,
1508 struct iw_request_info *info,
1509 union iwreq_data *wrqu, char *keybuf)
1510{
1511 u32 key;
1512 u32 keyindex_provided;
1513 struct NDIS_802_11_WEP wep;
1514 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1515 struct iw_point *erq = &(wrqu->encoding);
Julia Lawall8f47c282015-03-29 14:54:12 +02001516 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001517
1518 key = erq->flags & IW_ENCODE_INDEX;
1519 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1520 if (erq->flags & IW_ENCODE_DISABLED) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001521 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -05001522 padapter->securitypriv.ndisencryptstatus =
1523 Ndis802_11EncryptionDisabled;
1524 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1525 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1526 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1527 authmode = Ndis802_11AuthModeOpen;
1528 padapter->securitypriv.ndisauthtype = authmode;
1529 return 0;
1530 }
1531 if (key) {
1532 if (key > WEP_KEYS)
1533 return -EINVAL;
1534 key--;
1535 keyindex_provided = 1;
1536 } else {
1537 keyindex_provided = 0;
1538 key = padapter->securitypriv.PrivacyKeyIndex;
1539 }
1540 /* set authentication mode */
1541 if (erq->flags & IW_ENCODE_OPEN) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001542 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -05001543 padapter->securitypriv.ndisencryptstatus =
1544 Ndis802_11Encryption1Enabled;
1545 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1546 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1547 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1548 authmode = Ndis802_11AuthModeOpen;
1549 padapter->securitypriv.ndisauthtype = authmode;
1550 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
Tapasweni Pathak57b66862014-09-21 06:42:21 +05301551 netdev_info(dev,
1552 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -05001553 padapter->securitypriv.ndisencryptstatus =
1554 Ndis802_11Encryption1Enabled;
1555 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1556 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1557 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1558 authmode = Ndis802_11AuthModeShared;
1559 padapter->securitypriv.ndisauthtype = authmode;
1560 } else {
1561 padapter->securitypriv.ndisencryptstatus =
1562 Ndis802_11Encryption1Enabled;
1563 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1564 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1565 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1566 authmode = Ndis802_11AuthModeOpen;
1567 padapter->securitypriv.ndisauthtype = authmode;
1568 }
1569 wep.KeyIndex = key;
1570 if (erq->length > 0) {
1571 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1572 wep.Length = wep.KeyLength +
1573 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1574 } else {
Thomas Cort77e73e82013-10-01 11:26:55 -04001575 wep.KeyLength = 0;
Larry Finger2865d422010-08-20 10:15:30 -05001576 if (keyindex_provided == 1) { /* set key_id only, no given
Punit Varad32c16d2015-10-14 23:55:54 +05301577 * KeyMaterial(erq->length==0).
1578 */
Larry Finger2865d422010-08-20 10:15:30 -05001579 padapter->securitypriv.PrivacyKeyIndex = key;
1580 switch (padapter->securitypriv.DefKeylen[key]) {
1581 case 5:
1582 padapter->securitypriv.PrivacyAlgrthm =
1583 _WEP40_;
1584 break;
1585 case 13:
1586 padapter->securitypriv.PrivacyAlgrthm =
1587 _WEP104_;
1588 break;
1589 default:
1590 padapter->securitypriv.PrivacyAlgrthm =
1591 _NO_PRIVACY_;
1592 break;
1593 }
1594 return 0;
1595 }
1596 }
1597 wep.KeyIndex |= 0x80000000; /* transmit key */
1598 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1599 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1600 return -EOPNOTSUPP;
1601 return 0;
1602}
1603
1604static int r8711_wx_get_enc(struct net_device *dev,
1605 struct iw_request_info *info,
1606 union iwreq_data *wrqu, char *keybuf)
1607{
1608 uint key, ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02001609 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001610 struct iw_point *erq = &(wrqu->encoding);
1611 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1612
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001613 if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
Larry Finger2865d422010-08-20 10:15:30 -05001614 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1615 erq->length = 0;
1616 erq->flags |= IW_ENCODE_DISABLED;
1617 return 0;
1618 }
1619 }
1620 key = erq->flags & IW_ENCODE_INDEX;
1621 if (key) {
1622 if (key > WEP_KEYS)
1623 return -EINVAL;
1624 key--;
1625 } else {
1626 key = padapter->securitypriv.PrivacyKeyIndex;
1627 }
1628 erq->flags = key + 1;
1629 switch (padapter->securitypriv.ndisencryptstatus) {
1630 case Ndis802_11EncryptionNotSupported:
1631 case Ndis802_11EncryptionDisabled:
1632 erq->length = 0;
1633 erq->flags |= IW_ENCODE_DISABLED;
1634 break;
1635 case Ndis802_11Encryption1Enabled:
1636 erq->length = padapter->securitypriv.DefKeylen[key];
1637 if (erq->length) {
1638 memcpy(keybuf, padapter->securitypriv.DefKey[
1639 key].skey, padapter->securitypriv.
1640 DefKeylen[key]);
1641 erq->flags |= IW_ENCODE_ENABLED;
1642 if (padapter->securitypriv.ndisauthtype ==
1643 Ndis802_11AuthModeOpen)
1644 erq->flags |= IW_ENCODE_OPEN;
1645 else if (padapter->securitypriv.ndisauthtype ==
1646 Ndis802_11AuthModeShared)
1647 erq->flags |= IW_ENCODE_RESTRICTED;
1648 } else {
1649 erq->length = 0;
1650 erq->flags |= IW_ENCODE_DISABLED;
1651 }
1652 break;
1653 case Ndis802_11Encryption2Enabled:
1654 case Ndis802_11Encryption3Enabled:
1655 erq->length = 16;
1656 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1657 IW_ENCODE_NOKEY);
1658 break;
1659 default:
1660 erq->length = 0;
1661 erq->flags |= IW_ENCODE_DISABLED;
1662 break;
1663 }
1664 return ret;
1665}
1666
1667static int r8711_wx_get_power(struct net_device *dev,
1668 struct iw_request_info *info,
1669 union iwreq_data *wrqu, char *extra)
1670{
1671 wrqu->power.value = 0;
1672 wrqu->power.fixed = 0; /* no auto select */
1673 wrqu->power.disabled = 1;
1674 return 0;
1675}
1676
1677static int r871x_wx_set_gen_ie(struct net_device *dev,
1678 struct iw_request_info *info,
1679 union iwreq_data *wrqu, char *extra)
1680{
Julia Lawall8f47c282015-03-29 14:54:12 +02001681 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001682
1683 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1684}
1685
1686static int r871x_wx_set_auth(struct net_device *dev,
1687 struct iw_request_info *info,
1688 union iwreq_data *wrqu, char *extra)
1689{
Julia Lawall8f47c282015-03-29 14:54:12 +02001690 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001691 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1692 int paramid;
1693 int paramval;
1694 int ret = 0;
1695
1696 paramid = param->flags & IW_AUTH_INDEX;
1697 paramval = param->value;
1698 switch (paramid) {
1699 case IW_AUTH_WPA_VERSION:
1700 break;
1701 case IW_AUTH_CIPHER_PAIRWISE:
1702 break;
1703 case IW_AUTH_CIPHER_GROUP:
1704 break;
1705 case IW_AUTH_KEY_MGMT:
1706 /*
1707 * ??? does not use these parameters
1708 */
1709 break;
1710 case IW_AUTH_TKIP_COUNTERMEASURES:
1711 if (paramval) {
1712 /* wpa_supplicant is enabling tkip countermeasure. */
1713 padapter->securitypriv.btkip_countermeasure = true;
1714 } else {
1715 /* wpa_supplicant is disabling tkip countermeasure. */
1716 padapter->securitypriv.btkip_countermeasure = false;
1717 }
1718 break;
1719 case IW_AUTH_DROP_UNENCRYPTED:
1720 /* HACK:
1721 *
1722 * wpa_supplicant calls set_wpa_enabled when the driver
1723 * is loaded and unloaded, regardless of if WPA is being
1724 * used. No other calls are made which can be used to
1725 * determine if encryption will be used or not prior to
1726 * association being expected. If encryption is not being
1727 * used, drop_unencrypted is set to false, else true -- we
1728 * can use this to determine if the CAP_PRIVACY_ON bit should
1729 * be set.
1730 */
1731 if (padapter->securitypriv.ndisencryptstatus ==
1732 Ndis802_11Encryption1Enabled) {
1733 /* it means init value, or using wep,
1734 * ndisencryptstatus =
1735 * Ndis802_11Encryption1Enabled,
1736 * then it needn't reset it;
1737 */
1738 break;
1739 }
1740
1741 if (paramval) {
1742 padapter->securitypriv.ndisencryptstatus =
1743 Ndis802_11EncryptionDisabled;
1744 padapter->securitypriv.PrivacyAlgrthm =
1745 _NO_PRIVACY_;
1746 padapter->securitypriv.XGrpPrivacy =
1747 _NO_PRIVACY_;
1748 padapter->securitypriv.AuthAlgrthm = 0;
1749 padapter->securitypriv.ndisauthtype =
1750 Ndis802_11AuthModeOpen;
1751 }
1752 break;
1753 case IW_AUTH_80211_AUTH_ALG:
1754 ret = wpa_set_auth_algs(dev, (u32)paramval);
1755 break;
1756 case IW_AUTH_WPA_ENABLED:
1757 break;
1758 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1759 break;
1760 case IW_AUTH_PRIVACY_INVOKED:
1761 break;
1762 default:
1763 return -EOPNOTSUPP;
1764 }
1765
1766 return ret;
1767}
1768
1769static int r871x_wx_set_enc_ext(struct net_device *dev,
1770 struct iw_request_info *info,
1771 union iwreq_data *wrqu, char *extra)
1772{
1773 struct iw_point *pencoding = &wrqu->encoding;
1774 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1775 struct ieee_param *param = NULL;
1776 char *alg_name;
1777 u32 param_len;
1778 int ret = 0;
1779
Larry Finger2865d422010-08-20 10:15:30 -05001780 switch (pext->alg) {
1781 case IW_ENCODE_ALG_NONE:
1782 alg_name = "none";
1783 break;
1784 case IW_ENCODE_ALG_WEP:
1785 alg_name = "WEP";
1786 break;
1787 case IW_ENCODE_ALG_TKIP:
1788 alg_name = "TKIP";
1789 break;
1790 case IW_ENCODE_ALG_CCMP:
1791 alg_name = "CCMP";
1792 break;
1793 default:
Ali Bahar2192e602011-09-04 03:14:24 +08001794 return -EINVAL;
Larry Finger2865d422010-08-20 10:15:30 -05001795 }
Christian Engelmayer55d4f6c2014-05-07 21:36:48 +02001796
1797 param_len = sizeof(struct ieee_param) + pext->key_len;
Vitaly Osipov91d435f2014-05-24 18:19:27 +10001798 param = kzalloc(param_len, GFP_ATOMIC);
Christian Engelmayer55d4f6c2014-05-07 21:36:48 +02001799 if (param == NULL)
1800 return -ENOMEM;
Christian Engelmayer55d4f6c2014-05-07 21:36:48 +02001801 param->cmd = IEEE_CMD_SET_ENCRYPTION;
Punit Varae904cc82015-10-14 23:55:52 +05301802 eth_broadcast_addr(param->sta_addr);
Larry Finger2865d422010-08-20 10:15:30 -05001803 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1804 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1805 param->u.crypt.set_tx = 0;
1806 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1807 param->u.crypt.set_tx = 1;
1808 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1809 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1810 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1811 if (pext->key_len) {
1812 param->u.crypt.key_len = pext->key_len;
1813 memcpy(param + 1, pext + 1, pext->key_len);
1814 }
1815 ret = wpa_set_encryption(dev, param, param_len);
Alexander Beregalov40083862011-03-26 20:18:14 +03001816 kfree(param);
Larry Finger2865d422010-08-20 10:15:30 -05001817 return ret;
1818}
1819
1820static int r871x_wx_get_nick(struct net_device *dev,
1821 struct iw_request_info *info,
1822 union iwreq_data *wrqu, char *extra)
1823{
1824 if (extra) {
1825 wrqu->data.length = 8;
1826 wrqu->data.flags = 1;
1827 memcpy(extra, "rtl_wifi", 8);
1828 }
1829 return 0;
1830}
1831
1832static int r8711_wx_read32(struct net_device *dev,
1833 struct iw_request_info *info,
1834 union iwreq_data *wrqu, char *keybuf)
1835{
Julia Lawall8f47c282015-03-29 14:54:12 +02001836 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001837 u32 addr;
1838 u32 data32;
1839
1840 get_user(addr, (u32 __user *)wrqu->data.pointer);
1841 data32 = r8712_read32(padapter, addr);
1842 put_user(data32, (u32 __user *)wrqu->data.pointer);
1843 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1844 wrqu->data.flags = data32 & 0xffff;
1845 get_user(addr, (u32 __user *)wrqu->data.pointer);
1846 return 0;
1847}
1848
1849static int r8711_wx_write32(struct net_device *dev,
1850 struct iw_request_info *info,
1851 union iwreq_data *wrqu, char *keybuf)
1852{
Julia Lawall8f47c282015-03-29 14:54:12 +02001853 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001854 u32 addr;
1855 u32 data32;
1856
1857 get_user(addr, (u32 __user *)wrqu->data.pointer);
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001858 data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
Larry Finger2865d422010-08-20 10:15:30 -05001859 r8712_write32(padapter, addr, data32);
1860 return 0;
1861}
1862
1863static int dummy(struct net_device *dev,
1864 struct iw_request_info *a,
1865 union iwreq_data *wrqu, char *b)
1866{
Ali Bahar2192e602011-09-04 03:14:24 +08001867 return -ENOSYS;
Larry Finger2865d422010-08-20 10:15:30 -05001868}
1869
1870static int r8711_drvext_hdl(struct net_device *dev,
1871 struct iw_request_info *info,
1872 union iwreq_data *wrqu, char *extra)
1873{
1874 return 0;
1875}
1876
1877static int r871x_mp_ioctl_hdl(struct net_device *dev,
1878 struct iw_request_info *info,
1879 union iwreq_data *wrqu, char *extra)
1880{
Julia Lawall8f47c282015-03-29 14:54:12 +02001881 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001882 struct iw_point *p = &wrqu->data;
1883 struct oid_par_priv oid_par;
1884 struct mp_ioctl_handler *phandler;
1885 struct mp_ioctl_param *poidparam;
1886 unsigned long BytesRead, BytesWritten, BytesNeeded;
Dan Carpenterb5eed732015-04-08 14:19:00 +03001887 u8 *pparmbuf, bset;
Larry Finger2865d422010-08-20 10:15:30 -05001888 u16 len;
1889 uint status;
1890 int ret = 0;
1891
Dan Carpenterb5eed732015-04-08 14:19:00 +03001892 if ((!p->length) || (!p->pointer))
1893 return -EINVAL;
1894
Larry Finger2865d422010-08-20 10:15:30 -05001895 bset = (u8)(p->flags & 0xFFFF);
1896 len = p->length;
Cristina Opriceana45de4322015-03-28 02:57:34 +02001897 pparmbuf = memdup_user(p->pointer, len);
Dan Carpenterb5eed732015-04-08 14:19:00 +03001898 if (IS_ERR(pparmbuf))
1899 return PTR_ERR(pparmbuf);
1900
Larry Finger2865d422010-08-20 10:15:30 -05001901 poidparam = (struct mp_ioctl_param *)pparmbuf;
1902 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1903 ret = -EINVAL;
1904 goto _r871x_mp_ioctl_hdl_exit;
1905 }
1906 phandler = mp_ioctl_hdl + poidparam->subcode;
1907 if ((phandler->paramsize != 0) &&
1908 (poidparam->len < phandler->paramsize)) {
1909 ret = -EINVAL;
1910 goto _r871x_mp_ioctl_hdl_exit;
1911 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001912 if (phandler->oid == 0 && phandler->handler) {
Larry Finger2865d422010-08-20 10:15:30 -05001913 status = phandler->handler(&oid_par);
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001914 } else if (phandler->handler) {
Larry Finger2865d422010-08-20 10:15:30 -05001915 oid_par.adapter_context = padapter;
1916 oid_par.oid = phandler->oid;
1917 oid_par.information_buf = poidparam->data;
1918 oid_par.information_buf_len = poidparam->len;
1919 oid_par.dbg = 0;
1920 BytesWritten = 0;
1921 BytesNeeded = 0;
1922 if (bset) {
1923 oid_par.bytes_rw = &BytesRead;
1924 oid_par.bytes_needed = &BytesNeeded;
1925 oid_par.type_of_oid = SET_OID;
1926 } else {
1927 oid_par.bytes_rw = &BytesWritten;
1928 oid_par.bytes_needed = &BytesNeeded;
1929 oid_par.type_of_oid = QUERY_OID;
1930 }
1931 status = phandler->handler(&oid_par);
1932 /* todo:check status, BytesNeeded, etc. */
1933 } else {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001934 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1935 __func__, poidparam->subcode, phandler->oid,
1936 phandler->handler);
Larry Finger2865d422010-08-20 10:15:30 -05001937 ret = -EFAULT;
1938 goto _r871x_mp_ioctl_hdl_exit;
1939 }
1940 if (bset == 0x00) { /* query info */
1941 if (copy_to_user(p->pointer, pparmbuf, len))
1942 ret = -EFAULT;
1943 }
1944 if (status) {
1945 ret = -EFAULT;
1946 goto _r871x_mp_ioctl_hdl_exit;
1947 }
1948_r871x_mp_ioctl_hdl_exit:
Ilia Mirkinb7977fa2011-03-13 00:29:08 -05001949 kfree(pparmbuf);
Larry Finger2865d422010-08-20 10:15:30 -05001950 return ret;
1951}
1952
1953static int r871x_get_ap_info(struct net_device *dev,
1954 struct iw_request_info *info,
1955 union iwreq_data *wrqu, char *extra)
1956{
Julia Lawall8f47c282015-03-29 14:54:12 +02001957 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001958 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1959 struct __queue *queue = &pmlmepriv->scanned_queue;
1960 struct iw_point *pdata = &wrqu->data;
1961 struct wlan_network *pnetwork = NULL;
1962 u32 cnt = 0, wpa_ielen;
1963 unsigned long irqL;
1964 struct list_head *plist, *phead;
1965 unsigned char *pbuf;
1966 u8 bssid[ETH_ALEN];
1967 char data[32];
1968
1969 if (padapter->bDriverStopped || (pdata == NULL))
1970 return -EINVAL;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001971 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1972 _FW_UNDER_LINKING)) {
Larry Finger2865d422010-08-20 10:15:30 -05001973 msleep(30);
1974 cnt++;
1975 if (cnt > 100)
1976 break;
1977 }
1978 pdata->flags = 0;
1979 if (pdata->length >= 32) {
1980 if (copy_from_user(data, pdata->pointer, 32))
1981 return -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001982 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001983 return -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001984 }
Larry Finger2865d422010-08-20 10:15:30 -05001985 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
James A Shackleforde99a4282014-06-24 22:52:39 -04001986 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001987 plist = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001988 while (1) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001989 if (end_of_queue_search(phead, plist))
Larry Finger2865d422010-08-20 10:15:30 -05001990 break;
1991 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
Andy Shevchenko3fe1be82015-10-01 16:18:07 +03001992 if (!mac_pton(data, bssid)) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001993 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
1994 (u8 *)data);
Larry Finger2865d422010-08-20 10:15:30 -05001995 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
Przemo Firszt87a573a2012-12-10 23:21:21 +00001996 irqL);
Larry Finger2865d422010-08-20 10:15:30 -05001997 return -EINVAL;
1998 }
Przemo Firszt87a573a2012-12-10 23:21:21 +00001999 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
Punit Varaa1b42be2015-10-14 23:55:53 +05302000 if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
Larry Finger2865d422010-08-20 10:15:30 -05002001 /* BSSID match, then check if supporting wpa/wpa2 */
2002 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01002003 &wpa_ielen, pnetwork->network.IELength - 12);
Larry Finger2865d422010-08-20 10:15:30 -05002004 if (pbuf && (wpa_ielen > 0)) {
2005 pdata->flags = 1;
2006 break;
2007 }
2008 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01002009 &wpa_ielen, pnetwork->network.IELength - 12);
Larry Finger2865d422010-08-20 10:15:30 -05002010 if (pbuf && (wpa_ielen > 0)) {
2011 pdata->flags = 2;
2012 break;
2013 }
2014 }
James A Shackleford849fb0a2014-06-24 22:52:38 -04002015 plist = plist->next;
Larry Finger2865d422010-08-20 10:15:30 -05002016 }
2017 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2018 if (pdata->length >= 34) {
2019 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2020 (u8 *)&pdata->flags, 1))
2021 return -EINVAL;
2022 }
2023 return 0;
2024}
2025
2026static int r871x_set_pid(struct net_device *dev,
2027 struct iw_request_info *info,
2028 union iwreq_data *wrqu, char *extra)
2029{
Julia Lawall8f47c282015-03-29 14:54:12 +02002030 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002031 struct iw_point *pdata = &wrqu->data;
2032
2033 if ((padapter->bDriverStopped) || (pdata == NULL))
2034 return -EINVAL;
2035 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2036 return -EINVAL;
2037 return 0;
2038}
2039
Ali Baharc6dc0012011-09-04 03:14:20 +08002040static int r871x_set_chplan(struct net_device *dev,
2041 struct iw_request_info *info,
2042 union iwreq_data *wrqu, char *extra)
2043{
2044 int ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02002045 struct _adapter *padapter = netdev_priv(dev);
Ali Baharc6dc0012011-09-04 03:14:20 +08002046 struct iw_point *pdata = &wrqu->data;
2047 int ch_plan = -1;
2048
2049 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2050 ret = -EINVAL;
2051 goto exit;
2052 }
2053 ch_plan = (int)*extra;
2054 r8712_set_chplan_cmd(padapter, ch_plan);
2055
2056exit:
2057
2058 return ret;
2059}
2060
Larry Finger2865d422010-08-20 10:15:30 -05002061static int r871x_wps_start(struct net_device *dev,
2062 struct iw_request_info *info,
2063 union iwreq_data *wrqu, char *extra)
2064{
Julia Lawall8f47c282015-03-29 14:54:12 +02002065 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002066 struct iw_point *pdata = &wrqu->data;
2067 u32 u32wps_start = 0;
Larry Finger2865d422010-08-20 10:15:30 -05002068
Larry Finger2865d422010-08-20 10:15:30 -05002069 if ((padapter->bDriverStopped) || (pdata == NULL))
2070 return -EINVAL;
Wei Yongjun605fba82012-10-08 08:43:45 +08002071 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2072 return -EFAULT;
Larry Finger2865d422010-08-20 10:15:30 -05002073 if (u32wps_start == 0)
2074 u32wps_start = *extra;
2075 if (u32wps_start == 1) /* WPS Start */
2076 padapter->ledpriv.LedControlHandler(padapter,
2077 LED_CTL_START_WPS);
2078 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2079 padapter->ledpriv.LedControlHandler(padapter,
2080 LED_CTL_STOP_WPS);
2081 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2082 padapter->ledpriv.LedControlHandler(padapter,
2083 LED_CTL_STOP_WPS_FAIL);
2084 return 0;
2085}
2086
2087static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2088{
Julia Lawall8f47c282015-03-29 14:54:12 +02002089 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002090
2091 switch (name) {
2092 case IEEE_PARAM_WPA_ENABLED:
2093 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01002094 switch ((value) & 0xff) {
Larry Finger2865d422010-08-20 10:15:30 -05002095 case 1: /* WPA */
2096 padapter->securitypriv.ndisauthtype =
2097 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2098 padapter->securitypriv.ndisencryptstatus =
2099 Ndis802_11Encryption2Enabled;
2100 break;
2101 case 2: /* WPA2 */
2102 padapter->securitypriv.ndisauthtype =
2103 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2104 padapter->securitypriv.ndisencryptstatus =
2105 Ndis802_11Encryption3Enabled;
2106 break;
2107 }
2108 break;
2109 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2110 break;
2111 case IEEE_PARAM_DROP_UNENCRYPTED:
2112 /* HACK:
2113 *
2114 * wpa_supplicant calls set_wpa_enabled when the driver
2115 * is loaded and unloaded, regardless of if WPA is being
2116 * used. No other calls are made which can be used to
2117 * determine if encryption will be used or not prior to
2118 * association being expected. If encryption is not being
2119 * used, drop_unencrypted is set to false, else true -- we
2120 * can use this to determine if the CAP_PRIVACY_ON bit should
2121 * be set.
2122 */
2123 break;
2124 case IEEE_PARAM_PRIVACY_INVOKED:
2125 break;
2126 case IEEE_PARAM_AUTH_ALGS:
2127 return wpa_set_auth_algs(dev, value);
Larry Finger2865d422010-08-20 10:15:30 -05002128 case IEEE_PARAM_IEEE_802_1X:
2129 break;
2130 case IEEE_PARAM_WPAX_SELECT:
2131 /* added for WPA2 mixed mode */
2132 break;
2133 default:
2134 return -EOPNOTSUPP;
2135 }
2136 return 0;
2137}
2138
2139static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2140{
Julia Lawall8f47c282015-03-29 14:54:12 +02002141 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002142
2143 switch (command) {
2144 case IEEE_MLME_STA_DEAUTH:
2145 if (!r8712_set_802_11_disassociate(padapter))
2146 return -1;
2147 break;
2148 case IEEE_MLME_STA_DISASSOC:
2149 if (!r8712_set_802_11_disassociate(padapter))
2150 return -1;
2151 break;
2152 default:
2153 return -EOPNOTSUPP;
2154 }
2155 return 0;
2156}
2157
2158static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2159{
2160 struct ieee_param *param;
2161 int ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02002162 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002163
2164 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2165 return -EINVAL;
Vitaly Osipov91d435f2014-05-24 18:19:27 +10002166 param = memdup_user(p->pointer, p->length);
2167 if (IS_ERR(param))
2168 return PTR_ERR(param);
Larry Finger2865d422010-08-20 10:15:30 -05002169 switch (param->cmd) {
2170 case IEEE_CMD_SET_WPA_PARAM:
2171 ret = wpa_set_param(dev, param->u.wpa_param.name,
2172 param->u.wpa_param.value);
2173 break;
2174 case IEEE_CMD_SET_WPA_IE:
2175 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2176 (u16)param->u.wpa_ie.len);
2177 break;
2178 case IEEE_CMD_SET_ENCRYPTION:
2179 ret = wpa_set_encryption(dev, param, p->length);
2180 break;
2181 case IEEE_CMD_MLME:
2182 ret = wpa_mlme(dev, param->u.mlme.command,
2183 param->u.mlme.reason_code);
2184 break;
2185 default:
2186 ret = -EOPNOTSUPP;
2187 break;
2188 }
2189 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2190 ret = -EFAULT;
Tapasweni Pathak646da832014-10-08 20:41:26 +05302191 kfree(param);
Larry Finger2865d422010-08-20 10:15:30 -05002192 return ret;
2193}
2194
2195/* based on "driver_ipw" and for hostapd */
2196int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2197{
2198 struct iwreq *wrq = (struct iwreq *)rq;
2199
2200 switch (cmd) {
2201 case RTL_IOCTL_WPA_SUPPLICANT:
2202 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2203 default:
2204 return -EOPNOTSUPP;
2205 }
2206 return 0;
2207}
2208
2209static iw_handler r8711_handlers[] = {
2210 NULL, /* SIOCSIWCOMMIT */
2211 r8711_wx_get_name, /* SIOCGIWNAME */
2212 dummy, /* SIOCSIWNWID */
2213 dummy, /* SIOCGIWNWID */
2214 r8711_wx_set_freq, /* SIOCSIWFREQ */
2215 r8711_wx_get_freq, /* SIOCGIWFREQ */
2216 r8711_wx_set_mode, /* SIOCSIWMODE */
2217 r8711_wx_get_mode, /* SIOCGIWMODE */
2218 dummy, /* SIOCSIWSENS */
2219 r8711_wx_get_sens, /* SIOCGIWSENS */
2220 NULL, /* SIOCSIWRANGE */
2221 r8711_wx_get_range, /* SIOCGIWRANGE */
2222 r871x_wx_set_priv, /* SIOCSIWPRIV */
2223 NULL, /* SIOCGIWPRIV */
2224 NULL, /* SIOCSIWSTATS */
2225 NULL, /* SIOCGIWSTATS */
2226 dummy, /* SIOCSIWSPY */
2227 dummy, /* SIOCGIWSPY */
2228 NULL, /* SIOCGIWTHRSPY */
2229 NULL, /* SIOCWIWTHRSPY */
2230 r8711_wx_set_wap, /* SIOCSIWAP */
2231 r8711_wx_get_wap, /* SIOCGIWAP */
2232 r871x_wx_set_mlme, /* request MLME operation;
Punit Varad32c16d2015-10-14 23:55:54 +05302233 * uses struct iw_mlme
2234 */
Larry Finger2865d422010-08-20 10:15:30 -05002235 dummy, /* SIOCGIWAPLIST -- deprecated */
2236 r8711_wx_set_scan, /* SIOCSIWSCAN */
2237 r8711_wx_get_scan, /* SIOCGIWSCAN */
2238 r8711_wx_set_essid, /* SIOCSIWESSID */
2239 r8711_wx_get_essid, /* SIOCGIWESSID */
2240 dummy, /* SIOCSIWNICKN */
2241 r871x_wx_get_nick, /* SIOCGIWNICKN */
2242 NULL, /* -- hole -- */
2243 NULL, /* -- hole -- */
2244 r8711_wx_set_rate, /* SIOCSIWRATE */
2245 r8711_wx_get_rate, /* SIOCGIWRATE */
2246 dummy, /* SIOCSIWRTS */
2247 r8711_wx_get_rts, /* SIOCGIWRTS */
2248 r8711_wx_set_frag, /* SIOCSIWFRAG */
2249 r8711_wx_get_frag, /* SIOCGIWFRAG */
2250 dummy, /* SIOCSIWTXPOW */
2251 dummy, /* SIOCGIWTXPOW */
2252 dummy, /* SIOCSIWRETRY */
2253 r8711_wx_get_retry, /* SIOCGIWRETRY */
2254 r8711_wx_set_enc, /* SIOCSIWENCODE */
2255 r8711_wx_get_enc, /* SIOCGIWENCODE */
2256 dummy, /* SIOCSIWPOWER */
2257 r8711_wx_get_power, /* SIOCGIWPOWER */
2258 NULL, /*---hole---*/
2259 NULL, /*---hole---*/
2260 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2261 NULL, /* SIOCGIWGENIE */
2262 r871x_wx_set_auth, /* SIOCSIWAUTH */
2263 NULL, /* SIOCGIWAUTH */
2264 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2265 NULL, /* SIOCGIWENCODEEXT */
2266 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2267 NULL, /*---hole---*/
2268};
2269
2270static const struct iw_priv_args r8711_private_args[] = {
2271 {
2272 SIOCIWFIRSTPRIV + 0x0,
2273 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2274 },
2275 {
2276 SIOCIWFIRSTPRIV + 0x1,
2277 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2278 },
2279 {
2280 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2281 },
2282 {
2283 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2284 },
2285 {
2286 SIOCIWFIRSTPRIV + 0x4,
2287 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2288 },
2289 {
2290 SIOCIWFIRSTPRIV + 0x5,
2291 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2292 },
2293 {
2294 SIOCIWFIRSTPRIV + 0x6,
2295 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
Ali Baharc6dc0012011-09-04 03:14:20 +08002296 },
2297 {
2298 SIOCIWFIRSTPRIV + 0x7,
2299 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
Larry Finger2865d422010-08-20 10:15:30 -05002300 }
2301};
2302
2303static iw_handler r8711_private_handler[] = {
2304 r8711_wx_read32,
2305 r8711_wx_write32,
2306 r8711_drvext_hdl,
2307 r871x_mp_ioctl_hdl,
2308 r871x_get_ap_info, /*for MM DTV platform*/
2309 r871x_set_pid,
Ali Baharc6dc0012011-09-04 03:14:20 +08002310 r871x_wps_start,
2311 r871x_set_chplan
Larry Finger2865d422010-08-20 10:15:30 -05002312};
2313
2314static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2315{
Julia Lawall8f47c282015-03-29 14:54:12 +02002316 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002317 struct iw_statistics *piwstats = &padapter->iwstats;
2318 int tmp_level = 0;
2319 int tmp_qual = 0;
2320 int tmp_noise = 0;
2321
2322 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2323 piwstats->qual.qual = 0;
2324 piwstats->qual.level = 0;
2325 piwstats->qual.noise = 0;
2326 } else {
2327 /* show percentage, we need transfer dbm to orignal value. */
2328 tmp_level = padapter->recvpriv.fw_rssi;
2329 tmp_qual = padapter->recvpriv.signal;
2330 tmp_noise = padapter->recvpriv.noise;
2331 piwstats->qual.level = tmp_level;
Larry Fingerda3e6ec2012-02-26 22:08:36 -06002332 piwstats->qual.qual = tmp_qual;
Larry Finger2865d422010-08-20 10:15:30 -05002333 piwstats->qual.noise = tmp_noise;
2334 }
2335 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2336 return &padapter->iwstats;
2337}
2338
2339struct iw_handler_def r871x_handlers_def = {
2340 .standard = r8711_handlers,
Jim Cromieb330f602012-04-10 16:06:41 -06002341 .num_standard = ARRAY_SIZE(r8711_handlers),
Larry Finger2865d422010-08-20 10:15:30 -05002342 .private = r8711_private_handler,
2343 .private_args = (struct iw_priv_args *)r8711_private_args,
Jim Cromieb330f602012-04-10 16:06:41 -06002344 .num_private = ARRAY_SIZE(r8711_private_handler),
Larry Finger2865d422010-08-20 10:15:30 -05002345 .num_private_args = sizeof(r8711_private_args) /
2346 sizeof(struct iw_priv_args),
Ali Baharc6dc0012011-09-04 03:14:20 +08002347 .get_wireless_stats = r871x_get_wireless_stats
Larry Finger2865d422010-08-20 10:15:30 -05002348};