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