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