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