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