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