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