1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  * rtl871x_ioctl_linux.c
4  *
5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
6  * Linux device driver for RTL8192SU
7  *
8  * Modifications for inclusion into the Linux staging tree are
9  * Copyright(c) 2010 Larry Finger. All rights reserved.
10  *
11  * Contact information:
12  * WLAN FAE <wlanfae@realtek.com>
13  * Larry Finger <Larry.Finger@lwfinger.net>
14  *
15  ******************************************************************************/
16 
17 #define _RTL871X_IOCTL_LINUX_C_
18 #define _RTL871X_MP_IOCTL_C_
19 
20 #include "osdep_service.h"
21 #include "drv_types.h"
22 #include "wlan_bssdef.h"
23 #include "rtl871x_debug.h"
24 #include "wifi.h"
25 #include "rtl871x_mlme.h"
26 #include "rtl871x_ioctl.h"
27 #include "rtl871x_ioctl_set.h"
28 #include "rtl871x_mp_ioctl.h"
29 #include "mlme_osdep.h"
30 #include <linux/wireless.h>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/io.h>
34 #include <linux/semaphore.h>
35 #include <net/iw_handler.h>
36 #include <linux/if_arp.h>
37 #include <linux/etherdevice.h>
38 
39 
40 #define RTL_IOCTL_WPA_SUPPLICANT	(SIOCIWFIRSTPRIV + 0x1E)
41 
42 #define SCAN_ITEM_SIZE 768
43 #define MAX_CUSTOM_LEN 64
44 #define RATE_COUNT 4
45 
46 
47 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
48 		       6000000, 9000000, 12000000, 18000000,
49 		       24000000, 36000000, 48000000, 54000000};
50 
51 static const long ieee80211_wlan_frequencies[] = {
52 	2412, 2417, 2422, 2427,
53 	2432, 2437, 2442, 2447,
54 	2452, 2457, 2462, 2467,
55 	2472, 2484
56 };
57 
58 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
59 {
60 	union iwreq_data wrqu;
61 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
62 
63 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
64 	memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
65 		ETH_ALEN);
66 	wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
67 }
68 
69 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
70 {
71 	union iwreq_data wrqu;
72 
73 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
74 	eth_zero_addr(wrqu.ap_addr.sa_data);
75 	wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
76 }
77 
78 static inline void handle_pairwise_key(struct sta_info *psta,
79 				       struct ieee_param *param,
80 				       struct _adapter *padapter)
81 {
82 	/* pairwise key */
83 	memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
84 	       (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
85 	if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
86 		memcpy(psta->tkiptxmickey. skey,
87 		       &(param->u.crypt.key[16]), 8);
88 		memcpy(psta->tkiprxmickey. skey,
89 		       &(param->u.crypt.key[24]), 8);
90 		padapter->securitypriv. busetkipkey = false;
91 		mod_timer(&padapter->securitypriv.tkip_timer,
92 			  jiffies + msecs_to_jiffies(50));
93 	}
94 	r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
95 }
96 
97 static inline void handle_group_key(struct ieee_param *param,
98 				    struct _adapter *padapter)
99 {
100 	union Keytype *gk = padapter->securitypriv.XGrpKey;
101 	union Keytype *gtk = padapter->securitypriv.XGrptxmickey;
102 	union Keytype *grk = padapter->securitypriv.XGrprxmickey;
103 
104 	if (param->u.crypt.idx > 0 &&
105 	    param->u.crypt.idx < 3) {
106 		/* group key idx is 1 or 2 */
107 		memcpy(gk[param->u.crypt.idx - 1].skey,
108 		       param->u.crypt.key,
109 		       (param->u.crypt.key_len > 16 ? 16 :
110 			param->u.crypt.key_len));
111 		memcpy(gtk[param->u.crypt.idx - 1].skey,
112 		       &param->u.crypt.key[16], 8);
113 		memcpy(grk[param->u.crypt.idx - 1].skey,
114 		       &param->u.crypt.key[24], 8);
115 		padapter->securitypriv.binstallGrpkey = true;
116 		r8712_set_key(padapter, &padapter->securitypriv,
117 			param->u.crypt.idx);
118 		if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
119 			if (padapter->registrypriv.power_mgnt !=
120 			    padapter->pwrctrlpriv.pwr_mode)
121 				mod_timer(&padapter->mlmepriv.dhcp_timer,
122 					  jiffies + msecs_to_jiffies(60000));
123 		}
124 	}
125 }
126 
127 static noinline_for_stack char *translate_scan(struct _adapter *padapter,
128 				   struct iw_request_info *info,
129 				   struct wlan_network *pnetwork,
130 				   char *start, char *stop)
131 {
132 	struct iw_event iwe;
133 	struct ieee80211_ht_cap *pht_capie;
134 	char *current_val;
135 	s8 *p;
136 	u32 i = 0, ht_ielen = 0;
137 	u16	cap, ht_cap = false, mcs_rate;
138 	u8 rssi;
139 
140 	if ((pnetwork->network.Configuration.DSConfig < 1) ||
141 	    (pnetwork->network.Configuration.DSConfig > 14)) {
142 		if (pnetwork->network.Configuration.DSConfig < 1)
143 			pnetwork->network.Configuration.DSConfig = 1;
144 		else
145 			pnetwork->network.Configuration.DSConfig = 14;
146 	}
147 	/* AP MAC address */
148 	iwe.cmd = SIOCGIWAP;
149 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
150 	ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
151 	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
152 	/* Add the ESSID */
153 	iwe.cmd = SIOCGIWESSID;
154 	iwe.u.data.flags = 1;
155 	iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
156 	start = iwe_stream_add_point(info, start, stop, &iwe,
157 				     pnetwork->network.Ssid.Ssid);
158 	/* parsing HT_CAP_IE */
159 	p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
160 			 &ht_ielen, pnetwork->network.IELength - 12);
161 	if (p && ht_ielen > 0) {
162 		ht_cap = true;
163 		pht_capie = (struct ieee80211_ht_cap *)(p + 2);
164 		memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
165 	}
166 	/* Add the protocol name */
167 	iwe.cmd = SIOCGIWNAME;
168 	if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
169 		if (ht_cap)
170 			snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
171 		else
172 			snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
173 	} else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
174 		if (ht_cap)
175 			snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
176 		else
177 			snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
178 	} else {
179 		if (ht_cap)
180 			snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
181 		else
182 			snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
183 	}
184 	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
185 	/* Add mode */
186 	iwe.cmd = SIOCGIWMODE;
187 	memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
188 		2);
189 	le16_to_cpus(&cap);
190 	if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
191 		if (cap & WLAN_CAPABILITY_BSS)
192 			iwe.u.mode = (u32)IW_MODE_MASTER;
193 		else
194 			iwe.u.mode = (u32)IW_MODE_ADHOC;
195 		start = iwe_stream_add_event(info, start, stop, &iwe,
196 			IW_EV_UINT_LEN);
197 	}
198 	/* Add frequency/channel */
199 	iwe.cmd = SIOCGIWFREQ;
200 	{
201 		/*  check legal index */
202 		u8 dsconfig = pnetwork->network.Configuration.DSConfig;
203 
204 		if (dsconfig >= 1 && dsconfig <= sizeof(
205 		    ieee80211_wlan_frequencies) / sizeof(long))
206 			iwe.u.freq.m =
207 				(s32)(ieee80211_wlan_frequencies
208 				      [dsconfig - 1] * 100000);
209 		else
210 			iwe.u.freq.m = 0;
211 	}
212 	iwe.u.freq.e = (s16)1;
213 	iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
214 	start = iwe_stream_add_event(info, start, stop, &iwe,
215 		IW_EV_FREQ_LEN);
216 	/* Add encryption capability */
217 	iwe.cmd = SIOCGIWENCODE;
218 	if (cap & WLAN_CAPABILITY_PRIVACY)
219 		iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
220 				    IW_ENCODE_NOKEY);
221 	else
222 		iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
223 	iwe.u.data.length = (u16)0;
224 	start = iwe_stream_add_point(info, start, stop, &iwe,
225 		pnetwork->network.Ssid.Ssid);
226 	/*Add basic and extended rates */
227 	current_val = start + iwe_stream_lcp_len(info);
228 	iwe.cmd = SIOCGIWRATE;
229 	iwe.u.bitrate.fixed = 0;
230 	iwe.u.bitrate.disabled = 0;
231 	iwe.u.bitrate.value = 0;
232 	i = 0;
233 	while (pnetwork->network.rates[i] != 0) {
234 		/* Bit rate given in 500 kb/s units */
235 		iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
236 				      0x7F) * 500000;
237 		current_val = iwe_stream_add_value(info, start, current_val,
238 			      stop, &iwe, IW_EV_PARAM_LEN);
239 	}
240 	/* Check if we added any event */
241 	if ((current_val - start) > iwe_stream_lcp_len(info))
242 		start = current_val;
243 	/* parsing WPA/WPA2 IE */
244 	{
245 		u8 buf[MAX_WPA_IE_LEN];
246 		u8 wpa_ie[255], rsn_ie[255];
247 		u16 wpa_len = 0, rsn_len = 0;
248 		int n;
249 
250 		r8712_get_sec_ie(pnetwork->network.IEs,
251 				 pnetwork->network.IELength, rsn_ie, &rsn_len,
252 				 wpa_ie, &wpa_len);
253 		if (wpa_len > 0) {
254 			memset(buf, 0, MAX_WPA_IE_LEN);
255 			n = sprintf(buf, "wpa_ie=");
256 			for (i = 0; i < wpa_len; i++) {
257 				n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
258 							"%02x", wpa_ie[i]);
259 				if (n >= MAX_WPA_IE_LEN)
260 					break;
261 			}
262 			memset(&iwe, 0, sizeof(iwe));
263 			iwe.cmd = IWEVCUSTOM;
264 			iwe.u.data.length = (u16)strlen(buf);
265 			start = iwe_stream_add_point(info, start, stop,
266 				&iwe, buf);
267 			memset(&iwe, 0, sizeof(iwe));
268 			iwe.cmd = IWEVGENIE;
269 			iwe.u.data.length = (u16)wpa_len;
270 			start = iwe_stream_add_point(info, start, stop,
271 				&iwe, wpa_ie);
272 		}
273 		if (rsn_len > 0) {
274 			memset(buf, 0, MAX_WPA_IE_LEN);
275 			n = sprintf(buf, "rsn_ie=");
276 			for (i = 0; i < rsn_len; i++) {
277 				n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
278 							"%02x", rsn_ie[i]);
279 				if (n >= MAX_WPA_IE_LEN)
280 					break;
281 			}
282 			memset(&iwe, 0, sizeof(iwe));
283 			iwe.cmd = IWEVCUSTOM;
284 			iwe.u.data.length = strlen(buf);
285 			start = iwe_stream_add_point(info, start, stop,
286 				&iwe, buf);
287 			memset(&iwe, 0, sizeof(iwe));
288 			iwe.cmd = IWEVGENIE;
289 			iwe.u.data.length = rsn_len;
290 			start = iwe_stream_add_point(info, start, stop, &iwe,
291 				rsn_ie);
292 		}
293 	}
294 
295 	{ /* parsing WPS IE */
296 		u8 wps_ie[512];
297 		uint wps_ielen;
298 
299 		if (r8712_get_wps_ie(pnetwork->network.IEs,
300 		    pnetwork->network.IELength,
301 		    wps_ie, &wps_ielen)) {
302 			if (wps_ielen > 2) {
303 				iwe.cmd = IWEVGENIE;
304 				iwe.u.data.length = (u16)wps_ielen;
305 				start = iwe_stream_add_point(info, start, stop,
306 					&iwe, wps_ie);
307 			}
308 		}
309 	}
310 	/* Add quality statistics */
311 	iwe.cmd = IWEVQUAL;
312 	rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
313 	/* we only update signal_level (signal strength) that is rssi. */
314 	iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
315 				  IW_QUAL_NOISE_INVALID);
316 	iwe.u.qual.level = rssi;  /* signal strength */
317 	iwe.u.qual.qual = 0; /* signal quality */
318 	iwe.u.qual.noise = 0; /* noise level */
319 	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
320 	/* how to translate rssi to ?% */
321 	return start;
322 }
323 
324 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
325 {
326 	struct _adapter *padapter = netdev_priv(dev);
327 	int ret = 0;
328 
329 	if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
330 		padapter->securitypriv.ndisencryptstatus =
331 						 Ndis802_11Encryption1Enabled;
332 		padapter->securitypriv.ndisauthtype =
333 						 Ndis802_11AuthModeAutoSwitch;
334 		padapter->securitypriv.AuthAlgrthm = 3;
335 	} else if (value & AUTH_ALG_SHARED_KEY) {
336 		padapter->securitypriv.ndisencryptstatus =
337 						 Ndis802_11Encryption1Enabled;
338 		padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
339 		padapter->securitypriv.AuthAlgrthm = 1;
340 	} else if (value & AUTH_ALG_OPEN_SYSTEM) {
341 		if (padapter->securitypriv.ndisauthtype <
342 						 Ndis802_11AuthModeWPAPSK) {
343 			padapter->securitypriv.ndisauthtype =
344 						 Ndis802_11AuthModeOpen;
345 			padapter->securitypriv.AuthAlgrthm = 0;
346 		}
347 	} else {
348 		ret = -EINVAL;
349 	}
350 	return ret;
351 }
352 
353 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
354 			      u32 param_len)
355 {
356 	int ret = 0;
357 	u32 wep_key_idx, wep_key_len = 0;
358 	struct NDIS_802_11_WEP	 *pwep = NULL;
359 	struct _adapter *padapter = netdev_priv(dev);
360 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
361 	struct security_priv *psecuritypriv = &padapter->securitypriv;
362 
363 	param->u.crypt.err = 0;
364 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
365 	if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
366 			 param->u.crypt.key_len)
367 		return -EINVAL;
368 	if (!is_broadcast_ether_addr(param->sta_addr))
369 		return -EINVAL;
370 
371 	if (param->u.crypt.idx >= WEP_KEYS) {
372 		/* for large key indices, set the default (0) */
373 		param->u.crypt.idx = 0;
374 	}
375 	if (strcmp(param->u.crypt.alg, "WEP") == 0) {
376 		netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
377 		padapter->securitypriv.ndisencryptstatus =
378 			     Ndis802_11Encryption1Enabled;
379 		padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
380 		padapter->securitypriv.XGrpPrivacy = _WEP40_;
381 		wep_key_idx = param->u.crypt.idx;
382 		wep_key_len = param->u.crypt.key_len;
383 		if (wep_key_idx >= WEP_KEYS)
384 			wep_key_idx = 0;
385 		if (wep_key_len <= 0)
386 			return -EINVAL;
387 
388 		wep_key_len = wep_key_len <= 5 ? 5 : 13;
389 		pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
390 		if (!pwep)
391 			return -ENOMEM;
392 		pwep->KeyLength = wep_key_len;
393 		pwep->Length = wep_key_len +
394 			FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
395 		if (wep_key_len == 13) {
396 			padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
397 			padapter->securitypriv.XGrpPrivacy = _WEP104_;
398 		}
399 		pwep->KeyIndex = wep_key_idx;
400 		pwep->KeyIndex |= 0x80000000;
401 		memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
402 		if (param->u.crypt.set_tx) {
403 			if (r8712_set_802_11_add_wep(padapter, pwep) ==
404 			    (u8)_FAIL)
405 				ret = -EOPNOTSUPP;
406 		} else {
407 			/* don't update "psecuritypriv->PrivacyAlgrthm" and
408 			 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
409 			 * r8712_set_key to fw/cam
410 			 */
411 			if (wep_key_idx >= WEP_KEYS) {
412 				ret = -EOPNOTSUPP;
413 				goto exit;
414 			}
415 			memcpy(&psecuritypriv->DefKey[wep_key_idx].skey[0],
416 			       pwep->KeyMaterial,
417 			       pwep->KeyLength);
418 			psecuritypriv->DefKeylen[wep_key_idx] =
419 				pwep->KeyLength;
420 			r8712_set_key(padapter, psecuritypriv, wep_key_idx);
421 		}
422 		goto exit;
423 	}
424 	if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
425 		struct sta_info *psta, *pbcmc_sta;
426 		struct sta_priv *pstapriv = &padapter->stapriv;
427 		struct security_priv *spriv = &padapter->securitypriv;
428 
429 		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
430 		    WIFI_MP_STATE)) { /* sta mode */
431 			psta = r8712_get_stainfo(pstapriv,
432 						 get_bssid(pmlmepriv));
433 			if (psta) {
434 				psta->ieee8021x_blocked = false;
435 				if (spriv->ndisencryptstatus ==
436 				    Ndis802_11Encryption2Enabled ||
437 				    spriv->ndisencryptstatus ==
438 				    Ndis802_11Encryption3Enabled)
439 					psta->XPrivacy = spriv->PrivacyAlgrthm;
440 				if (param->u.crypt.set_tx == 1)
441 					handle_pairwise_key(psta, param,
442 							    padapter);
443 				else /* group key */
444 					handle_group_key(param, padapter);
445 			}
446 			pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
447 			if (pbcmc_sta) {
448 				pbcmc_sta->ieee8021x_blocked = false;
449 				if (spriv->ndisencryptstatus ==
450 				    Ndis802_11Encryption2Enabled ||
451 				    spriv->ndisencryptstatus ==
452 				    Ndis802_11Encryption3Enabled)
453 					pbcmc_sta->XPrivacy =
454 						spriv->PrivacyAlgrthm;
455 			}
456 		}
457 	}
458 exit:
459 	kfree(pwep);
460 	return ret;
461 }
462 
463 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
464 			    unsigned short ielen)
465 {
466 	u8 *buf = NULL;
467 	int group_cipher = 0, pairwise_cipher = 0;
468 	int ret = 0;
469 
470 	if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
471 		return -EINVAL;
472 	if (ielen) {
473 		buf = kmemdup(pie, ielen, GFP_ATOMIC);
474 		if (buf == NULL)
475 			return -ENOMEM;
476 		if (ielen < RSN_HEADER_LEN) {
477 			ret  = -EINVAL;
478 			goto exit;
479 		}
480 		if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
481 		    &pairwise_cipher) == _SUCCESS) {
482 			padapter->securitypriv.AuthAlgrthm = 2;
483 			padapter->securitypriv.ndisauthtype =
484 				  Ndis802_11AuthModeWPAPSK;
485 		}
486 		if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
487 		    &pairwise_cipher) == _SUCCESS) {
488 			padapter->securitypriv.AuthAlgrthm = 2;
489 			padapter->securitypriv.ndisauthtype =
490 				  Ndis802_11AuthModeWPA2PSK;
491 		}
492 		switch (group_cipher) {
493 		case WPA_CIPHER_NONE:
494 			padapter->securitypriv.XGrpPrivacy =
495 				 _NO_PRIVACY_;
496 			padapter->securitypriv.ndisencryptstatus =
497 				 Ndis802_11EncryptionDisabled;
498 			break;
499 		case WPA_CIPHER_WEP40:
500 			padapter->securitypriv.XGrpPrivacy = _WEP40_;
501 			padapter->securitypriv.ndisencryptstatus =
502 				 Ndis802_11Encryption1Enabled;
503 			break;
504 		case WPA_CIPHER_TKIP:
505 			padapter->securitypriv.XGrpPrivacy = _TKIP_;
506 			padapter->securitypriv.ndisencryptstatus =
507 				 Ndis802_11Encryption2Enabled;
508 			break;
509 		case WPA_CIPHER_CCMP:
510 			padapter->securitypriv.XGrpPrivacy = _AES_;
511 			padapter->securitypriv.ndisencryptstatus =
512 				 Ndis802_11Encryption3Enabled;
513 			break;
514 		case WPA_CIPHER_WEP104:
515 			padapter->securitypriv.XGrpPrivacy = _WEP104_;
516 			padapter->securitypriv.ndisencryptstatus =
517 				 Ndis802_11Encryption1Enabled;
518 			break;
519 		}
520 		switch (pairwise_cipher) {
521 		case WPA_CIPHER_NONE:
522 			padapter->securitypriv.PrivacyAlgrthm =
523 				 _NO_PRIVACY_;
524 			padapter->securitypriv.ndisencryptstatus =
525 				 Ndis802_11EncryptionDisabled;
526 			break;
527 		case WPA_CIPHER_WEP40:
528 			padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
529 			padapter->securitypriv.ndisencryptstatus =
530 				 Ndis802_11Encryption1Enabled;
531 			break;
532 		case WPA_CIPHER_TKIP:
533 			padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
534 			padapter->securitypriv.ndisencryptstatus =
535 				 Ndis802_11Encryption2Enabled;
536 			break;
537 		case WPA_CIPHER_CCMP:
538 			padapter->securitypriv.PrivacyAlgrthm = _AES_;
539 			padapter->securitypriv.ndisencryptstatus =
540 				 Ndis802_11Encryption3Enabled;
541 			break;
542 		case WPA_CIPHER_WEP104:
543 			padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
544 			padapter->securitypriv.ndisencryptstatus =
545 				 Ndis802_11Encryption1Enabled;
546 			break;
547 		}
548 		padapter->securitypriv.wps_phase = false;
549 		{/* set wps_ie */
550 			u16 cnt = 0;
551 			u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
552 
553 			while (cnt < ielen) {
554 				eid = buf[cnt];
555 
556 				if ((eid == _VENDOR_SPECIFIC_IE_) &&
557 				    (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
558 					netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
559 					padapter->securitypriv.wps_ie_len =
560 					    ((buf[cnt + 1] + 2) <
561 					    (MAX_WPA_IE_LEN << 2)) ?
562 					    (buf[cnt + 1] + 2) :
563 					    (MAX_WPA_IE_LEN << 2);
564 					memcpy(padapter->securitypriv.wps_ie,
565 					    &buf[cnt],
566 					    padapter->securitypriv.wps_ie_len);
567 					padapter->securitypriv.wps_phase =
568 								 true;
569 					netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
570 					cnt += buf[cnt + 1] + 2;
571 					break;
572 				}
573 
574 				cnt += buf[cnt + 1] + 2;
575 			}
576 		}
577 	}
578 exit:
579 	kfree(buf);
580 	return ret;
581 }
582 
583 static int r8711_wx_get_name(struct net_device *dev,
584 			     struct iw_request_info *info,
585 			     union iwreq_data *wrqu, char *extra)
586 {
587 	struct _adapter *padapter = netdev_priv(dev);
588 	u32 ht_ielen = 0;
589 	char *p;
590 	u8 ht_cap = false;
591 	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
592 	struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
593 	u8 *prates;
594 
595 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
596 	    true) {
597 		/* parsing HT_CAP_IE */
598 		p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
599 				 &ht_ielen, pcur_bss->IELength - 12);
600 		if (p && ht_ielen > 0)
601 			ht_cap = true;
602 		prates = pcur_bss->rates;
603 		if (r8712_is_cckratesonly_included(prates)) {
604 			if (ht_cap)
605 				snprintf(wrqu->name, IFNAMSIZ,
606 					 "IEEE 802.11bn");
607 			else
608 				snprintf(wrqu->name, IFNAMSIZ,
609 					 "IEEE 802.11b");
610 		} else if (r8712_is_cckrates_included(prates)) {
611 			if (ht_cap)
612 				snprintf(wrqu->name, IFNAMSIZ,
613 					 "IEEE 802.11bgn");
614 			else
615 				snprintf(wrqu->name, IFNAMSIZ,
616 					 "IEEE 802.11bg");
617 		} else {
618 			if (ht_cap)
619 				snprintf(wrqu->name, IFNAMSIZ,
620 					 "IEEE 802.11gn");
621 			else
622 				snprintf(wrqu->name, IFNAMSIZ,
623 					 "IEEE 802.11g");
624 		}
625 	} else {
626 		snprintf(wrqu->name, IFNAMSIZ, "unassociated");
627 	}
628 	return 0;
629 }
630 
631 static const long frequency_list[] = {
632 	2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
633 	2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
634 	5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
635 	5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
636 	5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
637 	5825
638 };
639 
640 static int r8711_wx_set_freq(struct net_device *dev,
641 			     struct iw_request_info *info,
642 			     union iwreq_data *wrqu, char *extra)
643 {
644 	struct _adapter *padapter = netdev_priv(dev);
645 	struct iw_freq *fwrq = &wrqu->freq;
646 	int rc = 0;
647 
648 /* If setting by frequency, convert to a channel */
649 	if ((fwrq->e == 1) &&
650 	  (fwrq->m >= (int) 2.412e8) &&
651 	  (fwrq->m <= (int) 2.487e8)) {
652 		int f = fwrq->m / 100000;
653 		int c = 0;
654 
655 		while ((c < 14) && (f != frequency_list[c]))
656 			c++;
657 		fwrq->e = 0;
658 		fwrq->m = c + 1;
659 	}
660 	/* Setting by channel number */
661 	if ((fwrq->m > 14) || (fwrq->e > 0)) {
662 		rc = -EOPNOTSUPP;
663 	} else {
664 		int channel = fwrq->m;
665 
666 		if ((channel < 1) || (channel > 14)) {
667 			rc = -EINVAL;
668 		} else {
669 			/* Yes ! We can set it !!! */
670 			padapter->registrypriv.channel = channel;
671 		}
672 	}
673 	return rc;
674 }
675 
676 static int r8711_wx_get_freq(struct net_device *dev,
677 			     struct iw_request_info *info,
678 			     union iwreq_data *wrqu, char *extra)
679 {
680 	struct _adapter *padapter = netdev_priv(dev);
681 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
682 	struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
683 
684 	if (!check_fwstate(pmlmepriv, _FW_LINKED))
685 		return -ENOLINK;
686 
687 	wrqu->freq.m = ieee80211_wlan_frequencies[
688 		       pcur_bss->Configuration.DSConfig - 1] * 100000;
689 	wrqu->freq.e = 1;
690 	wrqu->freq.i = pcur_bss->Configuration.DSConfig;
691 
692 	return 0;
693 }
694 
695 static int r8711_wx_set_mode(struct net_device *dev,
696 			     struct iw_request_info *a,
697 			     union iwreq_data *wrqu, char *b)
698 {
699 	struct _adapter *padapter = netdev_priv(dev);
700 	enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
701 
702 	switch (wrqu->mode) {
703 	case IW_MODE_AUTO:
704 		networkType = Ndis802_11AutoUnknown;
705 		break;
706 	case IW_MODE_ADHOC:
707 		networkType = Ndis802_11IBSS;
708 		break;
709 	case IW_MODE_MASTER:
710 		networkType = Ndis802_11APMode;
711 		break;
712 	case IW_MODE_INFRA:
713 		networkType = Ndis802_11Infrastructure;
714 		break;
715 	default:
716 		return -EINVAL;
717 	}
718 	if (Ndis802_11APMode == networkType)
719 		r8712_setopmode_cmd(padapter, networkType);
720 	else
721 		r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
722 
723 	r8712_set_802_11_infrastructure_mode(padapter, networkType);
724 	return 0;
725 }
726 
727 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
728 			     union iwreq_data *wrqu, char *b)
729 {
730 	struct _adapter *padapter = netdev_priv(dev);
731 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
732 
733 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
734 		wrqu->mode = IW_MODE_INFRA;
735 	else if (check_fwstate(pmlmepriv,
736 		 WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
737 		wrqu->mode = IW_MODE_ADHOC;
738 	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
739 		wrqu->mode = IW_MODE_MASTER;
740 	else
741 		wrqu->mode = IW_MODE_AUTO;
742 	return 0;
743 }
744 
745 static int r871x_wx_set_pmkid(struct net_device *dev,
746 			     struct iw_request_info *a,
747 			     union iwreq_data *wrqu, char *extra)
748 {
749 	struct _adapter *padapter = netdev_priv(dev);
750 	struct security_priv *psecuritypriv = &padapter->securitypriv;
751 	struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
752 	struct RT_PMKID_LIST *pl = psecuritypriv->PMKIDList;
753 	u8 strZeroMacAddress[ETH_ALEN] = {0x00};
754 	u8 strIssueBssid[ETH_ALEN] = {0x00};
755 	u8 j, blInserted = false;
756 	int intReturn = false;
757 
758 /*
759  *	There are the BSSID information in the bssid.sa_data array.
760  *	If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
761  *	all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
762  *	wpa_supplicant wants to add a PMKID/BSSID to driver.
763  *	If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
764  *	remove a PMKID/BSSID from driver.
765  */
766 	if (pPMK == NULL)
767 		return -EINVAL;
768 	memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
769 	switch (pPMK->cmd) {
770 	case IW_PMKSA_ADD:
771 		if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
772 			return intReturn;
773 		intReturn = true;
774 		blInserted = false;
775 		/* overwrite PMKID */
776 		for (j = 0; j < NUM_PMKID_CACHE; j++) {
777 			if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
778 				/* BSSID is matched, the same AP => rewrite
779 				 * with new PMKID.
780 				 */
781 				netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
782 					    __func__);
783 				memcpy(pl[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
784 				pl[j].bUsed = true;
785 				psecuritypriv->PMKIDIndex = j + 1;
786 				blInserted = true;
787 				break;
788 			}
789 		}
790 		if (!blInserted) {
791 			/* Find a new entry */
792 			netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
793 				    __func__, psecuritypriv->PMKIDIndex);
794 			memcpy(pl[psecuritypriv->PMKIDIndex].Bssid,
795 			       strIssueBssid, ETH_ALEN);
796 			memcpy(pl[psecuritypriv->PMKIDIndex].PMKID,
797 			       pPMK->pmkid, IW_PMKID_LEN);
798 			pl[psecuritypriv->PMKIDIndex].bUsed = true;
799 			psecuritypriv->PMKIDIndex++;
800 			if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
801 				psecuritypriv->PMKIDIndex = 0;
802 		}
803 		break;
804 	case IW_PMKSA_REMOVE:
805 		intReturn = true;
806 		for (j = 0; j < NUM_PMKID_CACHE; j++) {
807 			if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
808 				/* BSSID is matched, the same AP => Remove
809 				 * this PMKID information and reset it.
810 				 */
811 				eth_zero_addr(pl[j].Bssid);
812 				pl[j].bUsed = false;
813 				break;
814 			}
815 		}
816 		break;
817 	case IW_PMKSA_FLUSH:
818 		memset(psecuritypriv->PMKIDList, 0,
819 			sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
820 		psecuritypriv->PMKIDIndex = 0;
821 		intReturn = true;
822 		break;
823 	default:
824 		netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
825 		intReturn = false;
826 		break;
827 	}
828 	return intReturn;
829 }
830 
831 static int r8711_wx_get_sens(struct net_device *dev,
832 			     struct iw_request_info *info,
833 			     union iwreq_data *wrqu, char *extra)
834 {
835 	wrqu->sens.value = 0;
836 	wrqu->sens.fixed = 0;	/* no auto select */
837 	wrqu->sens.disabled = 1;
838 	return 0;
839 }
840 
841 static int r8711_wx_get_range(struct net_device *dev,
842 				struct iw_request_info *info,
843 				union iwreq_data *wrqu, char *extra)
844 {
845 	struct iw_range *range = (struct iw_range *)extra;
846 	u16 val;
847 	int i;
848 
849 	wrqu->data.length = sizeof(*range);
850 	memset(range, 0, sizeof(*range));
851 	/* Let's try to keep this struct in the same order as in
852 	 * linux/include/wireless.h
853 	 */
854 
855 	/* TODO: See what values we can set, and remove the ones we can't
856 	 * set, or fill them with some default data.
857 	 */
858 	/* ~5 Mb/s real (802.11b) */
859 	range->throughput = 5 * 1000 * 1000;
860 	/* TODO: 8711 sensitivity ? */
861 	/* signal level threshold range */
862 	/* percent values between 0 and 100. */
863 	range->max_qual.qual = 100;
864 	range->max_qual.level = 100;
865 	range->max_qual.noise = 100;
866 	range->max_qual.updated = 7; /* Updated all three */
867 	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
868 	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
869 	range->avg_qual.level = 0x100 - 78;
870 	range->avg_qual.noise = 0;
871 	range->avg_qual.updated = 7; /* Updated all three */
872 	range->num_bitrates = RATE_COUNT;
873 	for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
874 		range->bitrate[i] = rtl8180_rates[i];
875 	range->min_frag = MIN_FRAG_THRESHOLD;
876 	range->max_frag = MAX_FRAG_THRESHOLD;
877 	range->pm_capa = 0;
878 	range->we_version_compiled = WIRELESS_EXT;
879 	range->we_version_source = 16;
880 	range->num_channels = 14;
881 	for (i = 0, val = 0; i < 14; i++) {
882 		/* Include only legal frequencies for some countries */
883 		range->freq[val].i = i + 1;
884 		range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
885 		range->freq[val].e = 1;
886 		val++;
887 		if (val == IW_MAX_FREQUENCIES)
888 			break;
889 	}
890 	range->num_frequency = val;
891 	range->enc_capa = IW_ENC_CAPA_WPA |
892 			  IW_ENC_CAPA_WPA2 |
893 			  IW_ENC_CAPA_CIPHER_TKIP |
894 			  IW_ENC_CAPA_CIPHER_CCMP;
895 	return 0;
896 }
897 
898 static int r8711_wx_get_rate(struct net_device *dev,
899 			     struct iw_request_info *info,
900 			     union iwreq_data *wrqu, char *extra);
901 
902 static int r871x_wx_set_priv(struct net_device *dev,
903 				struct iw_request_info *info,
904 				union iwreq_data *awrq,
905 				char *extra)
906 {
907 	int ret = 0, len = 0;
908 	char *ext;
909 	struct _adapter *padapter = netdev_priv(dev);
910 	struct iw_point *dwrq = (struct iw_point *)awrq;
911 
912 	len = dwrq->length;
913 	ext = memdup_user(dwrq->pointer, len);
914 	if (IS_ERR(ext))
915 		return PTR_ERR(ext);
916 
917 	if (!strcasecmp(ext, "RSSI")) {
918 		/*Return received signal strength indicator in -db for */
919 		/* current AP */
920 		/*<ssid> Rssi xx */
921 		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
922 		struct wlan_network *pcur_network = &pmlmepriv->cur_network;
923 		/*static u8 xxxx; */
924 		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
925 			sprintf(ext, "%s rssi %d",
926 				pcur_network->network.Ssid.Ssid,
927 				/*(xxxx=xxxx+10) */
928 				((padapter->recvpriv.fw_rssi) >> 1) - 95
929 				/*pcur_network->network.Rssi */
930 				);
931 		} else {
932 			sprintf(ext, "OK");
933 		}
934 	} else if (!strcasecmp(ext, "LINKSPEED")) {
935 		/*Return link speed in MBPS */
936 		/*LinkSpeed xx */
937 		union iwreq_data wrqd;
938 		int ret_inner;
939 		int mbps;
940 
941 		ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
942 		if (ret_inner != 0)
943 			mbps = 0;
944 		else
945 			mbps = wrqd.bitrate.value / 1000000;
946 		sprintf(ext, "LINKSPEED %d", mbps);
947 	} else if (!strcasecmp(ext, "MACADDR")) {
948 		/*Return mac address of the station */
949 		/* Macaddr = xx:xx:xx:xx:xx:xx */
950 		sprintf(ext, "MACADDR = %pM", dev->dev_addr);
951 	} else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
952 		/*Set scan type to active */
953 		/*OK if successful */
954 		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
955 
956 		pmlmepriv->passive_mode = 1;
957 		sprintf(ext, "OK");
958 	} else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
959 		/*Set scan type to passive */
960 		/*OK if successful */
961 		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
962 
963 		pmlmepriv->passive_mode = 0;
964 		sprintf(ext, "OK");
965 	} else if (!strncmp(ext, "DCE-E", 5)) {
966 		/*Set scan type to passive */
967 		/*OK if successful */
968 		r8712_disconnectCtrlEx_cmd(padapter
969 			, 1 /*u32 enableDrvCtrl */
970 			, 5 /*u32 tryPktCnt */
971 			, 100 /*u32 tryPktInterval */
972 			, 5000 /*u32 firstStageTO */
973 		);
974 		sprintf(ext, "OK");
975 	} else if (!strncmp(ext, "DCE-D", 5)) {
976 		/*Set scan type to passive */
977 		/*OK if successfu */
978 		r8712_disconnectCtrlEx_cmd(padapter
979 			, 0 /*u32 enableDrvCtrl */
980 			, 5 /*u32 tryPktCnt */
981 			, 100 /*u32 tryPktInterval */
982 			, 5000 /*u32 firstStageTO */
983 		);
984 		sprintf(ext, "OK");
985 	} else {
986 		netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
987 			    __func__, ext);
988 		goto FREE_EXT;
989 	}
990 	if (copy_to_user(dwrq->pointer, ext,
991 				min(dwrq->length, (__u16)(strlen(ext) + 1))))
992 		ret = -EFAULT;
993 
994 FREE_EXT:
995 	kfree(ext);
996 	return ret;
997 }
998 
999 /* set bssid flow
1000  * s1. set_802_11_infrastructure_mode()
1001  * s2. set_802_11_authentication_mode()
1002  * s3. set_802_11_encryption_mode()
1003  * s4. set_802_11_bssid()
1004  *
1005  * This function intends to handle the Set AP command, which specifies the
1006  * MAC# of a preferred Access Point.
1007  * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1008  *
1009  * For this operation to succeed, there is no need for the interface to be up.
1010  *
1011  */
1012 static int r8711_wx_set_wap(struct net_device *dev,
1013 			 struct iw_request_info *info,
1014 			 union iwreq_data *awrq,
1015 			 char *extra)
1016 {
1017 	int ret = -EINPROGRESS;
1018 	struct _adapter *padapter = netdev_priv(dev);
1019 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1020 	struct  __queue *queue = &pmlmepriv->scanned_queue;
1021 	struct sockaddr *temp = (struct sockaddr *)awrq;
1022 	unsigned long irqL;
1023 	struct list_head *phead;
1024 	u8 *dst_bssid;
1025 	struct wlan_network *pnetwork = NULL;
1026 	enum NDIS_802_11_AUTHENTICATION_MODE	authmode;
1027 
1028 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1029 		return -EBUSY;
1030 	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1031 		return ret;
1032 	if (temp->sa_family != ARPHRD_ETHER)
1033 		return -EINVAL;
1034 	authmode = padapter->securitypriv.ndisauthtype;
1035 	spin_lock_irqsave(&queue->lock, irqL);
1036 	phead = &queue->queue;
1037 	pmlmepriv->pscanned = phead->next;
1038 	while (1) {
1039 		if (end_of_queue_search(phead, pmlmepriv->pscanned))
1040 			break;
1041 		pnetwork = container_of(pmlmepriv->pscanned,
1042 					struct wlan_network, list);
1043 		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1044 		dst_bssid = pnetwork->network.MacAddress;
1045 		if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1046 			r8712_set_802_11_infrastructure_mode(padapter,
1047 			    pnetwork->network.InfrastructureMode);
1048 			break;
1049 		}
1050 	}
1051 	spin_unlock_irqrestore(&queue->lock, irqL);
1052 	if (!ret) {
1053 		if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
1054 			ret = -ENOMEM;
1055 		} else {
1056 			if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1057 				ret = -1;
1058 		}
1059 	}
1060 	return ret;
1061 }
1062 
1063 static int r8711_wx_get_wap(struct net_device *dev,
1064 				struct iw_request_info *info,
1065 				union iwreq_data *wrqu, char *extra)
1066 {
1067 	struct _adapter *padapter = netdev_priv(dev);
1068 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1069 	struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1070 
1071 	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1072 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1073 				     WIFI_AP_STATE))
1074 		ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
1075 	else
1076 		eth_zero_addr(wrqu->ap_addr.sa_data);
1077 	return 0;
1078 }
1079 
1080 static int r871x_wx_set_mlme(struct net_device *dev,
1081 			     struct iw_request_info *info,
1082 			     union iwreq_data *wrqu, char *extra)
1083 {
1084 	int ret = 0;
1085 	struct _adapter *padapter = netdev_priv(dev);
1086 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
1087 
1088 	if (mlme == NULL)
1089 		return -1;
1090 	switch (mlme->cmd) {
1091 	case IW_MLME_DEAUTH:
1092 		if (!r8712_set_802_11_disassociate(padapter))
1093 			ret = -1;
1094 		break;
1095 	case IW_MLME_DISASSOC:
1096 		if (!r8712_set_802_11_disassociate(padapter))
1097 			ret = -1;
1098 		break;
1099 	default:
1100 		return -EOPNOTSUPP;
1101 	}
1102 	return ret;
1103 }
1104 
1105 /*
1106  *
1107  * This function intends to handle the Set Scan command.
1108  * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1109  *
1110  * For this operation to succeed, the interface is brought Up beforehand.
1111  *
1112  */
1113 static int r8711_wx_set_scan(struct net_device *dev,
1114 			struct iw_request_info *a,
1115 			union iwreq_data *wrqu, char *extra)
1116 {
1117 	struct _adapter *padapter = netdev_priv(dev);
1118 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1119 	u8 status = true;
1120 
1121 	if (padapter->driver_stopped) {
1122 		netdev_info(dev, "In %s: driver_stopped=%d\n",
1123 			    __func__, padapter->driver_stopped);
1124 		return -1;
1125 	}
1126 	if (!padapter->bup)
1127 		return -ENETDOWN;
1128 	if (!padapter->hw_init_completed)
1129 		return -1;
1130 	if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
1131 	    (pmlmepriv->sitesurveyctrl.traffic_busy))
1132 		return 0;
1133 	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1134 		struct iw_scan_req *req = (struct iw_scan_req *)extra;
1135 
1136 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1137 			struct ndis_802_11_ssid ssid;
1138 			unsigned long irqL;
1139 			u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1140 
1141 			memset((unsigned char *)&ssid, 0,
1142 				 sizeof(struct ndis_802_11_ssid));
1143 			memcpy(ssid.Ssid, req->essid, len);
1144 			ssid.SsidLength = len;
1145 			spin_lock_irqsave(&pmlmepriv->lock, irqL);
1146 			if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1147 			     _FW_UNDER_LINKING)) ||
1148 			    (pmlmepriv->sitesurveyctrl.traffic_busy)) {
1149 				if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1150 					status = false;
1151 			} else {
1152 				status = r8712_sitesurvey_cmd(padapter, &ssid);
1153 			}
1154 			spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1155 		}
1156 	} else {
1157 		status = r8712_set_802_11_bssid_list_scan(padapter);
1158 	}
1159 	if (!status)
1160 		return -1;
1161 	return 0;
1162 }
1163 
1164 static int r8711_wx_get_scan(struct net_device *dev,
1165 				struct iw_request_info *a,
1166 				union iwreq_data *wrqu, char *extra)
1167 {
1168 	struct _adapter *padapter = netdev_priv(dev);
1169 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1170 	struct  __queue *queue = &pmlmepriv->scanned_queue;
1171 	struct wlan_network *pnetwork = NULL;
1172 	unsigned long irqL;
1173 	struct list_head *plist, *phead;
1174 	char *ev = extra;
1175 	char *stop = ev + wrqu->data.length;
1176 	u32 ret = 0, cnt = 0;
1177 
1178 	if (padapter->driver_stopped)
1179 		return -EINVAL;
1180 	while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1181 			     _FW_UNDER_LINKING)) {
1182 		msleep(30);
1183 		cnt++;
1184 		if (cnt > 100)
1185 			break;
1186 	}
1187 	spin_lock_irqsave(&queue->lock, irqL);
1188 	phead = &queue->queue;
1189 	plist = phead->next;
1190 	while (1) {
1191 		if (end_of_queue_search(phead, plist))
1192 			break;
1193 		if ((stop - ev) < SCAN_ITEM_SIZE) {
1194 			ret = -E2BIG;
1195 			break;
1196 		}
1197 		pnetwork = container_of(plist, struct wlan_network, list);
1198 		ev = translate_scan(padapter, a, pnetwork, ev, stop);
1199 		plist = plist->next;
1200 	}
1201 	spin_unlock_irqrestore(&queue->lock, irqL);
1202 	wrqu->data.length = ev - extra;
1203 	wrqu->data.flags = 0;
1204 	return ret;
1205 }
1206 
1207 /* set ssid flow
1208  * s1. set_802_11_infrastructure_mode()
1209  * s2. set_802_11_authenticaion_mode()
1210  * s3. set_802_11_encryption_mode()
1211  * s4. set_802_11_ssid()
1212  *
1213  * This function intends to handle the Set ESSID command.
1214  * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1215  *
1216  * For this operation to succeed, there is no need for the interface to be Up.
1217  *
1218  */
1219 static int r8711_wx_set_essid(struct net_device *dev,
1220 				struct iw_request_info *a,
1221 				union iwreq_data *wrqu, char *extra)
1222 {
1223 	struct _adapter *padapter = netdev_priv(dev);
1224 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1225 	struct  __queue *queue = &pmlmepriv->scanned_queue;
1226 	struct wlan_network *pnetwork = NULL;
1227 	enum NDIS_802_11_AUTHENTICATION_MODE	authmode;
1228 	struct ndis_802_11_ssid ndis_ssid;
1229 	u8 *dst_ssid, *src_ssid;
1230 	struct list_head *phead;
1231 	u32 len;
1232 
1233 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1234 		return -EBUSY;
1235 	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1236 		return 0;
1237 	if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1238 		return -E2BIG;
1239 	authmode = padapter->securitypriv.ndisauthtype;
1240 	if (wrqu->essid.flags && wrqu->essid.length) {
1241 		len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1242 		       wrqu->essid.length : IW_ESSID_MAX_SIZE;
1243 		memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1244 		ndis_ssid.SsidLength = len;
1245 		memcpy(ndis_ssid.Ssid, extra, len);
1246 		src_ssid = ndis_ssid.Ssid;
1247 		phead = &queue->queue;
1248 		pmlmepriv->pscanned = phead->next;
1249 		while (1) {
1250 			if (end_of_queue_search(phead, pmlmepriv->pscanned))
1251 				break;
1252 			pnetwork = container_of(pmlmepriv->pscanned,
1253 						struct wlan_network, list);
1254 			pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1255 			dst_ssid = pnetwork->network.Ssid.Ssid;
1256 			if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1257 			    && (pnetwork->network.Ssid.SsidLength ==
1258 			     ndis_ssid.SsidLength)) {
1259 				if (check_fwstate(pmlmepriv,
1260 							WIFI_ADHOC_STATE)) {
1261 					if (pnetwork->network.
1262 						InfrastructureMode
1263 						!=
1264 						padapter->mlmepriv.
1265 						cur_network.network.
1266 						InfrastructureMode)
1267 						continue;
1268 				}
1269 
1270 				r8712_set_802_11_infrastructure_mode(
1271 				     padapter,
1272 				     pnetwork->network.InfrastructureMode);
1273 				break;
1274 			}
1275 		}
1276 		r8712_set_802_11_authentication_mode(padapter, authmode);
1277 		r8712_set_802_11_ssid(padapter, &ndis_ssid);
1278 	}
1279 	return -EINPROGRESS;
1280 }
1281 
1282 static int r8711_wx_get_essid(struct net_device *dev,
1283 				struct iw_request_info *a,
1284 				union iwreq_data *wrqu, char *extra)
1285 {
1286 	struct _adapter *padapter = netdev_priv(dev);
1287 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1288 	struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1289 	u32 len, ret = 0;
1290 
1291 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
1292 		len = pcur_bss->Ssid.SsidLength;
1293 		wrqu->essid.length = len;
1294 		memcpy(extra, pcur_bss->Ssid.Ssid, len);
1295 		wrqu->essid.flags = 1;
1296 	} else {
1297 		ret = -ENOLINK;
1298 	}
1299 	return ret;
1300 }
1301 
1302 static int r8711_wx_set_rate(struct net_device *dev,
1303 				struct iw_request_info *a,
1304 				union iwreq_data *wrqu, char *extra)
1305 {
1306 	struct _adapter *padapter = netdev_priv(dev);
1307 	u32 target_rate = wrqu->bitrate.value;
1308 	u32 fixed = wrqu->bitrate.fixed;
1309 	u32 ratevalue = 0;
1310 	u8 datarates[NumRates];
1311 	u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1312 	int i, ret = 0;
1313 
1314 	if (target_rate == -1) {
1315 		ratevalue = 11;
1316 		goto set_rate;
1317 	}
1318 	target_rate = target_rate / 100000;
1319 	switch (target_rate) {
1320 	case 10:
1321 		ratevalue = 0;
1322 		break;
1323 	case 20:
1324 		ratevalue = 1;
1325 		break;
1326 	case 55:
1327 		ratevalue = 2;
1328 		break;
1329 	case 60:
1330 		ratevalue = 3;
1331 		break;
1332 	case 90:
1333 		ratevalue = 4;
1334 		break;
1335 	case 110:
1336 		ratevalue = 5;
1337 		break;
1338 	case 120:
1339 		ratevalue = 6;
1340 		break;
1341 	case 180:
1342 		ratevalue = 7;
1343 		break;
1344 	case 240:
1345 		ratevalue = 8;
1346 		break;
1347 	case 360:
1348 		ratevalue = 9;
1349 		break;
1350 	case 480:
1351 		ratevalue = 10;
1352 		break;
1353 	case 540:
1354 		ratevalue = 11;
1355 		break;
1356 	default:
1357 		ratevalue = 11;
1358 		break;
1359 	}
1360 set_rate:
1361 	for (i = 0; i < NumRates; i++) {
1362 		if (ratevalue == mpdatarate[i]) {
1363 			datarates[i] = mpdatarate[i];
1364 			if (fixed == 0)
1365 				break;
1366 		} else {
1367 			datarates[i] = 0xff;
1368 		}
1369 	}
1370 	if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1371 		ret = -ENOMEM;
1372 	return ret;
1373 }
1374 
1375 static int r8711_wx_get_rate(struct net_device *dev,
1376 			     struct iw_request_info *info,
1377 			     union iwreq_data *wrqu, char *extra)
1378 {
1379 	struct _adapter *padapter = netdev_priv(dev);
1380 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1381 	struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1382 	struct ieee80211_ht_cap *pht_capie;
1383 	unsigned char rf_type = padapter->registrypriv.rf_config;
1384 	int i;
1385 	u8 *p;
1386 	u16 rate, max_rate = 0, ht_cap = false;
1387 	u32 ht_ielen = 0;
1388 	u8 bw_40MHz = 0, short_GI = 0;
1389 	u16 mcs_rate = 0;
1390 
1391 	i = 0;
1392 	if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
1393 		return -ENOLINK;
1394 	p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen,
1395 			 pcur_bss->IELength - 12);
1396 	if (p && ht_ielen > 0) {
1397 		ht_cap = true;
1398 		pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1399 		memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
1400 		bw_40MHz = (le16_to_cpu(pht_capie->cap_info) &
1401 			    IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1402 		short_GI = (le16_to_cpu(pht_capie->cap_info) &
1403 			    (IEEE80211_HT_CAP_SGI_20 |
1404 			    IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1405 	}
1406 	while ((pcur_bss->rates[i] != 0) &&
1407 	       (pcur_bss->rates[i] != 0xFF)) {
1408 		rate = pcur_bss->rates[i] & 0x7F;
1409 		if (rate > max_rate)
1410 			max_rate = rate;
1411 		wrqu->bitrate.fixed = 0;	/* no auto select */
1412 		wrqu->bitrate.value = rate * 500000;
1413 		i++;
1414 	}
1415 	if (ht_cap) {
1416 		if (mcs_rate & 0x8000 /* MCS15 */
1417 		    &&
1418 		    rf_type == RTL8712_RF_2T2R)
1419 			max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) :
1420 			((short_GI) ? 144 : 130);
1421 		else /* default MCS7 */
1422 			max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) :
1423 			((short_GI) ? 72 : 65);
1424 		max_rate *= 2; /* Mbps/2 */
1425 	}
1426 	wrqu->bitrate.value = max_rate * 500000;
1427 	return 0;
1428 }
1429 
1430 static int r8711_wx_get_rts(struct net_device *dev,
1431 				struct iw_request_info *info,
1432 				union iwreq_data *wrqu, char *extra)
1433 {
1434 	struct _adapter *padapter = netdev_priv(dev);
1435 
1436 	wrqu->rts.value = padapter->registrypriv.rts_thresh;
1437 	wrqu->rts.fixed = 0;	/* no auto select */
1438 	return 0;
1439 }
1440 
1441 static int r8711_wx_set_frag(struct net_device *dev,
1442 				struct iw_request_info *info,
1443 				union iwreq_data *wrqu, char *extra)
1444 {
1445 	struct _adapter *padapter = netdev_priv(dev);
1446 
1447 	if (wrqu->frag.disabled) {
1448 		padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1449 	} else {
1450 		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1451 		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
1452 			return -EINVAL;
1453 		padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1454 	}
1455 	return 0;
1456 }
1457 
1458 static int r8711_wx_get_frag(struct net_device *dev,
1459 				struct iw_request_info *info,
1460 				union iwreq_data *wrqu, char *extra)
1461 {
1462 	struct _adapter *padapter = netdev_priv(dev);
1463 
1464 	wrqu->frag.value = padapter->xmitpriv.frag_len;
1465 	wrqu->frag.fixed = 0;	/* no auto select */
1466 	return 0;
1467 }
1468 
1469 static int r8711_wx_get_retry(struct net_device *dev,
1470 				struct iw_request_info *info,
1471 				union iwreq_data *wrqu, char *extra)
1472 {
1473 	wrqu->retry.value = 7;
1474 	wrqu->retry.fixed = 0;	/* no auto select */
1475 	wrqu->retry.disabled = 1;
1476 	return 0;
1477 }
1478 
1479 static int r8711_wx_set_enc(struct net_device *dev,
1480 				struct iw_request_info *info,
1481 				union iwreq_data *wrqu, char *keybuf)
1482 {
1483 	u32 key;
1484 	u32 keyindex_provided;
1485 	struct NDIS_802_11_WEP	 wep;
1486 	enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1487 	struct iw_point *erq = &(wrqu->encoding);
1488 	struct _adapter *padapter = netdev_priv(dev);
1489 
1490 	key = erq->flags & IW_ENCODE_INDEX;
1491 	memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1492 	if (erq->flags & IW_ENCODE_DISABLED) {
1493 		netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1494 		padapter->securitypriv.ndisencryptstatus =
1495 				 Ndis802_11EncryptionDisabled;
1496 		padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1497 		padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1498 		padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1499 		authmode = Ndis802_11AuthModeOpen;
1500 		padapter->securitypriv.ndisauthtype = authmode;
1501 		return 0;
1502 	}
1503 	if (key) {
1504 		if (key > WEP_KEYS)
1505 			return -EINVAL;
1506 		key--;
1507 		keyindex_provided = 1;
1508 	} else {
1509 		keyindex_provided = 0;
1510 		key = padapter->securitypriv.PrivacyKeyIndex;
1511 	}
1512 	/* set authentication mode */
1513 	if (erq->flags & IW_ENCODE_OPEN) {
1514 		netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1515 		padapter->securitypriv.ndisencryptstatus =
1516 				 Ndis802_11Encryption1Enabled;
1517 		padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1518 		padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1519 		padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1520 		authmode = Ndis802_11AuthModeOpen;
1521 		padapter->securitypriv.ndisauthtype = authmode;
1522 	} else if (erq->flags & IW_ENCODE_RESTRICTED) {
1523 		netdev_info(dev,
1524 				"r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1525 		padapter->securitypriv.ndisencryptstatus =
1526 				 Ndis802_11Encryption1Enabled;
1527 		padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1528 		padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1529 		padapter->securitypriv.XGrpPrivacy = _WEP40_;
1530 		authmode = Ndis802_11AuthModeShared;
1531 		padapter->securitypriv.ndisauthtype = authmode;
1532 	} else {
1533 		padapter->securitypriv.ndisencryptstatus =
1534 				 Ndis802_11Encryption1Enabled;
1535 		padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1536 		padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1537 		padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1538 		authmode = Ndis802_11AuthModeOpen;
1539 		padapter->securitypriv.ndisauthtype = authmode;
1540 	}
1541 	wep.KeyIndex = key;
1542 	if (erq->length > 0) {
1543 		wep.KeyLength = erq->length <= 5 ? 5 : 13;
1544 		wep.Length = wep.KeyLength +
1545 			     FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1546 	} else {
1547 		wep.KeyLength = 0;
1548 		if (keyindex_provided == 1) { /* set key_id only, no given
1549 					       * KeyMaterial(erq->length==0).
1550 					       */
1551 			padapter->securitypriv.PrivacyKeyIndex = key;
1552 			switch (padapter->securitypriv.DefKeylen[key]) {
1553 			case 5:
1554 				padapter->securitypriv.PrivacyAlgrthm =
1555 						 _WEP40_;
1556 				break;
1557 			case 13:
1558 				padapter->securitypriv.PrivacyAlgrthm =
1559 						 _WEP104_;
1560 				break;
1561 			default:
1562 				padapter->securitypriv.PrivacyAlgrthm =
1563 						 _NO_PRIVACY_;
1564 				break;
1565 			}
1566 			return 0;
1567 		}
1568 	}
1569 	wep.KeyIndex |= 0x80000000;	/* transmit key */
1570 	memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1571 	if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1572 		return -EOPNOTSUPP;
1573 	return 0;
1574 }
1575 
1576 static int r8711_wx_get_enc(struct net_device *dev,
1577 				struct iw_request_info *info,
1578 				union iwreq_data *wrqu, char *keybuf)
1579 {
1580 	uint key, ret = 0;
1581 	struct _adapter *padapter = netdev_priv(dev);
1582 	struct iw_point *erq = &(wrqu->encoding);
1583 	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
1584 	union Keytype *dk = padapter->securitypriv.DefKey;
1585 
1586 	if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
1587 		if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1588 			erq->length = 0;
1589 			erq->flags |= IW_ENCODE_DISABLED;
1590 			return 0;
1591 		}
1592 	}
1593 	key = erq->flags & IW_ENCODE_INDEX;
1594 	if (key) {
1595 		if (key > WEP_KEYS)
1596 			return -EINVAL;
1597 		key--;
1598 	} else {
1599 		key = padapter->securitypriv.PrivacyKeyIndex;
1600 	}
1601 	erq->flags = key + 1;
1602 	switch (padapter->securitypriv.ndisencryptstatus) {
1603 	case Ndis802_11EncryptionNotSupported:
1604 	case Ndis802_11EncryptionDisabled:
1605 		erq->length = 0;
1606 		erq->flags |= IW_ENCODE_DISABLED;
1607 		break;
1608 	case Ndis802_11Encryption1Enabled:
1609 		erq->length = padapter->securitypriv.DefKeylen[key];
1610 		if (erq->length) {
1611 			memcpy(keybuf, dk[key].skey,
1612 			       padapter->securitypriv.DefKeylen[key]);
1613 			erq->flags |= IW_ENCODE_ENABLED;
1614 			if (padapter->securitypriv.ndisauthtype ==
1615 			    Ndis802_11AuthModeOpen)
1616 				erq->flags |= IW_ENCODE_OPEN;
1617 			else if (padapter->securitypriv.ndisauthtype ==
1618 				 Ndis802_11AuthModeShared)
1619 				erq->flags |= IW_ENCODE_RESTRICTED;
1620 		} else {
1621 			erq->length = 0;
1622 			erq->flags |= IW_ENCODE_DISABLED;
1623 		}
1624 		break;
1625 	case Ndis802_11Encryption2Enabled:
1626 	case Ndis802_11Encryption3Enabled:
1627 		erq->length = 16;
1628 		erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1629 			       IW_ENCODE_NOKEY);
1630 		break;
1631 	default:
1632 		erq->length = 0;
1633 		erq->flags |= IW_ENCODE_DISABLED;
1634 		break;
1635 	}
1636 	return ret;
1637 }
1638 
1639 static int r8711_wx_get_power(struct net_device *dev,
1640 				struct iw_request_info *info,
1641 				union iwreq_data *wrqu, char *extra)
1642 {
1643 	wrqu->power.value = 0;
1644 	wrqu->power.fixed = 0;	/* no auto select */
1645 	wrqu->power.disabled = 1;
1646 	return 0;
1647 }
1648 
1649 static int r871x_wx_set_gen_ie(struct net_device *dev,
1650 				struct iw_request_info *info,
1651 				union iwreq_data *wrqu, char *extra)
1652 {
1653 	struct _adapter *padapter = netdev_priv(dev);
1654 
1655 	return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1656 }
1657 
1658 static int r871x_wx_set_auth(struct net_device *dev,
1659 				struct iw_request_info *info,
1660 				union iwreq_data *wrqu, char *extra)
1661 {
1662 	struct _adapter *padapter = netdev_priv(dev);
1663 	struct iw_param *param = (struct iw_param *)&(wrqu->param);
1664 	int paramid;
1665 	int paramval;
1666 	int ret = 0;
1667 
1668 	paramid = param->flags & IW_AUTH_INDEX;
1669 	paramval = param->value;
1670 	switch (paramid) {
1671 	case IW_AUTH_WPA_VERSION:
1672 		break;
1673 	case IW_AUTH_CIPHER_PAIRWISE:
1674 		break;
1675 	case IW_AUTH_CIPHER_GROUP:
1676 		break;
1677 	case IW_AUTH_KEY_MGMT:
1678 		/*
1679 		 *  ??? does not use these parameters
1680 		 */
1681 		break;
1682 	case IW_AUTH_TKIP_COUNTERMEASURES:
1683 		if (paramval) {
1684 			/* wpa_supplicant is enabling tkip countermeasure. */
1685 			padapter->securitypriv.btkip_countermeasure = true;
1686 		} else {
1687 			/* wpa_supplicant is disabling tkip countermeasure. */
1688 			padapter->securitypriv.btkip_countermeasure = false;
1689 		}
1690 		break;
1691 	case IW_AUTH_DROP_UNENCRYPTED:
1692 		/* HACK:
1693 		 *
1694 		 * wpa_supplicant calls set_wpa_enabled when the driver
1695 		 * is loaded and unloaded, regardless of if WPA is being
1696 		 * used.  No other calls are made which can be used to
1697 		 * determine if encryption will be used or not prior to
1698 		 * association being expected.  If encryption is not being
1699 		 * used, drop_unencrypted is set to false, else true -- we
1700 		 * can use this to determine if the CAP_PRIVACY_ON bit should
1701 		 * be set.
1702 		 */
1703 		if (padapter->securitypriv.ndisencryptstatus ==
1704 		    Ndis802_11Encryption1Enabled) {
1705 			/* it means init value, or using wep,
1706 			 * ndisencryptstatus =
1707 			 *	Ndis802_11Encryption1Enabled,
1708 			 * then it needn't reset it;
1709 			 */
1710 			break;
1711 		}
1712 
1713 		if (paramval) {
1714 			padapter->securitypriv.ndisencryptstatus =
1715 				   Ndis802_11EncryptionDisabled;
1716 			padapter->securitypriv.PrivacyAlgrthm =
1717 				  _NO_PRIVACY_;
1718 			padapter->securitypriv.XGrpPrivacy =
1719 				  _NO_PRIVACY_;
1720 			padapter->securitypriv.AuthAlgrthm = 0;
1721 			padapter->securitypriv.ndisauthtype =
1722 				  Ndis802_11AuthModeOpen;
1723 		}
1724 		break;
1725 	case IW_AUTH_80211_AUTH_ALG:
1726 		ret = wpa_set_auth_algs(dev, (u32)paramval);
1727 		break;
1728 	case IW_AUTH_WPA_ENABLED:
1729 		break;
1730 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1731 		break;
1732 	case IW_AUTH_PRIVACY_INVOKED:
1733 		break;
1734 	default:
1735 		return -EOPNOTSUPP;
1736 	}
1737 
1738 	return ret;
1739 }
1740 
1741 static int r871x_wx_set_enc_ext(struct net_device *dev,
1742 			     struct iw_request_info *info,
1743 			     union iwreq_data *wrqu, char *extra)
1744 {
1745 	struct iw_point *pencoding = &wrqu->encoding;
1746 	struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1747 	struct ieee_param *param = NULL;
1748 	char *alg_name;
1749 	u32 param_len;
1750 	int ret = 0;
1751 
1752 	switch (pext->alg) {
1753 	case IW_ENCODE_ALG_NONE:
1754 		alg_name = "none";
1755 		break;
1756 	case IW_ENCODE_ALG_WEP:
1757 		alg_name = "WEP";
1758 		break;
1759 	case IW_ENCODE_ALG_TKIP:
1760 		alg_name = "TKIP";
1761 		break;
1762 	case IW_ENCODE_ALG_CCMP:
1763 		alg_name = "CCMP";
1764 		break;
1765 	default:
1766 		return -EINVAL;
1767 	}
1768 
1769 	param_len = sizeof(struct ieee_param) + pext->key_len;
1770 	param = kzalloc(param_len, GFP_ATOMIC);
1771 	if (!param)
1772 		return -ENOMEM;
1773 	param->cmd = IEEE_CMD_SET_ENCRYPTION;
1774 	eth_broadcast_addr(param->sta_addr);
1775 	strlcpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1776 	if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1777 		param->u.crypt.set_tx = 0;
1778 	if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1779 		param->u.crypt.set_tx = 1;
1780 	param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1781 	if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1782 		memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1783 	if (pext->key_len) {
1784 		param->u.crypt.key_len = pext->key_len;
1785 		memcpy(param + 1, pext + 1, pext->key_len);
1786 	}
1787 	ret = wpa_set_encryption(dev, param, param_len);
1788 	kfree(param);
1789 	return ret;
1790 }
1791 
1792 static int r871x_wx_get_nick(struct net_device *dev,
1793 			     struct iw_request_info *info,
1794 			     union iwreq_data *wrqu, char *extra)
1795 {
1796 	if (extra) {
1797 		wrqu->data.length = 8;
1798 		wrqu->data.flags = 1;
1799 		memcpy(extra, "rtl_wifi", 8);
1800 	}
1801 	return 0;
1802 }
1803 
1804 static int r8711_wx_read32(struct net_device *dev,
1805 				struct iw_request_info *info,
1806 				union iwreq_data *wrqu, char *keybuf)
1807 {
1808 	struct _adapter *padapter = netdev_priv(dev);
1809 	u32 addr;
1810 	u32 data32;
1811 
1812 	get_user(addr, (u32 __user *)wrqu->data.pointer);
1813 	data32 = r8712_read32(padapter, addr);
1814 	put_user(data32, (u32 __user *)wrqu->data.pointer);
1815 	wrqu->data.length = (data32 & 0xffff0000) >> 16;
1816 	wrqu->data.flags = data32 & 0xffff;
1817 	get_user(addr, (u32 __user *)wrqu->data.pointer);
1818 	return 0;
1819 }
1820 
1821 static int r8711_wx_write32(struct net_device *dev,
1822 				 struct iw_request_info *info,
1823 				 union iwreq_data *wrqu, char *keybuf)
1824 {
1825 	struct _adapter *padapter = netdev_priv(dev);
1826 	u32 addr;
1827 	u32 data32;
1828 
1829 	get_user(addr, (u32 __user *)wrqu->data.pointer);
1830 	data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
1831 	r8712_write32(padapter, addr, data32);
1832 	return 0;
1833 }
1834 
1835 static int dummy(struct net_device *dev,
1836 		struct iw_request_info *a,
1837 		union iwreq_data *wrqu, char *b)
1838 {
1839 	return -EINVAL;
1840 }
1841 
1842 static int r8711_drvext_hdl(struct net_device *dev,
1843 				struct iw_request_info *info,
1844 				union iwreq_data *wrqu, char *extra)
1845 {
1846 	return 0;
1847 }
1848 
1849 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1850 				struct iw_request_info *info,
1851 				union iwreq_data *wrqu, char *extra)
1852 {
1853 	struct _adapter *padapter = netdev_priv(dev);
1854 	struct iw_point *p = &wrqu->data;
1855 	struct oid_par_priv oid_par;
1856 	struct mp_ioctl_handler *phandler;
1857 	struct mp_ioctl_param *poidparam;
1858 	unsigned long BytesRead, BytesWritten, BytesNeeded;
1859 	u8 *pparmbuf, bset;
1860 	u16 len;
1861 	uint status;
1862 	int ret = 0;
1863 
1864 	if ((!p->length) || (!p->pointer))
1865 		return -EINVAL;
1866 
1867 	bset = (u8)(p->flags & 0xFFFF);
1868 	len = p->length;
1869 	pparmbuf = memdup_user(p->pointer, len);
1870 	if (IS_ERR(pparmbuf))
1871 		return PTR_ERR(pparmbuf);
1872 
1873 	poidparam = (struct mp_ioctl_param *)pparmbuf;
1874 	if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1875 		ret = -EINVAL;
1876 		goto _r871x_mp_ioctl_hdl_exit;
1877 	}
1878 	phandler = mp_ioctl_hdl + poidparam->subcode;
1879 	if ((phandler->paramsize != 0) &&
1880 	    (poidparam->len < phandler->paramsize)) {
1881 		ret = -EINVAL;
1882 		goto _r871x_mp_ioctl_hdl_exit;
1883 	}
1884 	if (phandler->oid == 0 && phandler->handler) {
1885 		status = phandler->handler(&oid_par);
1886 	} else if (phandler->handler) {
1887 		oid_par.adapter_context = padapter;
1888 		oid_par.oid = phandler->oid;
1889 		oid_par.information_buf = poidparam->data;
1890 		oid_par.information_buf_len = poidparam->len;
1891 		oid_par.dbg = 0;
1892 		BytesWritten = 0;
1893 		BytesNeeded = 0;
1894 		if (bset) {
1895 			oid_par.bytes_rw = &BytesRead;
1896 			oid_par.bytes_needed = &BytesNeeded;
1897 			oid_par.type_of_oid = SET_OID;
1898 		} else {
1899 			oid_par.bytes_rw = &BytesWritten;
1900 			oid_par.bytes_needed = &BytesNeeded;
1901 			oid_par.type_of_oid = QUERY_OID;
1902 		}
1903 		status = phandler->handler(&oid_par);
1904 		/* todo:check status, BytesNeeded, etc. */
1905 	} else {
1906 		netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1907 			    __func__, poidparam->subcode, phandler->oid,
1908 			    phandler->handler);
1909 		ret = -EFAULT;
1910 		goto _r871x_mp_ioctl_hdl_exit;
1911 	}
1912 	if (bset == 0x00) { /* query info */
1913 		if (copy_to_user(p->pointer, pparmbuf, len))
1914 			ret = -EFAULT;
1915 	}
1916 	if (status) {
1917 		ret = -EFAULT;
1918 		goto _r871x_mp_ioctl_hdl_exit;
1919 	}
1920 _r871x_mp_ioctl_hdl_exit:
1921 	kfree(pparmbuf);
1922 	return ret;
1923 }
1924 
1925 static int r871x_get_ap_info(struct net_device *dev,
1926 				struct iw_request_info *info,
1927 				union iwreq_data *wrqu, char *extra)
1928 {
1929 	struct _adapter *padapter = netdev_priv(dev);
1930 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1931 	struct  __queue *queue = &pmlmepriv->scanned_queue;
1932 	struct iw_point *pdata = &wrqu->data;
1933 	struct wlan_network *pnetwork = NULL;
1934 	u32 cnt = 0, wpa_ielen;
1935 	unsigned long irqL;
1936 	struct list_head *plist, *phead;
1937 	unsigned char *pbuf;
1938 	u8 bssid[ETH_ALEN];
1939 	char data[33];
1940 
1941 	if (padapter->driver_stopped || (pdata == NULL))
1942 		return -EINVAL;
1943 	while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1944 			     _FW_UNDER_LINKING)) {
1945 		msleep(30);
1946 		cnt++;
1947 		if (cnt > 100)
1948 			break;
1949 	}
1950 	pdata->flags = 0;
1951 	if (pdata->length < 32)
1952 		return -EINVAL;
1953 	if (copy_from_user(data, pdata->pointer, 32))
1954 		return -EINVAL;
1955 	data[32] = 0;
1956 
1957 	spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
1958 	phead = &queue->queue;
1959 	plist = phead->next;
1960 	while (1) {
1961 		if (end_of_queue_search(phead, plist))
1962 			break;
1963 		pnetwork = container_of(plist, struct wlan_network, list);
1964 		if (!mac_pton(data, bssid)) {
1965 			netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
1966 				    (u8 *)data);
1967 			spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
1968 					       irqL);
1969 			return -EINVAL;
1970 		}
1971 		netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
1972 		if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
1973 			/* BSSID match, then check if supporting wpa/wpa2 */
1974 			pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
1975 			       &wpa_ielen, pnetwork->network.IELength - 12);
1976 			if (pbuf && (wpa_ielen > 0)) {
1977 				pdata->flags = 1;
1978 				break;
1979 			}
1980 			pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
1981 			       &wpa_ielen, pnetwork->network.IELength - 12);
1982 			if (pbuf && (wpa_ielen > 0)) {
1983 				pdata->flags = 2;
1984 				break;
1985 			}
1986 		}
1987 		plist = plist->next;
1988 	}
1989 	spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
1990 	if (pdata->length >= 34) {
1991 		if (copy_to_user((u8 __user *)pdata->pointer + 32,
1992 		    (u8 *)&pdata->flags, 1))
1993 			return -EINVAL;
1994 	}
1995 	return 0;
1996 }
1997 
1998 static int r871x_set_pid(struct net_device *dev,
1999 				struct iw_request_info *info,
2000 				union iwreq_data *wrqu, char *extra)
2001 {
2002 	struct _adapter *padapter = netdev_priv(dev);
2003 	struct iw_point *pdata = &wrqu->data;
2004 
2005 	if ((padapter->driver_stopped) || (pdata == NULL))
2006 		return -EINVAL;
2007 	if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2008 		return -EINVAL;
2009 	return 0;
2010 }
2011 
2012 static int r871x_set_chplan(struct net_device *dev,
2013 				struct iw_request_info *info,
2014 				union iwreq_data *wrqu, char *extra)
2015 {
2016 	int ret = 0;
2017 	struct _adapter *padapter = netdev_priv(dev);
2018 	struct iw_point *pdata = &wrqu->data;
2019 	int ch_plan = -1;
2020 
2021 	if ((padapter->driver_stopped) || (pdata == NULL)) {
2022 		ret = -EINVAL;
2023 		goto exit;
2024 	}
2025 	ch_plan = (int)*extra;
2026 	r8712_set_chplan_cmd(padapter, ch_plan);
2027 
2028 exit:
2029 
2030 	return ret;
2031 }
2032 
2033 static int r871x_wps_start(struct net_device *dev,
2034 			   struct iw_request_info *info,
2035 			   union iwreq_data *wrqu, char *extra)
2036 {
2037 	struct _adapter *padapter = netdev_priv(dev);
2038 	struct iw_point *pdata = &wrqu->data;
2039 	u32   u32wps_start = 0;
2040 
2041 	if ((padapter->driver_stopped) || (pdata == NULL))
2042 		return -EINVAL;
2043 	if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2044 		return -EFAULT;
2045 	if (u32wps_start == 0)
2046 		u32wps_start = *extra;
2047 	if (u32wps_start == 1) /* WPS Start */
2048 		padapter->ledpriv.LedControlHandler(padapter,
2049 			   LED_CTL_START_WPS);
2050 	else if (u32wps_start == 2) /* WPS Stop because of wps success */
2051 		padapter->ledpriv.LedControlHandler(padapter,
2052 			   LED_CTL_STOP_WPS);
2053 	else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2054 		padapter->ledpriv.LedControlHandler(padapter,
2055 			   LED_CTL_STOP_WPS_FAIL);
2056 	return 0;
2057 }
2058 
2059 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2060 {
2061 	struct _adapter *padapter = netdev_priv(dev);
2062 
2063 	switch (name) {
2064 	case IEEE_PARAM_WPA_ENABLED:
2065 		padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2066 		switch ((value) & 0xff) {
2067 		case 1: /* WPA */
2068 			padapter->securitypriv.ndisauthtype =
2069 				Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2070 			padapter->securitypriv.ndisencryptstatus =
2071 				Ndis802_11Encryption2Enabled;
2072 			break;
2073 		case 2: /* WPA2 */
2074 			padapter->securitypriv.ndisauthtype =
2075 				Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2076 			padapter->securitypriv.ndisencryptstatus =
2077 				Ndis802_11Encryption3Enabled;
2078 			break;
2079 		}
2080 		break;
2081 	case IEEE_PARAM_TKIP_COUNTERMEASURES:
2082 		break;
2083 	case IEEE_PARAM_DROP_UNENCRYPTED:
2084 		/* HACK:
2085 		 *
2086 		 * wpa_supplicant calls set_wpa_enabled when the driver
2087 		 * is loaded and unloaded, regardless of if WPA is being
2088 		 * used.  No other calls are made which can be used to
2089 		 * determine if encryption will be used or not prior to
2090 		 * association being expected.  If encryption is not being
2091 		 * used, drop_unencrypted is set to false, else true -- we
2092 		 * can use this to determine if the CAP_PRIVACY_ON bit should
2093 		 * be set.
2094 		 */
2095 		break;
2096 	case IEEE_PARAM_PRIVACY_INVOKED:
2097 		break;
2098 	case IEEE_PARAM_AUTH_ALGS:
2099 		return wpa_set_auth_algs(dev, value);
2100 	case IEEE_PARAM_IEEE_802_1X:
2101 		break;
2102 	case IEEE_PARAM_WPAX_SELECT:
2103 		/* added for WPA2 mixed mode */
2104 		break;
2105 	default:
2106 		return -EOPNOTSUPP;
2107 	}
2108 	return 0;
2109 }
2110 
2111 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2112 {
2113 	struct _adapter *padapter = netdev_priv(dev);
2114 
2115 	switch (command) {
2116 	case IEEE_MLME_STA_DEAUTH:
2117 		if (!r8712_set_802_11_disassociate(padapter))
2118 			return -1;
2119 		break;
2120 	case IEEE_MLME_STA_DISASSOC:
2121 		if (!r8712_set_802_11_disassociate(padapter))
2122 			return -1;
2123 		break;
2124 	default:
2125 		return -EOPNOTSUPP;
2126 	}
2127 	return 0;
2128 }
2129 
2130 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2131 {
2132 	struct ieee_param *param;
2133 	int ret = 0;
2134 	struct _adapter *padapter = netdev_priv(dev);
2135 
2136 	if (p->length < sizeof(struct ieee_param) || !p->pointer)
2137 		return -EINVAL;
2138 	param = memdup_user(p->pointer, p->length);
2139 	if (IS_ERR(param))
2140 		return PTR_ERR(param);
2141 	switch (param->cmd) {
2142 	case IEEE_CMD_SET_WPA_PARAM:
2143 		ret = wpa_set_param(dev, param->u.wpa_param.name,
2144 		      param->u.wpa_param.value);
2145 		break;
2146 	case IEEE_CMD_SET_WPA_IE:
2147 		ret =  r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2148 		       (u16)param->u.wpa_ie.len);
2149 		break;
2150 	case IEEE_CMD_SET_ENCRYPTION:
2151 		ret = wpa_set_encryption(dev, param, p->length);
2152 		break;
2153 	case IEEE_CMD_MLME:
2154 		ret = wpa_mlme(dev, param->u.mlme.command,
2155 		      param->u.mlme.reason_code);
2156 		break;
2157 	default:
2158 		ret = -EOPNOTSUPP;
2159 		break;
2160 	}
2161 	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2162 		ret = -EFAULT;
2163 	kfree(param);
2164 	return ret;
2165 }
2166 
2167 /* based on "driver_ipw" and for hostapd */
2168 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2169 {
2170 	struct iwreq *wrq = (struct iwreq *)rq;
2171 
2172 	switch (cmd) {
2173 	case RTL_IOCTL_WPA_SUPPLICANT:
2174 		return wpa_supplicant_ioctl(dev, &wrq->u.data);
2175 	default:
2176 		return -EOPNOTSUPP;
2177 	}
2178 	return 0;
2179 }
2180 
2181 static iw_handler r8711_handlers[] = {
2182 	NULL,				/* SIOCSIWCOMMIT */
2183 	r8711_wx_get_name,		/* SIOCGIWNAME */
2184 	dummy,				/* SIOCSIWNWID */
2185 	dummy,				/* SIOCGIWNWID */
2186 	r8711_wx_set_freq,		/* SIOCSIWFREQ */
2187 	r8711_wx_get_freq,		/* SIOCGIWFREQ */
2188 	r8711_wx_set_mode,		/* SIOCSIWMODE */
2189 	r8711_wx_get_mode,		/* SIOCGIWMODE */
2190 	dummy,				/* SIOCSIWSENS */
2191 	r8711_wx_get_sens,		/* SIOCGIWSENS */
2192 	NULL,				/* SIOCSIWRANGE */
2193 	r8711_wx_get_range,		/* SIOCGIWRANGE */
2194 	r871x_wx_set_priv,		/* SIOCSIWPRIV */
2195 	NULL,				/* SIOCGIWPRIV */
2196 	NULL,				/* SIOCSIWSTATS */
2197 	NULL,				/* SIOCGIWSTATS */
2198 	dummy,				/* SIOCSIWSPY */
2199 	dummy,				/* SIOCGIWSPY */
2200 	NULL,				/* SIOCGIWTHRSPY */
2201 	NULL,				/* SIOCWIWTHRSPY */
2202 	r8711_wx_set_wap,		/* SIOCSIWAP */
2203 	r8711_wx_get_wap,		/* SIOCGIWAP */
2204 	r871x_wx_set_mlme,		/* request MLME operation;
2205 					 *  uses struct iw_mlme
2206 					 */
2207 	dummy,				/* SIOCGIWAPLIST -- deprecated */
2208 	r8711_wx_set_scan,		/* SIOCSIWSCAN */
2209 	r8711_wx_get_scan,		/* SIOCGIWSCAN */
2210 	r8711_wx_set_essid,		/* SIOCSIWESSID */
2211 	r8711_wx_get_essid,		/* SIOCGIWESSID */
2212 	dummy,				/* SIOCSIWNICKN */
2213 	r871x_wx_get_nick,		/* SIOCGIWNICKN */
2214 	NULL,				/* -- hole -- */
2215 	NULL,				/* -- hole -- */
2216 	r8711_wx_set_rate,		/* SIOCSIWRATE */
2217 	r8711_wx_get_rate,		/* SIOCGIWRATE */
2218 	dummy,				/* SIOCSIWRTS */
2219 	r8711_wx_get_rts,		/* SIOCGIWRTS */
2220 	r8711_wx_set_frag,		/* SIOCSIWFRAG */
2221 	r8711_wx_get_frag,		/* SIOCGIWFRAG */
2222 	dummy,				/* SIOCSIWTXPOW */
2223 	dummy,				/* SIOCGIWTXPOW */
2224 	dummy,				/* SIOCSIWRETRY */
2225 	r8711_wx_get_retry,		/* SIOCGIWRETRY */
2226 	r8711_wx_set_enc,		/* SIOCSIWENCODE */
2227 	r8711_wx_get_enc,		/* SIOCGIWENCODE */
2228 	dummy,				/* SIOCSIWPOWER */
2229 	r8711_wx_get_power,		/* SIOCGIWPOWER */
2230 	NULL,				/*---hole---*/
2231 	NULL,				/*---hole---*/
2232 	r871x_wx_set_gen_ie,		/* SIOCSIWGENIE */
2233 	NULL,				/* SIOCGIWGENIE */
2234 	r871x_wx_set_auth,		/* SIOCSIWAUTH */
2235 	NULL,				/* SIOCGIWAUTH */
2236 	r871x_wx_set_enc_ext,		/* SIOCSIWENCODEEXT */
2237 	NULL,				/* SIOCGIWENCODEEXT */
2238 	r871x_wx_set_pmkid,		/* SIOCSIWPMKSA */
2239 	NULL,				/*---hole---*/
2240 };
2241 
2242 static const struct iw_priv_args r8711_private_args[] = {
2243 	{
2244 		SIOCIWFIRSTPRIV + 0x0,
2245 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2246 	},
2247 	{
2248 		SIOCIWFIRSTPRIV + 0x1,
2249 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2250 	},
2251 	{
2252 		SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2253 	},
2254 	{
2255 		SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2256 	},
2257 	{
2258 		SIOCIWFIRSTPRIV + 0x4,
2259 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2260 	},
2261 	{
2262 		SIOCIWFIRSTPRIV + 0x5,
2263 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2264 	},
2265 	{
2266 		SIOCIWFIRSTPRIV + 0x6,
2267 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2268 	},
2269 	{
2270 		SIOCIWFIRSTPRIV + 0x7,
2271 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2272 	}
2273 };
2274 
2275 static iw_handler r8711_private_handler[] = {
2276 	r8711_wx_read32,
2277 	r8711_wx_write32,
2278 	r8711_drvext_hdl,
2279 	r871x_mp_ioctl_hdl,
2280 	r871x_get_ap_info, /*for MM DTV platform*/
2281 	r871x_set_pid,
2282 	r871x_wps_start,
2283 	r871x_set_chplan
2284 };
2285 
2286 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2287 {
2288 	struct _adapter *padapter = netdev_priv(dev);
2289 	struct iw_statistics *piwstats = &padapter->iwstats;
2290 	int tmp_level = 0;
2291 	int tmp_qual = 0;
2292 	int tmp_noise = 0;
2293 
2294 	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2295 		piwstats->qual.qual = 0;
2296 		piwstats->qual.level = 0;
2297 		piwstats->qual.noise = 0;
2298 	} else {
2299 		/* show percentage, we need transfer dbm to original value. */
2300 		tmp_level = padapter->recvpriv.fw_rssi;
2301 		tmp_qual = padapter->recvpriv.signal;
2302 		tmp_noise = padapter->recvpriv.noise;
2303 		piwstats->qual.level = tmp_level;
2304 		piwstats->qual.qual = tmp_qual;
2305 		piwstats->qual.noise = tmp_noise;
2306 	}
2307 	piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2308 	return &padapter->iwstats;
2309 }
2310 
2311 struct iw_handler_def r871x_handlers_def = {
2312 	.standard = r8711_handlers,
2313 	.num_standard = ARRAY_SIZE(r8711_handlers),
2314 	.private = r8711_private_handler,
2315 	.private_args = (struct iw_priv_args *)r8711_private_args,
2316 	.num_private = ARRAY_SIZE(r8711_private_handler),
2317 	.num_private_args = sizeof(r8711_private_args) /
2318 			    sizeof(struct iw_priv_args),
2319 	.get_wireless_stats = r871x_get_wireless_stats
2320 };
2321