blob: 2d26f9a30fcf790fddc2d4ec0ff8b4e074fe5cf0 [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
Arnd Bergmann8c5af162016-02-17 09:32:58 +0100140static noinline_for_stack char *translate_scan(struct _adapter *padapter,
Larry Finger2865d422010-08-20 10:15:30 -0500141 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);
Jannik Becherca24e702016-12-20 18:59:46 +0100202 le16_to_cpus(&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;
Dan Carpenteraea48152016-01-30 17:41:10 +0300401 pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
Bhaktipriya Shridhar0b90c302016-03-21 02:10:21 +0530402 if (!pwep)
Larry Finger2865d422010-08-20 10:15:30 -0500403 return -ENOMEM;
Larry Finger2865d422010-08-20 10:15:30 -0500404 pwep->KeyLength = wep_key_len;
405 pwep->Length = wep_key_len +
406 FIELD_OFFSET(struct NDIS_802_11_WEP,
407 KeyMaterial);
408 if (wep_key_len == 13) {
409 padapter->securitypriv.PrivacyAlgrthm =
410 _WEP104_;
411 padapter->securitypriv.XGrpPrivacy =
412 _WEP104_;
413 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100414 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500415 return -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100416 }
Larry Finger2865d422010-08-20 10:15:30 -0500417 pwep->KeyIndex = wep_key_idx;
418 pwep->KeyIndex |= 0x80000000;
419 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
420 if (param->u.crypt.set_tx) {
421 if (r8712_set_802_11_add_wep(padapter, pwep) ==
422 (u8)_FAIL)
423 ret = -EOPNOTSUPP;
424 } else {
425 /* don't update "psecuritypriv->PrivacyAlgrthm" and
426 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
427 * r8712_set_key to fw/cam
428 */
429 if (wep_key_idx >= WEP_KEYS) {
430 ret = -EOPNOTSUPP;
431 goto exit;
432 }
433 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
434 skey[0]), pwep->KeyMaterial,
435 pwep->KeyLength);
436 psecuritypriv->DefKeylen[wep_key_idx] =
437 pwep->KeyLength;
438 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
439 }
440 goto exit;
441 }
442 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
443 struct sta_info *psta, *pbcmc_sta;
444 struct sta_priv *pstapriv = &padapter->stapriv;
445
446 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100447 WIFI_MP_STATE)) { /* sta mode */
Larry Finger2865d422010-08-20 10:15:30 -0500448 psta = r8712_get_stainfo(pstapriv,
449 get_bssid(pmlmepriv));
450 if (psta) {
451 psta->ieee8021x_blocked = false;
452 if ((padapter->securitypriv.ndisencryptstatus ==
453 Ndis802_11Encryption2Enabled) ||
454 (padapter->securitypriv.ndisencryptstatus ==
455 Ndis802_11Encryption3Enabled))
456 psta->XPrivacy = padapter->
457 securitypriv.PrivacyAlgrthm;
458 if (param->u.crypt.set_tx == 1)
459 handle_pairwise_key(psta, param,
460 padapter);
461 else /* group key */
462 handle_group_key(param, padapter);
463 }
464 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
465 if (pbcmc_sta) {
466 pbcmc_sta->ieee8021x_blocked = false;
467 if ((padapter->securitypriv.ndisencryptstatus ==
468 Ndis802_11Encryption2Enabled) ||
469 (padapter->securitypriv.ndisencryptstatus ==
470 Ndis802_11Encryption3Enabled))
471 pbcmc_sta->XPrivacy =
472 padapter->securitypriv.
473 PrivacyAlgrthm;
474 }
475 }
476 }
477exit:
Tapasweni Pathak646da832014-10-08 20:41:26 +0530478 kfree(pwep);
Larry Finger2865d422010-08-20 10:15:30 -0500479 return ret;
480}
481
482static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
483 unsigned short ielen)
484{
Sudip Mukherjeee29d3eb2014-10-27 17:42:25 +0530485 u8 *buf = NULL;
Larry Finger2865d422010-08-20 10:15:30 -0500486 int group_cipher = 0, pairwise_cipher = 0;
487 int ret = 0;
488
489 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
490 return -EINVAL;
491 if (ielen) {
Vitaly Osipov91d435f2014-05-24 18:19:27 +1000492 buf = kmemdup(pie, ielen, GFP_ATOMIC);
Larry Finger2865d422010-08-20 10:15:30 -0500493 if (buf == NULL)
494 return -ENOMEM;
Larry Finger2865d422010-08-20 10:15:30 -0500495 if (ielen < RSN_HEADER_LEN) {
Ali Bahar2192e602011-09-04 03:14:24 +0800496 ret = -EINVAL;
Larry Finger2865d422010-08-20 10:15:30 -0500497 goto exit;
498 }
499 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
500 &pairwise_cipher) == _SUCCESS) {
501 padapter->securitypriv.AuthAlgrthm = 2;
502 padapter->securitypriv.ndisauthtype =
503 Ndis802_11AuthModeWPAPSK;
504 }
505 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
506 &pairwise_cipher) == _SUCCESS) {
507 padapter->securitypriv.AuthAlgrthm = 2;
508 padapter->securitypriv.ndisauthtype =
509 Ndis802_11AuthModeWPA2PSK;
510 }
511 switch (group_cipher) {
512 case WPA_CIPHER_NONE:
513 padapter->securitypriv.XGrpPrivacy =
514 _NO_PRIVACY_;
515 padapter->securitypriv.ndisencryptstatus =
516 Ndis802_11EncryptionDisabled;
517 break;
518 case WPA_CIPHER_WEP40:
519 padapter->securitypriv.XGrpPrivacy = _WEP40_;
520 padapter->securitypriv.ndisencryptstatus =
521 Ndis802_11Encryption1Enabled;
522 break;
523 case WPA_CIPHER_TKIP:
524 padapter->securitypriv.XGrpPrivacy = _TKIP_;
525 padapter->securitypriv.ndisencryptstatus =
526 Ndis802_11Encryption2Enabled;
527 break;
528 case WPA_CIPHER_CCMP:
529 padapter->securitypriv.XGrpPrivacy = _AES_;
530 padapter->securitypriv.ndisencryptstatus =
531 Ndis802_11Encryption3Enabled;
532 break;
533 case WPA_CIPHER_WEP104:
534 padapter->securitypriv.XGrpPrivacy = _WEP104_;
535 padapter->securitypriv.ndisencryptstatus =
536 Ndis802_11Encryption1Enabled;
537 break;
538 }
539 switch (pairwise_cipher) {
540 case WPA_CIPHER_NONE:
541 padapter->securitypriv.PrivacyAlgrthm =
542 _NO_PRIVACY_;
543 padapter->securitypriv.ndisencryptstatus =
544 Ndis802_11EncryptionDisabled;
545 break;
546 case WPA_CIPHER_WEP40:
547 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
548 padapter->securitypriv.ndisencryptstatus =
549 Ndis802_11Encryption1Enabled;
550 break;
551 case WPA_CIPHER_TKIP:
552 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
553 padapter->securitypriv.ndisencryptstatus =
554 Ndis802_11Encryption2Enabled;
555 break;
556 case WPA_CIPHER_CCMP:
557 padapter->securitypriv.PrivacyAlgrthm = _AES_;
558 padapter->securitypriv.ndisencryptstatus =
559 Ndis802_11Encryption3Enabled;
560 break;
561 case WPA_CIPHER_WEP104:
562 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
563 padapter->securitypriv.ndisencryptstatus =
564 Ndis802_11Encryption1Enabled;
565 break;
566 }
567 padapter->securitypriv.wps_phase = false;
568 {/* set wps_ie */
569 u16 cnt = 0;
570 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
571
572 while (cnt < ielen) {
573 eid = buf[cnt];
574
575 if ((eid == _VENDOR_SPECIFIC_IE_) &&
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100576 (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
Przemo Firszt87a573a2012-12-10 23:21:21 +0000577 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
Larry Finger2865d422010-08-20 10:15:30 -0500578 padapter->securitypriv.wps_ie_len =
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100579 ((buf[cnt + 1] + 2) <
Larry Finger2865d422010-08-20 10:15:30 -0500580 (MAX_WPA_IE_LEN << 2)) ?
581 (buf[cnt + 1] + 2) :
582 (MAX_WPA_IE_LEN << 2);
583 memcpy(padapter->securitypriv.wps_ie,
584 &buf[cnt],
585 padapter->securitypriv.wps_ie_len);
586 padapter->securitypriv.wps_phase =
587 true;
Przemo Firszt87a573a2012-12-10 23:21:21 +0000588 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100589 cnt += buf[cnt + 1] + 2;
Larry Finger2865d422010-08-20 10:15:30 -0500590 break;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100591 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500592 cnt += buf[cnt + 1] + 2;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100593 }
Larry Finger2865d422010-08-20 10:15:30 -0500594 }
595 }
596 }
597exit:
598 kfree(buf);
599 return ret;
600}
601
602static int r8711_wx_get_name(struct net_device *dev,
603 struct iw_request_info *info,
604 union iwreq_data *wrqu, char *extra)
605{
Julia Lawall8f47c282015-03-29 14:54:12 +0200606 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500607 u32 ht_ielen = 0;
608 char *p;
609 u8 ht_cap = false;
610 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
Joshua Clayton44367872015-08-05 17:17:18 -0700611 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Joshua Claytondb55b162015-08-05 17:17:20 -0700612 u8 *prates;
Larry Finger2865d422010-08-20 10:15:30 -0500613
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100614 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
Larry Finger2865d422010-08-20 10:15:30 -0500615 true) {
616 /* parsing HT_CAP_IE */
617 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
618 &ht_ielen, pcur_bss->IELength - 12);
619 if (p && ht_ielen > 0)
620 ht_cap = true;
Joshua Clayton7fb539e2015-08-05 17:17:21 -0700621 prates = pcur_bss->rates;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100622 if (r8712_is_cckratesonly_included(prates)) {
623 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500624 snprintf(wrqu->name, IFNAMSIZ,
625 "IEEE 802.11bn");
626 else
627 snprintf(wrqu->name, IFNAMSIZ,
628 "IEEE 802.11b");
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100629 } else if (r8712_is_cckrates_included(prates)) {
630 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500631 snprintf(wrqu->name, IFNAMSIZ,
632 "IEEE 802.11bgn");
633 else
634 snprintf(wrqu->name, IFNAMSIZ,
635 "IEEE 802.11bg");
636 } else {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100637 if (ht_cap)
Larry Finger2865d422010-08-20 10:15:30 -0500638 snprintf(wrqu->name, IFNAMSIZ,
639 "IEEE 802.11gn");
640 else
641 snprintf(wrqu->name, IFNAMSIZ,
642 "IEEE 802.11g");
643 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100644 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500645 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100646 }
Larry Finger2865d422010-08-20 10:15:30 -0500647 return 0;
648}
649
650static const long frequency_list[] = {
651 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
652 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
653 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
654 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
655 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
656 5825
657};
658
659static int r8711_wx_set_freq(struct net_device *dev,
660 struct iw_request_info *info,
661 union iwreq_data *wrqu, char *extra)
662{
Julia Lawall8f47c282015-03-29 14:54:12 +0200663 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500664 struct iw_freq *fwrq = &wrqu->freq;
665 int rc = 0;
666
667/* If setting by frequency, convert to a channel */
668 if ((fwrq->e == 1) &&
669 (fwrq->m >= (int) 2.412e8) &&
670 (fwrq->m <= (int) 2.487e8)) {
671 int f = fwrq->m / 100000;
672 int c = 0;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530673
Larry Finger2865d422010-08-20 10:15:30 -0500674 while ((c < 14) && (f != frequency_list[c]))
675 c++;
676 fwrq->e = 0;
677 fwrq->m = c + 1;
678 }
679 /* Setting by channel number */
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100680 if ((fwrq->m > 14) || (fwrq->e > 0)) {
Larry Finger2865d422010-08-20 10:15:30 -0500681 rc = -EOPNOTSUPP;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100682 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500683 int channel = fwrq->m;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530684
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100685 if ((channel < 1) || (channel > 14)) {
Larry Finger2865d422010-08-20 10:15:30 -0500686 rc = -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +0100687 } else {
Larry Finger2865d422010-08-20 10:15:30 -0500688 /* Yes ! We can set it !!! */
689 padapter->registrypriv.channel = channel;
690 }
691 }
692 return rc;
693}
694
695static int r8711_wx_get_freq(struct net_device *dev,
696 struct iw_request_info *info,
697 union iwreq_data *wrqu, char *extra)
698{
Julia Lawall8f47c282015-03-29 14:54:12 +0200699 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500700 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -0700701 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -0500702
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100703 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
Larry Finger2865d422010-08-20 10:15:30 -0500704 wrqu->freq.m = ieee80211_wlan_frequencies[
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100705 pcur_bss->Configuration.DSConfig - 1] * 100000;
Larry Finger2865d422010-08-20 10:15:30 -0500706 wrqu->freq.e = 1;
707 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
Ali Bahar2192e602011-09-04 03:14:24 +0800708 } else {
709 return -ENOLINK;
710 }
Larry Finger2865d422010-08-20 10:15:30 -0500711 return 0;
712}
713
714static int r8711_wx_set_mode(struct net_device *dev,
715 struct iw_request_info *a,
716 union iwreq_data *wrqu, char *b)
717{
Julia Lawall8f47c282015-03-29 14:54:12 +0200718 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500719 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
720
721 switch (wrqu->mode) {
722 case IW_MODE_AUTO:
723 networkType = Ndis802_11AutoUnknown;
724 break;
725 case IW_MODE_ADHOC:
726 networkType = Ndis802_11IBSS;
727 break;
728 case IW_MODE_MASTER:
729 networkType = Ndis802_11APMode;
730 break;
731 case IW_MODE_INFRA:
732 networkType = Ndis802_11Infrastructure;
733 break;
734 default:
735 return -EINVAL;
736 }
737 if (Ndis802_11APMode == networkType)
738 r8712_setopmode_cmd(padapter, networkType);
739 else
740 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
Ali Bahar2192e602011-09-04 03:14:24 +0800741
742 r8712_set_802_11_infrastructure_mode(padapter, networkType);
Larry Finger2865d422010-08-20 10:15:30 -0500743 return 0;
744}
745
746static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
747 union iwreq_data *wrqu, char *b)
748{
Julia Lawall8f47c282015-03-29 14:54:12 +0200749 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500750 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
751
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100752 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
Larry Finger2865d422010-08-20 10:15:30 -0500753 wrqu->mode = IW_MODE_INFRA;
754 else if (check_fwstate(pmlmepriv,
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100755 WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
Larry Finger2865d422010-08-20 10:15:30 -0500756 wrqu->mode = IW_MODE_ADHOC;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100757 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
Larry Finger2865d422010-08-20 10:15:30 -0500758 wrqu->mode = IW_MODE_MASTER;
759 else
760 wrqu->mode = IW_MODE_AUTO;
761 return 0;
762}
763
764static int r871x_wx_set_pmkid(struct net_device *dev,
765 struct iw_request_info *a,
766 union iwreq_data *wrqu, char *extra)
767{
Julia Lawall8f47c282015-03-29 14:54:12 +0200768 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500769 struct security_priv *psecuritypriv = &padapter->securitypriv;
770 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
771 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
772 u8 strIssueBssid[ETH_ALEN] = {0x00};
773 u8 j, blInserted = false;
774 int intReturn = false;
775
776/*
Punit Varad32c16d2015-10-14 23:55:54 +0530777 * There are the BSSID information in the bssid.sa_data array.
778 * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
779 * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
780 * wpa_supplicant wants to add a PMKID/BSSID to driver.
781 * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
782 * remove a PMKID/BSSID from driver.
783 */
Larry Finger2865d422010-08-20 10:15:30 -0500784 if (pPMK == NULL)
785 return -EINVAL;
786 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
787 switch (pPMK->cmd) {
788 case IW_PMKSA_ADD:
789 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
790 return intReturn;
Dogukan Ergun07e9e612015-06-13 15:04:26 +0300791 intReturn = true;
Larry Finger2865d422010-08-20 10:15:30 -0500792 blInserted = false;
793 /* overwrite PMKID */
Thomas Cort77e73e82013-10-01 11:26:55 -0400794 for (j = 0; j < NUM_PMKID_CACHE; j++) {
Larry Finger2865d422010-08-20 10:15:30 -0500795 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
796 strIssueBssid, ETH_ALEN)) {
797 /* BSSID is matched, the same AP => rewrite
Punit Varad32c16d2015-10-14 23:55:54 +0530798 * with new PMKID.
799 */
Przemo Firszt87a573a2012-12-10 23:21:21 +0000800 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
801 __func__);
Larry Finger2865d422010-08-20 10:15:30 -0500802 memcpy(psecuritypriv->PMKIDList[j].PMKID,
803 pPMK->pmkid, IW_PMKID_LEN);
804 psecuritypriv->PMKIDList[j].bUsed = true;
805 psecuritypriv->PMKIDIndex = j + 1;
806 blInserted = true;
807 break;
808 }
809 }
810 if (!blInserted) {
811 /* Find a new entry */
Przemo Firszt87a573a2012-12-10 23:21:21 +0000812 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
813 __func__, psecuritypriv->PMKIDIndex);
Larry Finger2865d422010-08-20 10:15:30 -0500814 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
815 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
816 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
817 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
818 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
819 bUsed = true;
Thomas Cort77e73e82013-10-01 11:26:55 -0400820 psecuritypriv->PMKIDIndex++;
Larry Finger2865d422010-08-20 10:15:30 -0500821 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
822 psecuritypriv->PMKIDIndex = 0;
823 }
824 break;
825 case IW_PMKSA_REMOVE:
826 intReturn = true;
827 for (j = 0; j < NUM_PMKID_CACHE; j++) {
828 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
829 strIssueBssid, ETH_ALEN)) {
830 /* BSSID is matched, the same AP => Remove
Punit Varad32c16d2015-10-14 23:55:54 +0530831 * this PMKID information and reset it.
832 */
Aya Mahfouz22905b82015-03-04 09:00:02 +0200833 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
Larry Finger2865d422010-08-20 10:15:30 -0500834 psecuritypriv->PMKIDList[j].bUsed = false;
835 break;
836 }
837 }
838 break;
839 case IW_PMKSA_FLUSH:
840 memset(psecuritypriv->PMKIDList, 0,
841 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
842 psecuritypriv->PMKIDIndex = 0;
843 intReturn = true;
844 break;
845 default:
Przemo Firszt87a573a2012-12-10 23:21:21 +0000846 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -0500847 intReturn = false;
848 break;
849 }
850 return intReturn;
851}
852
853static int r8711_wx_get_sens(struct net_device *dev,
854 struct iw_request_info *info,
855 union iwreq_data *wrqu, char *extra)
856{
857 wrqu->sens.value = 0;
858 wrqu->sens.fixed = 0; /* no auto select */
859 wrqu->sens.disabled = 1;
860 return 0;
861}
862
863static int r8711_wx_get_range(struct net_device *dev,
864 struct iw_request_info *info,
865 union iwreq_data *wrqu, char *extra)
866{
867 struct iw_range *range = (struct iw_range *)extra;
868 u16 val;
869 int i;
870
871 wrqu->data.length = sizeof(*range);
872 memset(range, 0, sizeof(*range));
873 /* Let's try to keep this struct in the same order as in
874 * linux/include/wireless.h
875 */
876
877 /* TODO: See what values we can set, and remove the ones we can't
878 * set, or fill them with some default data.
879 */
880 /* ~5 Mb/s real (802.11b) */
881 range->throughput = 5 * 1000 * 1000;
882 /* TODO: 8711 sensitivity ? */
883 /* signal level threshold range */
884 /* percent values between 0 and 100. */
885 range->max_qual.qual = 100;
886 range->max_qual.level = 100;
887 range->max_qual.noise = 100;
888 range->max_qual.updated = 7; /* Updated all three */
889 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
Justin P. Mattockbe10ac22012-05-07 07:38:22 -0700890 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
Luis de Bethencourt681cd982015-10-11 14:16:57 +0100891 range->avg_qual.level = 0x100 - 78;
Larry Finger2865d422010-08-20 10:15:30 -0500892 range->avg_qual.noise = 0;
893 range->avg_qual.updated = 7; /* Updated all three */
894 range->num_bitrates = RATE_COUNT;
895 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
896 range->bitrate[i] = rtl8180_rates[i];
897 range->min_frag = MIN_FRAG_THRESHOLD;
898 range->max_frag = MAX_FRAG_THRESHOLD;
899 range->pm_capa = 0;
900 range->we_version_compiled = WIRELESS_EXT;
901 range->we_version_source = 16;
902 range->num_channels = 14;
903 for (i = 0, val = 0; i < 14; i++) {
904 /* Include only legal frequencies for some countries */
905 range->freq[val].i = i + 1;
906 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
907 range->freq[val].e = 1;
908 val++;
909 if (val == IW_MAX_FREQUENCIES)
910 break;
911 }
912 range->num_frequency = val;
913 range->enc_capa = IW_ENC_CAPA_WPA |
914 IW_ENC_CAPA_WPA2 |
915 IW_ENC_CAPA_CIPHER_TKIP |
916 IW_ENC_CAPA_CIPHER_CCMP;
917 return 0;
918}
919
Ali Baharc6dc0012011-09-04 03:14:20 +0800920static int r8711_wx_get_rate(struct net_device *dev,
921 struct iw_request_info *info,
922 union iwreq_data *wrqu, char *extra);
923
Larry Finger2865d422010-08-20 10:15:30 -0500924static int r871x_wx_set_priv(struct net_device *dev,
925 struct iw_request_info *info,
926 union iwreq_data *awrq,
927 char *extra)
928{
929 int ret = 0, len = 0;
930 char *ext;
Ali Baharc6dc0012011-09-04 03:14:20 +0800931 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -0500932 struct iw_point *dwrq = (struct iw_point *)awrq;
933
934 len = dwrq->length;
Vitaly Osipov91d435f2014-05-24 18:19:27 +1000935 ext = memdup_user(dwrq->pointer, len);
936 if (IS_ERR(ext))
937 return PTR_ERR(ext);
Ali Baharc6dc0012011-09-04 03:14:20 +0800938
Alison Schofield29b1b612015-10-06 14:40:58 -0700939 if (!strcasecmp(ext, "RSSI")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800940 /*Return received signal strength indicator in -db for */
941 /* current AP */
942 /*<ssid> Rssi xx */
943 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
944 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
945 /*static u8 xxxx; */
Luis de Bethencourt1ca96882015-10-19 18:14:29 +0100946 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800947 sprintf(ext, "%s rssi %d",
948 pcur_network->network.Ssid.Ssid,
949 /*(xxxx=xxxx+10) */
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +0100950 ((padapter->recvpriv.fw_rssi) >> 1) - 95
Ali Baharc6dc0012011-09-04 03:14:20 +0800951 /*pcur_network->network.Rssi */
952 );
953 } else {
954 sprintf(ext, "OK");
955 }
Alison Schofield29b1b612015-10-06 14:40:58 -0700956 } else if (!strcasecmp(ext, "LINKSPEED")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800957 /*Return link speed in MBPS */
958 /*LinkSpeed xx */
959 union iwreq_data wrqd;
960 int ret_inner;
961 int mbps;
962
963 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
Alison Schofield29b1b612015-10-06 14:40:58 -0700964 if (ret_inner != 0)
Ali Baharc6dc0012011-09-04 03:14:20 +0800965 mbps = 0;
966 else
967 mbps = wrqd.bitrate.value / 1000000;
968 sprintf(ext, "LINKSPEED %d", mbps);
Alison Schofield29b1b612015-10-06 14:40:58 -0700969 } else if (!strcasecmp(ext, "MACADDR")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800970 /*Return mac address of the station */
Andy Shevchenko87fa05e2013-07-10 17:27:21 +0300971 /* Macaddr = xx:xx:xx:xx:xx:xx */
972 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
Alison Schofield29b1b612015-10-06 14:40:58 -0700973 } else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800974 /*Set scan type to active */
975 /*OK if successful */
976 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530977
Ali Baharc6dc0012011-09-04 03:14:20 +0800978 pmlmepriv->passive_mode = 1;
979 sprintf(ext, "OK");
Alison Schofield29b1b612015-10-06 14:40:58 -0700980 } else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800981 /*Set scan type to passive */
982 /*OK if successful */
983 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +0530984
Ali Baharc6dc0012011-09-04 03:14:20 +0800985 pmlmepriv->passive_mode = 0;
986 sprintf(ext, "OK");
Alison Schofield29b1b612015-10-06 14:40:58 -0700987 } else if (!strncmp(ext, "DCE-E", 5)) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800988 /*Set scan type to passive */
989 /*OK if successful */
990 r8712_disconnectCtrlEx_cmd(padapter
991 , 1 /*u32 enableDrvCtrl */
992 , 5 /*u32 tryPktCnt */
993 , 100 /*u32 tryPktInterval */
994 , 5000 /*u32 firstStageTO */
995 );
996 sprintf(ext, "OK");
Alison Schofield29b1b612015-10-06 14:40:58 -0700997 } else if (!strncmp(ext, "DCE-D", 5)) {
Ali Baharc6dc0012011-09-04 03:14:20 +0800998 /*Set scan type to passive */
999 /*OK if successfu */
1000 r8712_disconnectCtrlEx_cmd(padapter
1001 , 0 /*u32 enableDrvCtrl */
1002 , 5 /*u32 tryPktCnt */
1003 , 100 /*u32 tryPktInterval */
1004 , 5000 /*u32 firstStageTO */
1005 );
1006 sprintf(ext, "OK");
1007 } else {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001008 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1009 __func__, ext);
Ali Baharc6dc0012011-09-04 03:14:20 +08001010 goto FREE_EXT;
1011 }
1012 if (copy_to_user(dwrq->pointer, ext,
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001013 min(dwrq->length, (__u16)(strlen(ext) + 1))))
Ali Baharc6dc0012011-09-04 03:14:20 +08001014 ret = -EFAULT;
1015
1016FREE_EXT:
Larry Finger2865d422010-08-20 10:15:30 -05001017 kfree(ext);
1018 return ret;
1019}
1020
1021/* set bssid flow
1022 * s1. set_802_11_infrastructure_mode()
1023 * s2. set_802_11_authentication_mode()
1024 * s3. set_802_11_encryption_mode()
1025 * s4. set_802_11_bssid()
Ali Bahard1661df2011-07-12 23:10:55 +08001026 *
1027 * This function intends to handle the Set AP command, which specifies the
1028 * MAC# of a preferred Access Point.
1029 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1030 *
Justin P. Mattockbe10ac22012-05-07 07:38:22 -07001031 * For this operation to succeed, there is no need for the interface to be up.
Ali Bahard1661df2011-07-12 23:10:55 +08001032 *
Larry Finger2865d422010-08-20 10:15:30 -05001033 */
1034static int r8711_wx_set_wap(struct net_device *dev,
1035 struct iw_request_info *info,
1036 union iwreq_data *awrq,
1037 char *extra)
1038{
1039 int ret = -EINPROGRESS;
Julia Lawall8f47c282015-03-29 14:54:12 +02001040 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001041 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1042 struct __queue *queue = &pmlmepriv->scanned_queue;
1043 struct sockaddr *temp = (struct sockaddr *)awrq;
1044 unsigned long irqL;
1045 struct list_head *phead;
1046 u8 *dst_bssid;
1047 struct wlan_network *pnetwork = NULL;
1048 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1049
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001050 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
Ali Bahar2192e602011-09-04 03:14:24 +08001051 return -EBUSY;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001052 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
Larry Finger2865d422010-08-20 10:15:30 -05001053 return ret;
1054 if (temp->sa_family != ARPHRD_ETHER)
1055 return -EINVAL;
1056 authmode = padapter->securitypriv.ndisauthtype;
1057 spin_lock_irqsave(&queue->lock, irqL);
James A Shackleforde99a4282014-06-24 22:52:39 -04001058 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001059 pmlmepriv->pscanned = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001060 while (1) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001061 if (end_of_queue_search(phead, pmlmepriv->pscanned))
Larry Finger2865d422010-08-20 10:15:30 -05001062 break;
Geliang Tangfcc2cf12016-04-05 09:58:04 +08001063 pnetwork = container_of(pmlmepriv->pscanned,
1064 struct wlan_network, list);
James A Shackleford849fb0a2014-06-24 22:52:38 -04001065 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
Larry Finger2865d422010-08-20 10:15:30 -05001066 dst_bssid = pnetwork->network.MacAddress;
1067 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
Ali Bahar2192e602011-09-04 03:14:24 +08001068 r8712_set_802_11_infrastructure_mode(padapter,
1069 pnetwork->network.InfrastructureMode);
Larry Finger2865d422010-08-20 10:15:30 -05001070 break;
1071 }
1072 }
1073 spin_unlock_irqrestore(&queue->lock, irqL);
1074 if (!ret) {
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001075 if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
Ali Bahar2192e602011-09-04 03:14:24 +08001076 ret = -ENOMEM;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001077 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001078 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1079 ret = -1;
1080 }
1081 }
1082 return ret;
1083}
1084
1085static int r8711_wx_get_wap(struct net_device *dev,
1086 struct iw_request_info *info,
1087 union iwreq_data *wrqu, char *extra)
1088{
Julia Lawall8f47c282015-03-29 14:54:12 +02001089 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001090 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -07001091 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -05001092
1093 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
Cyril Roelandt2df29e72012-12-11 01:20:48 +01001094 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1095 WIFI_AP_STATE))
Haneen Mohammede0e982b2015-03-16 18:41:31 +03001096 ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
Cyril Roelandt2df29e72012-12-11 01:20:48 +01001097 else
Aya Mahfouz22905b82015-03-04 09:00:02 +02001098 eth_zero_addr(wrqu->ap_addr.sa_data);
Larry Finger2865d422010-08-20 10:15:30 -05001099 return 0;
1100}
1101
1102static int r871x_wx_set_mlme(struct net_device *dev,
1103 struct iw_request_info *info,
1104 union iwreq_data *wrqu, char *extra)
1105{
1106 int ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02001107 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001108 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1109
1110 if (mlme == NULL)
1111 return -1;
Larry Finger2865d422010-08-20 10:15:30 -05001112 switch (mlme->cmd) {
1113 case IW_MLME_DEAUTH:
1114 if (!r8712_set_802_11_disassociate(padapter))
1115 ret = -1;
1116 break;
1117 case IW_MLME_DISASSOC:
1118 if (!r8712_set_802_11_disassociate(padapter))
1119 ret = -1;
1120 break;
1121 default:
1122 return -EOPNOTSUPP;
1123 }
1124 return ret;
1125}
1126
Ali Bahard1661df2011-07-12 23:10:55 +08001127/**
1128 *
1129 * This function intends to handle the Set Scan command.
1130 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1131 *
1132 * For this operation to succeed, the interface is brought Up beforehand.
1133 *
1134 */
Larry Finger2865d422010-08-20 10:15:30 -05001135static int r8711_wx_set_scan(struct net_device *dev,
1136 struct iw_request_info *a,
1137 union iwreq_data *wrqu, char *extra)
1138{
Julia Lawall8f47c282015-03-29 14:54:12 +02001139 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001140 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1141 u8 status = true;
1142
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001143 if (padapter->bDriverStopped) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001144 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1145 __func__, padapter->bDriverStopped);
Larry Finger2865d422010-08-20 10:15:30 -05001146 return -1;
1147 }
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001148 if (!padapter->bup)
Ali Bahar2192e602011-09-04 03:14:24 +08001149 return -ENETDOWN;
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001150 if (!padapter->hw_init_completed)
Larry Finger2865d422010-08-20 10:15:30 -05001151 return -1;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001152 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001153 (pmlmepriv->sitesurveyctrl.traffic_busy))
Larry Finger2865d422010-08-20 10:15:30 -05001154 return 0;
1155 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1156 struct iw_scan_req *req = (struct iw_scan_req *)extra;
Tapasweni Pathak02a29d22014-09-24 16:34:56 +05301157
Larry Finger2865d422010-08-20 10:15:30 -05001158 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1159 struct ndis_802_11_ssid ssid;
1160 unsigned long irqL;
Przemo Firszt0024a1e2012-12-10 23:21:22 +00001161 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
Tapasweni Pathak02a29d22014-09-24 16:34:56 +05301162
Larry Finger2865d422010-08-20 10:15:30 -05001163 memset((unsigned char *)&ssid, 0,
1164 sizeof(struct ndis_802_11_ssid));
1165 memcpy(ssid.Ssid, req->essid, len);
1166 ssid.SsidLength = len;
1167 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1168 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1169 _FW_UNDER_LINKING)) ||
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001170 (pmlmepriv->sitesurveyctrl.traffic_busy)) {
Larry Finger2865d422010-08-20 10:15:30 -05001171 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1172 status = false;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001173 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001174 status = r8712_sitesurvey_cmd(padapter, &ssid);
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001175 }
Larry Finger2865d422010-08-20 10:15:30 -05001176 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1177 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001178 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001179 status = r8712_set_802_11_bssid_list_scan(padapter);
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001180 }
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001181 if (!status)
Larry Finger2865d422010-08-20 10:15:30 -05001182 return -1;
1183 return 0;
1184}
1185
1186static int r8711_wx_get_scan(struct net_device *dev,
1187 struct iw_request_info *a,
1188 union iwreq_data *wrqu, char *extra)
1189{
Julia Lawall8f47c282015-03-29 14:54:12 +02001190 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001191 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1192 struct __queue *queue = &pmlmepriv->scanned_queue;
1193 struct wlan_network *pnetwork = NULL;
1194 unsigned long irqL;
1195 struct list_head *plist, *phead;
1196 char *ev = extra;
1197 char *stop = ev + wrqu->data.length;
1198 u32 ret = 0, cnt = 0;
1199
1200 if (padapter->bDriverStopped)
1201 return -EINVAL;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001202 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1203 _FW_UNDER_LINKING)) {
Larry Finger2865d422010-08-20 10:15:30 -05001204 msleep(30);
1205 cnt++;
Ali Baharc6dc0012011-09-04 03:14:20 +08001206 if (cnt > 100)
Larry Finger2865d422010-08-20 10:15:30 -05001207 break;
1208 }
1209 spin_lock_irqsave(&queue->lock, irqL);
James A Shackleforde99a4282014-06-24 22:52:39 -04001210 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001211 plist = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001212 while (1) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001213 if (end_of_queue_search(phead, plist))
Larry Finger2865d422010-08-20 10:15:30 -05001214 break;
1215 if ((stop - ev) < SCAN_ITEM_SIZE) {
1216 ret = -E2BIG;
1217 break;
1218 }
Geliang Tangfcc2cf12016-04-05 09:58:04 +08001219 pnetwork = container_of(plist, struct wlan_network, list);
Larry Finger2865d422010-08-20 10:15:30 -05001220 ev = translate_scan(padapter, a, pnetwork, ev, stop);
James A Shackleford849fb0a2014-06-24 22:52:38 -04001221 plist = plist->next;
Larry Finger2865d422010-08-20 10:15:30 -05001222 }
1223 spin_unlock_irqrestore(&queue->lock, irqL);
1224 wrqu->data.length = ev - extra;
1225 wrqu->data.flags = 0;
1226 return ret;
1227}
1228
1229/* set ssid flow
1230 * s1. set_802_11_infrastructure_mode()
1231 * s2. set_802_11_authenticaion_mode()
1232 * s3. set_802_11_encryption_mode()
1233 * s4. set_802_11_ssid()
Ali Bahard1661df2011-07-12 23:10:55 +08001234 *
1235 * This function intends to handle the Set ESSID command.
1236 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1237 *
1238 * For this operation to succeed, there is no need for the interface to be Up.
1239 *
Larry Finger2865d422010-08-20 10:15:30 -05001240 */
1241static int r8711_wx_set_essid(struct net_device *dev,
1242 struct iw_request_info *a,
1243 union iwreq_data *wrqu, char *extra)
1244{
Julia Lawall8f47c282015-03-29 14:54:12 +02001245 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001246 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1247 struct __queue *queue = &pmlmepriv->scanned_queue;
1248 struct wlan_network *pnetwork = NULL;
1249 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1250 struct ndis_802_11_ssid ndis_ssid;
1251 u8 *dst_ssid, *src_ssid;
1252 struct list_head *phead;
1253 u32 len;
1254
Larry Finger2865d422010-08-20 10:15:30 -05001255 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
Ali Bahar2192e602011-09-04 03:14:24 +08001256 return -EBUSY;
Larry Finger2865d422010-08-20 10:15:30 -05001257 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1258 return 0;
1259 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1260 return -E2BIG;
1261 authmode = padapter->securitypriv.ndisauthtype;
1262 if (wrqu->essid.flags && wrqu->essid.length) {
1263 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1264 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1265 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1266 ndis_ssid.SsidLength = len;
1267 memcpy(ndis_ssid.Ssid, extra, len);
1268 src_ssid = ndis_ssid.Ssid;
James A Shackleforde99a4282014-06-24 22:52:39 -04001269 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001270 pmlmepriv->pscanned = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001271 while (1) {
1272 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1273 break;
Geliang Tangfcc2cf12016-04-05 09:58:04 +08001274 pnetwork = container_of(pmlmepriv->pscanned,
1275 struct wlan_network, list);
James A Shackleford849fb0a2014-06-24 22:52:38 -04001276 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
Larry Finger2865d422010-08-20 10:15:30 -05001277 dst_ssid = pnetwork->network.Ssid.Ssid;
1278 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1279 && (pnetwork->network.Ssid.SsidLength ==
1280 ndis_ssid.SsidLength)) {
Ali Baharc6dc0012011-09-04 03:14:20 +08001281 if (check_fwstate(pmlmepriv,
1282 WIFI_ADHOC_STATE)) {
1283 if (pnetwork->network.
1284 InfrastructureMode
1285 !=
1286 padapter->mlmepriv.
1287 cur_network.network.
1288 InfrastructureMode)
1289 continue;
1290 }
1291
Ali Bahar2192e602011-09-04 03:14:24 +08001292 r8712_set_802_11_infrastructure_mode(
Larry Finger2865d422010-08-20 10:15:30 -05001293 padapter,
Ali Bahar2192e602011-09-04 03:14:24 +08001294 pnetwork->network.InfrastructureMode);
Larry Finger2865d422010-08-20 10:15:30 -05001295 break;
1296 }
1297 }
1298 r8712_set_802_11_authentication_mode(padapter, authmode);
1299 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1300 }
1301 return -EINPROGRESS;
1302}
1303
1304static int r8711_wx_get_essid(struct net_device *dev,
1305 struct iw_request_info *a,
1306 union iwreq_data *wrqu, char *extra)
1307{
Julia Lawall8f47c282015-03-29 14:54:12 +02001308 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001309 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -07001310 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -05001311 u32 len, ret = 0;
1312
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001313 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
Larry Finger2865d422010-08-20 10:15:30 -05001314 len = pcur_bss->Ssid.SsidLength;
1315 wrqu->essid.length = len;
1316 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1317 wrqu->essid.flags = 1;
Ali Bahar2192e602011-09-04 03:14:24 +08001318 } else {
1319 ret = -ENOLINK;
1320 }
Larry Finger2865d422010-08-20 10:15:30 -05001321 return ret;
1322}
1323
1324static int r8711_wx_set_rate(struct net_device *dev,
1325 struct iw_request_info *a,
1326 union iwreq_data *wrqu, char *extra)
1327{
Julia Lawall8f47c282015-03-29 14:54:12 +02001328 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001329 u32 target_rate = wrqu->bitrate.value;
1330 u32 fixed = wrqu->bitrate.fixed;
1331 u32 ratevalue = 0;
1332 u8 datarates[NumRates];
1333 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1334 int i, ret = 0;
1335
1336 if (target_rate == -1) {
1337 ratevalue = 11;
1338 goto set_rate;
1339 }
1340 target_rate = target_rate / 100000;
1341 switch (target_rate) {
1342 case 10:
1343 ratevalue = 0;
1344 break;
1345 case 20:
1346 ratevalue = 1;
1347 break;
1348 case 55:
1349 ratevalue = 2;
1350 break;
1351 case 60:
1352 ratevalue = 3;
1353 break;
1354 case 90:
1355 ratevalue = 4;
1356 break;
1357 case 110:
1358 ratevalue = 5;
1359 break;
1360 case 120:
1361 ratevalue = 6;
1362 break;
1363 case 180:
1364 ratevalue = 7;
1365 break;
1366 case 240:
1367 ratevalue = 8;
1368 break;
1369 case 360:
1370 ratevalue = 9;
1371 break;
1372 case 480:
1373 ratevalue = 10;
1374 break;
1375 case 540:
1376 ratevalue = 11;
1377 break;
1378 default:
1379 ratevalue = 11;
1380 break;
1381 }
1382set_rate:
1383 for (i = 0; i < NumRates; i++) {
1384 if (ratevalue == mpdatarate[i]) {
1385 datarates[i] = mpdatarate[i];
1386 if (fixed == 0)
1387 break;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001388 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001389 datarates[i] = 0xff;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001390 }
Larry Finger2865d422010-08-20 10:15:30 -05001391 }
1392 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
Ali Bahar2192e602011-09-04 03:14:24 +08001393 ret = -ENOMEM;
Larry Finger2865d422010-08-20 10:15:30 -05001394 return ret;
1395}
1396
1397static int r8711_wx_get_rate(struct net_device *dev,
1398 struct iw_request_info *info,
1399 union iwreq_data *wrqu, char *extra)
1400{
Julia Lawall8f47c282015-03-29 14:54:12 +02001401 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001402 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Joshua Clayton44367872015-08-05 17:17:18 -07001403 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
Larry Finger2865d422010-08-20 10:15:30 -05001404 struct ieee80211_ht_cap *pht_capie;
Ali Baharc6dc0012011-09-04 03:14:20 +08001405 unsigned char rf_type = padapter->registrypriv.rf_config;
Larry Finger2865d422010-08-20 10:15:30 -05001406 int i;
1407 u8 *p;
1408 u16 rate, max_rate = 0, ht_cap = false;
1409 u32 ht_ielen = 0;
1410 u8 bw_40MHz = 0, short_GI = 0;
1411 u16 mcs_rate = 0;
1412
1413 i = 0;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001414 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
Larry Finger2865d422010-08-20 10:15:30 -05001415 p = r8712_get_ie(&pcur_bss->IEs[12],
1416 _HT_CAPABILITY_IE_, &ht_ielen,
1417 pcur_bss->IELength - 12);
1418 if (p && ht_ielen > 0) {
1419 ht_cap = true;
1420 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
Max Perepelitsyn0636b462015-01-02 14:08:08 +06001421 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
Larry Finger2865d422010-08-20 10:15:30 -05001422 bw_40MHz = (pht_capie->cap_info &
1423 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1424 short_GI = (pht_capie->cap_info &
1425 (IEEE80211_HT_CAP_SGI_20 |
1426 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1427 }
Joshua Clayton7fb539e2015-08-05 17:17:21 -07001428 while ((pcur_bss->rates[i] != 0) &&
1429 (pcur_bss->rates[i] != 0xFF)) {
1430 rate = pcur_bss->rates[i] & 0x7F;
Larry Finger2865d422010-08-20 10:15:30 -05001431 if (rate > max_rate)
1432 max_rate = rate;
1433 wrqu->bitrate.fixed = 0; /* no auto select */
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001434 wrqu->bitrate.value = rate * 500000;
Larry Finger2865d422010-08-20 10:15:30 -05001435 i++;
1436 }
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001437 if (ht_cap) {
Ali Baharc6dc0012011-09-04 03:14:20 +08001438 if (mcs_rate & 0x8000 /* MCS15 */
1439 &&
Alison Schofield29b1b612015-10-06 14:40:58 -07001440 rf_type == RTL8712_RF_2T2R)
Larry Finger2865d422010-08-20 10:15:30 -05001441 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1442 270) : ((short_GI) ? 144 : 130);
Larry Finger2865d422010-08-20 10:15:30 -05001443 else /* default MCS7 */
1444 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1445 135) : ((short_GI) ? 72 : 65);
1446 max_rate *= 2; /* Mbps/2 */
Larry Finger2865d422010-08-20 10:15:30 -05001447 }
Rickard Strandqvist3ae70742014-06-15 19:20:58 +02001448 wrqu->bitrate.value = max_rate * 500000;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001449 } else {
Ali Bahar2192e602011-09-04 03:14:24 +08001450 return -ENOLINK;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001451 }
Larry Finger2865d422010-08-20 10:15:30 -05001452 return 0;
1453}
1454
1455static int r8711_wx_get_rts(struct net_device *dev,
1456 struct iw_request_info *info,
1457 union iwreq_data *wrqu, char *extra)
1458{
Julia Lawall8f47c282015-03-29 14:54:12 +02001459 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001460
1461 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1462 wrqu->rts.fixed = 0; /* no auto select */
1463 return 0;
1464}
1465
1466static int r8711_wx_set_frag(struct net_device *dev,
1467 struct iw_request_info *info,
1468 union iwreq_data *wrqu, char *extra)
1469{
Julia Lawall8f47c282015-03-29 14:54:12 +02001470 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001471
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001472 if (wrqu->frag.disabled) {
Larry Finger2865d422010-08-20 10:15:30 -05001473 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001474 } else {
Larry Finger2865d422010-08-20 10:15:30 -05001475 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1476 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1477 return -EINVAL;
1478 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1479 }
1480 return 0;
1481}
1482
1483static int r8711_wx_get_frag(struct net_device *dev,
1484 struct iw_request_info *info,
1485 union iwreq_data *wrqu, char *extra)
1486{
Julia Lawall8f47c282015-03-29 14:54:12 +02001487 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001488
1489 wrqu->frag.value = padapter->xmitpriv.frag_len;
1490 wrqu->frag.fixed = 0; /* no auto select */
1491 return 0;
1492}
1493
1494static int r8711_wx_get_retry(struct net_device *dev,
1495 struct iw_request_info *info,
1496 union iwreq_data *wrqu, char *extra)
1497{
1498 wrqu->retry.value = 7;
1499 wrqu->retry.fixed = 0; /* no auto select */
1500 wrqu->retry.disabled = 1;
1501 return 0;
1502}
1503
1504static int r8711_wx_set_enc(struct net_device *dev,
1505 struct iw_request_info *info,
1506 union iwreq_data *wrqu, char *keybuf)
1507{
1508 u32 key;
1509 u32 keyindex_provided;
1510 struct NDIS_802_11_WEP wep;
1511 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1512 struct iw_point *erq = &(wrqu->encoding);
Julia Lawall8f47c282015-03-29 14:54:12 +02001513 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001514
1515 key = erq->flags & IW_ENCODE_INDEX;
1516 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1517 if (erq->flags & IW_ENCODE_DISABLED) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001518 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -05001519 padapter->securitypriv.ndisencryptstatus =
1520 Ndis802_11EncryptionDisabled;
1521 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1522 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1523 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1524 authmode = Ndis802_11AuthModeOpen;
1525 padapter->securitypriv.ndisauthtype = authmode;
1526 return 0;
1527 }
1528 if (key) {
1529 if (key > WEP_KEYS)
1530 return -EINVAL;
1531 key--;
1532 keyindex_provided = 1;
1533 } else {
1534 keyindex_provided = 0;
1535 key = padapter->securitypriv.PrivacyKeyIndex;
1536 }
1537 /* set authentication mode */
1538 if (erq->flags & IW_ENCODE_OPEN) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001539 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -05001540 padapter->securitypriv.ndisencryptstatus =
1541 Ndis802_11Encryption1Enabled;
1542 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1543 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1544 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1545 authmode = Ndis802_11AuthModeOpen;
1546 padapter->securitypriv.ndisauthtype = authmode;
1547 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
Tapasweni Pathak57b66862014-09-21 06:42:21 +05301548 netdev_info(dev,
1549 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
Larry Finger2865d422010-08-20 10:15:30 -05001550 padapter->securitypriv.ndisencryptstatus =
1551 Ndis802_11Encryption1Enabled;
1552 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1553 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1554 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1555 authmode = Ndis802_11AuthModeShared;
1556 padapter->securitypriv.ndisauthtype = authmode;
1557 } else {
1558 padapter->securitypriv.ndisencryptstatus =
1559 Ndis802_11Encryption1Enabled;
1560 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1561 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1562 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1563 authmode = Ndis802_11AuthModeOpen;
1564 padapter->securitypriv.ndisauthtype = authmode;
1565 }
1566 wep.KeyIndex = key;
1567 if (erq->length > 0) {
1568 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1569 wep.Length = wep.KeyLength +
1570 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1571 } else {
Thomas Cort77e73e82013-10-01 11:26:55 -04001572 wep.KeyLength = 0;
Larry Finger2865d422010-08-20 10:15:30 -05001573 if (keyindex_provided == 1) { /* set key_id only, no given
Punit Varad32c16d2015-10-14 23:55:54 +05301574 * KeyMaterial(erq->length==0).
1575 */
Larry Finger2865d422010-08-20 10:15:30 -05001576 padapter->securitypriv.PrivacyKeyIndex = key;
1577 switch (padapter->securitypriv.DefKeylen[key]) {
1578 case 5:
1579 padapter->securitypriv.PrivacyAlgrthm =
1580 _WEP40_;
1581 break;
1582 case 13:
1583 padapter->securitypriv.PrivacyAlgrthm =
1584 _WEP104_;
1585 break;
1586 default:
1587 padapter->securitypriv.PrivacyAlgrthm =
1588 _NO_PRIVACY_;
1589 break;
1590 }
1591 return 0;
1592 }
1593 }
1594 wep.KeyIndex |= 0x80000000; /* transmit key */
1595 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1596 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1597 return -EOPNOTSUPP;
1598 return 0;
1599}
1600
1601static int r8711_wx_get_enc(struct net_device *dev,
1602 struct iw_request_info *info,
1603 union iwreq_data *wrqu, char *keybuf)
1604{
1605 uint key, ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02001606 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001607 struct iw_point *erq = &(wrqu->encoding);
1608 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1609
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001610 if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
Larry Finger2865d422010-08-20 10:15:30 -05001611 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1612 erq->length = 0;
1613 erq->flags |= IW_ENCODE_DISABLED;
1614 return 0;
1615 }
1616 }
1617 key = erq->flags & IW_ENCODE_INDEX;
1618 if (key) {
1619 if (key > WEP_KEYS)
1620 return -EINVAL;
1621 key--;
1622 } else {
1623 key = padapter->securitypriv.PrivacyKeyIndex;
1624 }
1625 erq->flags = key + 1;
1626 switch (padapter->securitypriv.ndisencryptstatus) {
1627 case Ndis802_11EncryptionNotSupported:
1628 case Ndis802_11EncryptionDisabled:
1629 erq->length = 0;
1630 erq->flags |= IW_ENCODE_DISABLED;
1631 break;
1632 case Ndis802_11Encryption1Enabled:
1633 erq->length = padapter->securitypriv.DefKeylen[key];
1634 if (erq->length) {
1635 memcpy(keybuf, padapter->securitypriv.DefKey[
1636 key].skey, padapter->securitypriv.
1637 DefKeylen[key]);
1638 erq->flags |= IW_ENCODE_ENABLED;
1639 if (padapter->securitypriv.ndisauthtype ==
1640 Ndis802_11AuthModeOpen)
1641 erq->flags |= IW_ENCODE_OPEN;
1642 else if (padapter->securitypriv.ndisauthtype ==
1643 Ndis802_11AuthModeShared)
1644 erq->flags |= IW_ENCODE_RESTRICTED;
1645 } else {
1646 erq->length = 0;
1647 erq->flags |= IW_ENCODE_DISABLED;
1648 }
1649 break;
1650 case Ndis802_11Encryption2Enabled:
1651 case Ndis802_11Encryption3Enabled:
1652 erq->length = 16;
1653 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1654 IW_ENCODE_NOKEY);
1655 break;
1656 default:
1657 erq->length = 0;
1658 erq->flags |= IW_ENCODE_DISABLED;
1659 break;
1660 }
1661 return ret;
1662}
1663
1664static int r8711_wx_get_power(struct net_device *dev,
1665 struct iw_request_info *info,
1666 union iwreq_data *wrqu, char *extra)
1667{
1668 wrqu->power.value = 0;
1669 wrqu->power.fixed = 0; /* no auto select */
1670 wrqu->power.disabled = 1;
1671 return 0;
1672}
1673
1674static int r871x_wx_set_gen_ie(struct net_device *dev,
1675 struct iw_request_info *info,
1676 union iwreq_data *wrqu, char *extra)
1677{
Julia Lawall8f47c282015-03-29 14:54:12 +02001678 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001679
1680 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1681}
1682
1683static int r871x_wx_set_auth(struct net_device *dev,
1684 struct iw_request_info *info,
1685 union iwreq_data *wrqu, char *extra)
1686{
Julia Lawall8f47c282015-03-29 14:54:12 +02001687 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001688 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1689 int paramid;
1690 int paramval;
1691 int ret = 0;
1692
1693 paramid = param->flags & IW_AUTH_INDEX;
1694 paramval = param->value;
1695 switch (paramid) {
1696 case IW_AUTH_WPA_VERSION:
1697 break;
1698 case IW_AUTH_CIPHER_PAIRWISE:
1699 break;
1700 case IW_AUTH_CIPHER_GROUP:
1701 break;
1702 case IW_AUTH_KEY_MGMT:
1703 /*
1704 * ??? does not use these parameters
1705 */
1706 break;
1707 case IW_AUTH_TKIP_COUNTERMEASURES:
1708 if (paramval) {
1709 /* wpa_supplicant is enabling tkip countermeasure. */
1710 padapter->securitypriv.btkip_countermeasure = true;
1711 } else {
1712 /* wpa_supplicant is disabling tkip countermeasure. */
1713 padapter->securitypriv.btkip_countermeasure = false;
1714 }
1715 break;
1716 case IW_AUTH_DROP_UNENCRYPTED:
1717 /* HACK:
1718 *
1719 * wpa_supplicant calls set_wpa_enabled when the driver
1720 * is loaded and unloaded, regardless of if WPA is being
1721 * used. No other calls are made which can be used to
1722 * determine if encryption will be used or not prior to
1723 * association being expected. If encryption is not being
1724 * used, drop_unencrypted is set to false, else true -- we
1725 * can use this to determine if the CAP_PRIVACY_ON bit should
1726 * be set.
1727 */
1728 if (padapter->securitypriv.ndisencryptstatus ==
1729 Ndis802_11Encryption1Enabled) {
1730 /* it means init value, or using wep,
1731 * ndisencryptstatus =
1732 * Ndis802_11Encryption1Enabled,
1733 * then it needn't reset it;
1734 */
1735 break;
1736 }
1737
1738 if (paramval) {
1739 padapter->securitypriv.ndisencryptstatus =
1740 Ndis802_11EncryptionDisabled;
1741 padapter->securitypriv.PrivacyAlgrthm =
1742 _NO_PRIVACY_;
1743 padapter->securitypriv.XGrpPrivacy =
1744 _NO_PRIVACY_;
1745 padapter->securitypriv.AuthAlgrthm = 0;
1746 padapter->securitypriv.ndisauthtype =
1747 Ndis802_11AuthModeOpen;
1748 }
1749 break;
1750 case IW_AUTH_80211_AUTH_ALG:
1751 ret = wpa_set_auth_algs(dev, (u32)paramval);
1752 break;
1753 case IW_AUTH_WPA_ENABLED:
1754 break;
1755 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1756 break;
1757 case IW_AUTH_PRIVACY_INVOKED:
1758 break;
1759 default:
1760 return -EOPNOTSUPP;
1761 }
1762
1763 return ret;
1764}
1765
1766static int r871x_wx_set_enc_ext(struct net_device *dev,
1767 struct iw_request_info *info,
1768 union iwreq_data *wrqu, char *extra)
1769{
1770 struct iw_point *pencoding = &wrqu->encoding;
1771 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1772 struct ieee_param *param = NULL;
1773 char *alg_name;
1774 u32 param_len;
1775 int ret = 0;
1776
Larry Finger2865d422010-08-20 10:15:30 -05001777 switch (pext->alg) {
1778 case IW_ENCODE_ALG_NONE:
1779 alg_name = "none";
1780 break;
1781 case IW_ENCODE_ALG_WEP:
1782 alg_name = "WEP";
1783 break;
1784 case IW_ENCODE_ALG_TKIP:
1785 alg_name = "TKIP";
1786 break;
1787 case IW_ENCODE_ALG_CCMP:
1788 alg_name = "CCMP";
1789 break;
1790 default:
Ali Bahar2192e602011-09-04 03:14:24 +08001791 return -EINVAL;
Larry Finger2865d422010-08-20 10:15:30 -05001792 }
Christian Engelmayer55d4f6c2014-05-07 21:36:48 +02001793
1794 param_len = sizeof(struct ieee_param) + pext->key_len;
Vitaly Osipov91d435f2014-05-24 18:19:27 +10001795 param = kzalloc(param_len, GFP_ATOMIC);
Bhaktipriya Shridhar0b90c302016-03-21 02:10:21 +05301796 if (!param)
Christian Engelmayer55d4f6c2014-05-07 21:36:48 +02001797 return -ENOMEM;
Christian Engelmayer55d4f6c2014-05-07 21:36:48 +02001798 param->cmd = IEEE_CMD_SET_ENCRYPTION;
Punit Varae904cc82015-10-14 23:55:52 +05301799 eth_broadcast_addr(param->sta_addr);
Larry Finger2865d422010-08-20 10:15:30 -05001800 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1801 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1802 param->u.crypt.set_tx = 0;
1803 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1804 param->u.crypt.set_tx = 1;
1805 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1806 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1807 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1808 if (pext->key_len) {
1809 param->u.crypt.key_len = pext->key_len;
1810 memcpy(param + 1, pext + 1, pext->key_len);
1811 }
1812 ret = wpa_set_encryption(dev, param, param_len);
Alexander Beregalov40083862011-03-26 20:18:14 +03001813 kfree(param);
Larry Finger2865d422010-08-20 10:15:30 -05001814 return ret;
1815}
1816
1817static int r871x_wx_get_nick(struct net_device *dev,
1818 struct iw_request_info *info,
1819 union iwreq_data *wrqu, char *extra)
1820{
1821 if (extra) {
1822 wrqu->data.length = 8;
1823 wrqu->data.flags = 1;
1824 memcpy(extra, "rtl_wifi", 8);
1825 }
1826 return 0;
1827}
1828
1829static int r8711_wx_read32(struct net_device *dev,
1830 struct iw_request_info *info,
1831 union iwreq_data *wrqu, char *keybuf)
1832{
Julia Lawall8f47c282015-03-29 14:54:12 +02001833 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001834 u32 addr;
1835 u32 data32;
1836
1837 get_user(addr, (u32 __user *)wrqu->data.pointer);
1838 data32 = r8712_read32(padapter, addr);
1839 put_user(data32, (u32 __user *)wrqu->data.pointer);
1840 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1841 wrqu->data.flags = data32 & 0xffff;
1842 get_user(addr, (u32 __user *)wrqu->data.pointer);
1843 return 0;
1844}
1845
1846static int r8711_wx_write32(struct net_device *dev,
1847 struct iw_request_info *info,
1848 union iwreq_data *wrqu, char *keybuf)
1849{
Julia Lawall8f47c282015-03-29 14:54:12 +02001850 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001851 u32 addr;
1852 u32 data32;
1853
1854 get_user(addr, (u32 __user *)wrqu->data.pointer);
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001855 data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
Larry Finger2865d422010-08-20 10:15:30 -05001856 r8712_write32(padapter, addr, data32);
1857 return 0;
1858}
1859
1860static int dummy(struct net_device *dev,
1861 struct iw_request_info *a,
1862 union iwreq_data *wrqu, char *b)
1863{
Ali Bahar2192e602011-09-04 03:14:24 +08001864 return -ENOSYS;
Larry Finger2865d422010-08-20 10:15:30 -05001865}
1866
1867static int r8711_drvext_hdl(struct net_device *dev,
1868 struct iw_request_info *info,
1869 union iwreq_data *wrqu, char *extra)
1870{
1871 return 0;
1872}
1873
1874static int r871x_mp_ioctl_hdl(struct net_device *dev,
1875 struct iw_request_info *info,
1876 union iwreq_data *wrqu, char *extra)
1877{
Julia Lawall8f47c282015-03-29 14:54:12 +02001878 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001879 struct iw_point *p = &wrqu->data;
1880 struct oid_par_priv oid_par;
1881 struct mp_ioctl_handler *phandler;
1882 struct mp_ioctl_param *poidparam;
1883 unsigned long BytesRead, BytesWritten, BytesNeeded;
Dan Carpenterb5eed732015-04-08 14:19:00 +03001884 u8 *pparmbuf, bset;
Larry Finger2865d422010-08-20 10:15:30 -05001885 u16 len;
1886 uint status;
1887 int ret = 0;
1888
Dan Carpenterb5eed732015-04-08 14:19:00 +03001889 if ((!p->length) || (!p->pointer))
1890 return -EINVAL;
1891
Larry Finger2865d422010-08-20 10:15:30 -05001892 bset = (u8)(p->flags & 0xFFFF);
1893 len = p->length;
Cristina Opriceana45de4322015-03-28 02:57:34 +02001894 pparmbuf = memdup_user(p->pointer, len);
Dan Carpenterb5eed732015-04-08 14:19:00 +03001895 if (IS_ERR(pparmbuf))
1896 return PTR_ERR(pparmbuf);
1897
Larry Finger2865d422010-08-20 10:15:30 -05001898 poidparam = (struct mp_ioctl_param *)pparmbuf;
1899 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1900 ret = -EINVAL;
1901 goto _r871x_mp_ioctl_hdl_exit;
1902 }
1903 phandler = mp_ioctl_hdl + poidparam->subcode;
1904 if ((phandler->paramsize != 0) &&
1905 (poidparam->len < phandler->paramsize)) {
1906 ret = -EINVAL;
1907 goto _r871x_mp_ioctl_hdl_exit;
1908 }
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001909 if (phandler->oid == 0 && phandler->handler) {
Larry Finger2865d422010-08-20 10:15:30 -05001910 status = phandler->handler(&oid_par);
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001911 } else if (phandler->handler) {
Larry Finger2865d422010-08-20 10:15:30 -05001912 oid_par.adapter_context = padapter;
1913 oid_par.oid = phandler->oid;
1914 oid_par.information_buf = poidparam->data;
1915 oid_par.information_buf_len = poidparam->len;
1916 oid_par.dbg = 0;
1917 BytesWritten = 0;
1918 BytesNeeded = 0;
1919 if (bset) {
1920 oid_par.bytes_rw = &BytesRead;
1921 oid_par.bytes_needed = &BytesNeeded;
1922 oid_par.type_of_oid = SET_OID;
1923 } else {
1924 oid_par.bytes_rw = &BytesWritten;
1925 oid_par.bytes_needed = &BytesNeeded;
1926 oid_par.type_of_oid = QUERY_OID;
1927 }
1928 status = phandler->handler(&oid_par);
1929 /* todo:check status, BytesNeeded, etc. */
1930 } else {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001931 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1932 __func__, poidparam->subcode, phandler->oid,
1933 phandler->handler);
Larry Finger2865d422010-08-20 10:15:30 -05001934 ret = -EFAULT;
1935 goto _r871x_mp_ioctl_hdl_exit;
1936 }
1937 if (bset == 0x00) { /* query info */
1938 if (copy_to_user(p->pointer, pparmbuf, len))
1939 ret = -EFAULT;
1940 }
1941 if (status) {
1942 ret = -EFAULT;
1943 goto _r871x_mp_ioctl_hdl_exit;
1944 }
1945_r871x_mp_ioctl_hdl_exit:
Ilia Mirkinb7977fa2011-03-13 00:29:08 -05001946 kfree(pparmbuf);
Larry Finger2865d422010-08-20 10:15:30 -05001947 return ret;
1948}
1949
1950static int r871x_get_ap_info(struct net_device *dev,
1951 struct iw_request_info *info,
1952 union iwreq_data *wrqu, char *extra)
1953{
Julia Lawall8f47c282015-03-29 14:54:12 +02001954 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05001955 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1956 struct __queue *queue = &pmlmepriv->scanned_queue;
1957 struct iw_point *pdata = &wrqu->data;
1958 struct wlan_network *pnetwork = NULL;
1959 u32 cnt = 0, wpa_ielen;
1960 unsigned long irqL;
1961 struct list_head *plist, *phead;
1962 unsigned char *pbuf;
1963 u8 bssid[ETH_ALEN];
Alan0c684232016-02-15 18:58:10 +00001964 char data[33];
Larry Finger2865d422010-08-20 10:15:30 -05001965
1966 if (padapter->bDriverStopped || (pdata == NULL))
1967 return -EINVAL;
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01001968 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1969 _FW_UNDER_LINKING)) {
Larry Finger2865d422010-08-20 10:15:30 -05001970 msleep(30);
1971 cnt++;
1972 if (cnt > 100)
1973 break;
1974 }
1975 pdata->flags = 0;
1976 if (pdata->length >= 32) {
1977 if (copy_from_user(data, pdata->pointer, 32))
1978 return -EINVAL;
Omri Arad12bc1d12016-09-12 21:02:25 +03001979 data[32] = 0;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001980 } else {
Omri Arad12bc1d12016-09-12 21:02:25 +03001981 return -EINVAL;
Luis de Bethencourt168a2c12015-10-19 18:15:29 +01001982 }
Larry Finger2865d422010-08-20 10:15:30 -05001983 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
James A Shackleforde99a4282014-06-24 22:52:39 -04001984 phead = &queue->queue;
James A Shackleford849fb0a2014-06-24 22:52:38 -04001985 plist = phead->next;
Larry Finger2865d422010-08-20 10:15:30 -05001986 while (1) {
Luis de Bethencourt1ca96882015-10-19 18:14:29 +01001987 if (end_of_queue_search(phead, plist))
Larry Finger2865d422010-08-20 10:15:30 -05001988 break;
Geliang Tangfcc2cf12016-04-05 09:58:04 +08001989 pnetwork = container_of(plist, struct wlan_network, list);
Andy Shevchenko3fe1be82015-10-01 16:18:07 +03001990 if (!mac_pton(data, bssid)) {
Przemo Firszt87a573a2012-12-10 23:21:21 +00001991 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
1992 (u8 *)data);
Larry Finger2865d422010-08-20 10:15:30 -05001993 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
Przemo Firszt87a573a2012-12-10 23:21:21 +00001994 irqL);
Larry Finger2865d422010-08-20 10:15:30 -05001995 return -EINVAL;
1996 }
Przemo Firszt87a573a2012-12-10 23:21:21 +00001997 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
Punit Varaa1b42be2015-10-14 23:55:53 +05301998 if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
Larry Finger2865d422010-08-20 10:15:30 -05001999 /* BSSID match, then check if supporting wpa/wpa2 */
2000 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01002001 &wpa_ielen, pnetwork->network.IELength - 12);
Larry Finger2865d422010-08-20 10:15:30 -05002002 if (pbuf && (wpa_ielen > 0)) {
2003 pdata->flags = 1;
2004 break;
2005 }
2006 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01002007 &wpa_ielen, pnetwork->network.IELength - 12);
Larry Finger2865d422010-08-20 10:15:30 -05002008 if (pbuf && (wpa_ielen > 0)) {
2009 pdata->flags = 2;
2010 break;
2011 }
2012 }
James A Shackleford849fb0a2014-06-24 22:52:38 -04002013 plist = plist->next;
Larry Finger2865d422010-08-20 10:15:30 -05002014 }
2015 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2016 if (pdata->length >= 34) {
2017 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2018 (u8 *)&pdata->flags, 1))
2019 return -EINVAL;
2020 }
2021 return 0;
2022}
2023
2024static int r871x_set_pid(struct net_device *dev,
2025 struct iw_request_info *info,
2026 union iwreq_data *wrqu, char *extra)
2027{
Julia Lawall8f47c282015-03-29 14:54:12 +02002028 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002029 struct iw_point *pdata = &wrqu->data;
2030
2031 if ((padapter->bDriverStopped) || (pdata == NULL))
2032 return -EINVAL;
2033 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2034 return -EINVAL;
2035 return 0;
2036}
2037
Ali Baharc6dc0012011-09-04 03:14:20 +08002038static int r871x_set_chplan(struct net_device *dev,
2039 struct iw_request_info *info,
2040 union iwreq_data *wrqu, char *extra)
2041{
2042 int ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02002043 struct _adapter *padapter = netdev_priv(dev);
Ali Baharc6dc0012011-09-04 03:14:20 +08002044 struct iw_point *pdata = &wrqu->data;
2045 int ch_plan = -1;
2046
2047 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2048 ret = -EINVAL;
2049 goto exit;
2050 }
2051 ch_plan = (int)*extra;
2052 r8712_set_chplan_cmd(padapter, ch_plan);
2053
2054exit:
2055
2056 return ret;
2057}
2058
Larry Finger2865d422010-08-20 10:15:30 -05002059static int r871x_wps_start(struct net_device *dev,
2060 struct iw_request_info *info,
2061 union iwreq_data *wrqu, char *extra)
2062{
Julia Lawall8f47c282015-03-29 14:54:12 +02002063 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002064 struct iw_point *pdata = &wrqu->data;
2065 u32 u32wps_start = 0;
Larry Finger2865d422010-08-20 10:15:30 -05002066
Larry Finger2865d422010-08-20 10:15:30 -05002067 if ((padapter->bDriverStopped) || (pdata == NULL))
2068 return -EINVAL;
Wei Yongjun605fba82012-10-08 08:43:45 +08002069 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2070 return -EFAULT;
Larry Finger2865d422010-08-20 10:15:30 -05002071 if (u32wps_start == 0)
2072 u32wps_start = *extra;
2073 if (u32wps_start == 1) /* WPS Start */
2074 padapter->ledpriv.LedControlHandler(padapter,
2075 LED_CTL_START_WPS);
2076 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2077 padapter->ledpriv.LedControlHandler(padapter,
2078 LED_CTL_STOP_WPS);
2079 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2080 padapter->ledpriv.LedControlHandler(padapter,
2081 LED_CTL_STOP_WPS_FAIL);
2082 return 0;
2083}
2084
2085static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2086{
Julia Lawall8f47c282015-03-29 14:54:12 +02002087 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002088
2089 switch (name) {
2090 case IEEE_PARAM_WPA_ENABLED:
2091 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
Luis de Bethencourt4ef2de52015-10-19 18:16:01 +01002092 switch ((value) & 0xff) {
Larry Finger2865d422010-08-20 10:15:30 -05002093 case 1: /* WPA */
2094 padapter->securitypriv.ndisauthtype =
2095 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2096 padapter->securitypriv.ndisencryptstatus =
2097 Ndis802_11Encryption2Enabled;
2098 break;
2099 case 2: /* WPA2 */
2100 padapter->securitypriv.ndisauthtype =
2101 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2102 padapter->securitypriv.ndisencryptstatus =
2103 Ndis802_11Encryption3Enabled;
2104 break;
2105 }
2106 break;
2107 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2108 break;
2109 case IEEE_PARAM_DROP_UNENCRYPTED:
2110 /* HACK:
2111 *
2112 * wpa_supplicant calls set_wpa_enabled when the driver
2113 * is loaded and unloaded, regardless of if WPA is being
2114 * used. No other calls are made which can be used to
2115 * determine if encryption will be used or not prior to
2116 * association being expected. If encryption is not being
2117 * used, drop_unencrypted is set to false, else true -- we
2118 * can use this to determine if the CAP_PRIVACY_ON bit should
2119 * be set.
2120 */
2121 break;
2122 case IEEE_PARAM_PRIVACY_INVOKED:
2123 break;
2124 case IEEE_PARAM_AUTH_ALGS:
2125 return wpa_set_auth_algs(dev, value);
Larry Finger2865d422010-08-20 10:15:30 -05002126 case IEEE_PARAM_IEEE_802_1X:
2127 break;
2128 case IEEE_PARAM_WPAX_SELECT:
2129 /* added for WPA2 mixed mode */
2130 break;
2131 default:
2132 return -EOPNOTSUPP;
2133 }
2134 return 0;
2135}
2136
2137static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2138{
Julia Lawall8f47c282015-03-29 14:54:12 +02002139 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002140
2141 switch (command) {
2142 case IEEE_MLME_STA_DEAUTH:
2143 if (!r8712_set_802_11_disassociate(padapter))
2144 return -1;
2145 break;
2146 case IEEE_MLME_STA_DISASSOC:
2147 if (!r8712_set_802_11_disassociate(padapter))
2148 return -1;
2149 break;
2150 default:
2151 return -EOPNOTSUPP;
2152 }
2153 return 0;
2154}
2155
2156static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2157{
2158 struct ieee_param *param;
2159 int ret = 0;
Julia Lawall8f47c282015-03-29 14:54:12 +02002160 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002161
2162 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2163 return -EINVAL;
Vitaly Osipov91d435f2014-05-24 18:19:27 +10002164 param = memdup_user(p->pointer, p->length);
2165 if (IS_ERR(param))
2166 return PTR_ERR(param);
Larry Finger2865d422010-08-20 10:15:30 -05002167 switch (param->cmd) {
2168 case IEEE_CMD_SET_WPA_PARAM:
2169 ret = wpa_set_param(dev, param->u.wpa_param.name,
2170 param->u.wpa_param.value);
2171 break;
2172 case IEEE_CMD_SET_WPA_IE:
2173 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2174 (u16)param->u.wpa_ie.len);
2175 break;
2176 case IEEE_CMD_SET_ENCRYPTION:
2177 ret = wpa_set_encryption(dev, param, p->length);
2178 break;
2179 case IEEE_CMD_MLME:
2180 ret = wpa_mlme(dev, param->u.mlme.command,
2181 param->u.mlme.reason_code);
2182 break;
2183 default:
2184 ret = -EOPNOTSUPP;
2185 break;
2186 }
2187 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2188 ret = -EFAULT;
Tapasweni Pathak646da832014-10-08 20:41:26 +05302189 kfree(param);
Larry Finger2865d422010-08-20 10:15:30 -05002190 return ret;
2191}
2192
2193/* based on "driver_ipw" and for hostapd */
2194int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2195{
2196 struct iwreq *wrq = (struct iwreq *)rq;
2197
2198 switch (cmd) {
2199 case RTL_IOCTL_WPA_SUPPLICANT:
2200 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2201 default:
2202 return -EOPNOTSUPP;
2203 }
2204 return 0;
2205}
2206
2207static iw_handler r8711_handlers[] = {
2208 NULL, /* SIOCSIWCOMMIT */
2209 r8711_wx_get_name, /* SIOCGIWNAME */
2210 dummy, /* SIOCSIWNWID */
2211 dummy, /* SIOCGIWNWID */
2212 r8711_wx_set_freq, /* SIOCSIWFREQ */
2213 r8711_wx_get_freq, /* SIOCGIWFREQ */
2214 r8711_wx_set_mode, /* SIOCSIWMODE */
2215 r8711_wx_get_mode, /* SIOCGIWMODE */
2216 dummy, /* SIOCSIWSENS */
2217 r8711_wx_get_sens, /* SIOCGIWSENS */
2218 NULL, /* SIOCSIWRANGE */
2219 r8711_wx_get_range, /* SIOCGIWRANGE */
2220 r871x_wx_set_priv, /* SIOCSIWPRIV */
2221 NULL, /* SIOCGIWPRIV */
2222 NULL, /* SIOCSIWSTATS */
2223 NULL, /* SIOCGIWSTATS */
2224 dummy, /* SIOCSIWSPY */
2225 dummy, /* SIOCGIWSPY */
2226 NULL, /* SIOCGIWTHRSPY */
2227 NULL, /* SIOCWIWTHRSPY */
2228 r8711_wx_set_wap, /* SIOCSIWAP */
2229 r8711_wx_get_wap, /* SIOCGIWAP */
2230 r871x_wx_set_mlme, /* request MLME operation;
Punit Varad32c16d2015-10-14 23:55:54 +05302231 * uses struct iw_mlme
2232 */
Larry Finger2865d422010-08-20 10:15:30 -05002233 dummy, /* SIOCGIWAPLIST -- deprecated */
2234 r8711_wx_set_scan, /* SIOCSIWSCAN */
2235 r8711_wx_get_scan, /* SIOCGIWSCAN */
2236 r8711_wx_set_essid, /* SIOCSIWESSID */
2237 r8711_wx_get_essid, /* SIOCGIWESSID */
2238 dummy, /* SIOCSIWNICKN */
2239 r871x_wx_get_nick, /* SIOCGIWNICKN */
2240 NULL, /* -- hole -- */
2241 NULL, /* -- hole -- */
2242 r8711_wx_set_rate, /* SIOCSIWRATE */
2243 r8711_wx_get_rate, /* SIOCGIWRATE */
2244 dummy, /* SIOCSIWRTS */
2245 r8711_wx_get_rts, /* SIOCGIWRTS */
2246 r8711_wx_set_frag, /* SIOCSIWFRAG */
2247 r8711_wx_get_frag, /* SIOCGIWFRAG */
2248 dummy, /* SIOCSIWTXPOW */
2249 dummy, /* SIOCGIWTXPOW */
2250 dummy, /* SIOCSIWRETRY */
2251 r8711_wx_get_retry, /* SIOCGIWRETRY */
2252 r8711_wx_set_enc, /* SIOCSIWENCODE */
2253 r8711_wx_get_enc, /* SIOCGIWENCODE */
2254 dummy, /* SIOCSIWPOWER */
2255 r8711_wx_get_power, /* SIOCGIWPOWER */
2256 NULL, /*---hole---*/
2257 NULL, /*---hole---*/
2258 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2259 NULL, /* SIOCGIWGENIE */
2260 r871x_wx_set_auth, /* SIOCSIWAUTH */
2261 NULL, /* SIOCGIWAUTH */
2262 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2263 NULL, /* SIOCGIWENCODEEXT */
2264 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2265 NULL, /*---hole---*/
2266};
2267
2268static const struct iw_priv_args r8711_private_args[] = {
2269 {
2270 SIOCIWFIRSTPRIV + 0x0,
2271 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2272 },
2273 {
2274 SIOCIWFIRSTPRIV + 0x1,
2275 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2276 },
2277 {
2278 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2279 },
2280 {
2281 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2282 },
2283 {
2284 SIOCIWFIRSTPRIV + 0x4,
2285 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2286 },
2287 {
2288 SIOCIWFIRSTPRIV + 0x5,
2289 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2290 },
2291 {
2292 SIOCIWFIRSTPRIV + 0x6,
2293 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
Ali Baharc6dc0012011-09-04 03:14:20 +08002294 },
2295 {
2296 SIOCIWFIRSTPRIV + 0x7,
2297 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
Larry Finger2865d422010-08-20 10:15:30 -05002298 }
2299};
2300
2301static iw_handler r8711_private_handler[] = {
2302 r8711_wx_read32,
2303 r8711_wx_write32,
2304 r8711_drvext_hdl,
2305 r871x_mp_ioctl_hdl,
2306 r871x_get_ap_info, /*for MM DTV platform*/
2307 r871x_set_pid,
Ali Baharc6dc0012011-09-04 03:14:20 +08002308 r871x_wps_start,
2309 r871x_set_chplan
Larry Finger2865d422010-08-20 10:15:30 -05002310};
2311
2312static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2313{
Julia Lawall8f47c282015-03-29 14:54:12 +02002314 struct _adapter *padapter = netdev_priv(dev);
Larry Finger2865d422010-08-20 10:15:30 -05002315 struct iw_statistics *piwstats = &padapter->iwstats;
2316 int tmp_level = 0;
2317 int tmp_qual = 0;
2318 int tmp_noise = 0;
2319
2320 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2321 piwstats->qual.qual = 0;
2322 piwstats->qual.level = 0;
2323 piwstats->qual.noise = 0;
2324 } else {
2325 /* show percentage, we need transfer dbm to orignal value. */
2326 tmp_level = padapter->recvpriv.fw_rssi;
2327 tmp_qual = padapter->recvpriv.signal;
2328 tmp_noise = padapter->recvpriv.noise;
2329 piwstats->qual.level = tmp_level;
Larry Fingerda3e6ec2012-02-26 22:08:36 -06002330 piwstats->qual.qual = tmp_qual;
Larry Finger2865d422010-08-20 10:15:30 -05002331 piwstats->qual.noise = tmp_noise;
2332 }
2333 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2334 return &padapter->iwstats;
2335}
2336
2337struct iw_handler_def r871x_handlers_def = {
2338 .standard = r8711_handlers,
Jim Cromieb330f602012-04-10 16:06:41 -06002339 .num_standard = ARRAY_SIZE(r8711_handlers),
Larry Finger2865d422010-08-20 10:15:30 -05002340 .private = r8711_private_handler,
2341 .private_args = (struct iw_priv_args *)r8711_private_args,
Jim Cromieb330f602012-04-10 16:06:41 -06002342 .num_private = ARRAY_SIZE(r8711_private_handler),
Larry Finger2865d422010-08-20 10:15:30 -05002343 .num_private_args = sizeof(r8711_private_args) /
2344 sizeof(struct iw_priv_args),
Ali Baharc6dc0012011-09-04 03:14:20 +08002345 .get_wireless_stats = r871x_get_wireless_stats
Larry Finger2865d422010-08-20 10:15:30 -05002346};