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