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