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