1 /******************************************************************************
2 * rtl871x_ioctl_linux.c
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
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.
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
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
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.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>
47 #include <linux/semaphore.h>
48 #include <net/iw_handler.h>
49 #include <linux/if_arp.h>
51 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
53 #define SCAN_ITEM_SIZE 768
54 #define MAX_CUSTOM_LEN 64
58 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
59 6000000, 9000000, 12000000, 18000000,
60 24000000, 36000000, 48000000, 54000000};
62 static const long ieee80211_wlan_frequencies[] = {
63 2412, 2417, 2422, 2427,
64 2432, 2437, 2442, 2447,
65 2452, 2457, 2462, 2467,
69 static const char * const iw_operation_mode[] = {
70 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
75 * hwaddr_aton - Convert ASCII string to MAC address
76 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
77 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
78 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
80 static int hwaddr_aton_i(const char *txt, u8 *addr)
84 for (i = 0; i < 6; i++) {
87 a = hex_to_bin(*txt++);
90 b = hex_to_bin(*txt++);
93 *addr++ = (a << 4) | b;
94 if (i < 5 && *txt++ != ':')
100 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
102 union iwreq_data wrqu;
103 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
105 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
106 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
108 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
111 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
113 union iwreq_data wrqu;
115 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
116 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
117 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
120 static inline void handle_pairwise_key(struct sta_info *psta,
121 struct ieee_param *param,
122 struct _adapter *padapter)
125 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
126 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
127 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
128 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
130 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
132 padapter->securitypriv. busetkipkey = false;
133 _set_timer(&padapter->securitypriv.tkip_timer, 50);
135 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
138 static inline void handle_group_key(struct ieee_param *param,
139 struct _adapter *padapter)
141 if (0 < param->u.crypt.idx &&
142 param->u.crypt.idx < 3) {
143 /* group key idx is 1 or 2 */
144 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
145 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
146 > 16 ? 16 : param->u.crypt.key_len));
147 memcpy(padapter->securitypriv.XGrptxmickey[param->
148 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
149 memcpy(padapter->securitypriv. XGrprxmickey[param->
150 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
151 padapter->securitypriv.binstallGrpkey = true;
152 r8712_set_key(padapter, &padapter->securitypriv,
154 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
155 if (padapter->registrypriv.power_mgnt != padapter->
156 pwrctrlpriv.pwr_mode)
157 _set_timer(&(padapter->mlmepriv.dhcp_timer),
163 static inline char *translate_scan(struct _adapter *padapter,
164 struct iw_request_info *info,
165 struct wlan_network *pnetwork,
166 char *start, char *stop)
169 struct ieee80211_ht_cap *pht_capie;
172 u32 i = 0, ht_ielen = 0;
173 u16 cap, ht_cap = false, mcs_rate;
174 u8 rssi, bw_40MHz = 0, short_GI = 0;
176 if ((pnetwork->network.Configuration.DSConfig < 1) ||
177 (pnetwork->network.Configuration.DSConfig > 14)) {
178 if (pnetwork->network.Configuration.DSConfig < 1)
179 pnetwork->network.Configuration.DSConfig = 1;
181 pnetwork->network.Configuration.DSConfig = 14;
185 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
186 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
187 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
189 iwe.cmd = SIOCGIWESSID;
190 iwe.u.data.flags = 1;
191 iwe.u.data.length = (u16)min((u16)pnetwork->network.Ssid.SsidLength,
193 start = iwe_stream_add_point(info, start, stop, &iwe,
194 pnetwork->network.Ssid.Ssid);
195 /* parsing HT_CAP_IE */
196 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
197 &ht_ielen, pnetwork->network.IELength - 12);
198 if (p && ht_ielen > 0) {
200 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
201 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
202 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
204 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
205 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
207 /* Add the protocol name */
208 iwe.cmd = SIOCGIWNAME;
209 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
210 SupportedRates)) == true) {
212 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
214 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
215 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
216 SupportedRates)) == true) {
218 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
220 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
223 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
225 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
227 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
229 iwe.cmd = SIOCGIWMODE;
230 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
232 cap = le16_to_cpu(cap);
233 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
234 if (cap & WLAN_CAPABILITY_BSS)
235 iwe.u.mode = (u32)IW_MODE_MASTER;
237 iwe.u.mode = (u32)IW_MODE_ADHOC;
238 start = iwe_stream_add_event(info, start, stop, &iwe,
241 /* Add frequency/channel */
242 iwe.cmd = SIOCGIWFREQ;
244 /* check legal index */
245 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
246 if (dsconfig >= 1 && dsconfig <= sizeof(
247 ieee80211_wlan_frequencies) / sizeof(long))
248 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
249 pnetwork->network.Configuration.
250 DSConfig - 1] * 100000);
254 iwe.u.freq.e = (s16)1;
255 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
256 start = iwe_stream_add_event(info, start, stop, &iwe,
258 /* Add encryption capability */
259 iwe.cmd = SIOCGIWENCODE;
260 if (cap & WLAN_CAPABILITY_PRIVACY)
261 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
264 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
265 iwe.u.data.length = (u16)0;
266 start = iwe_stream_add_point(info, start, stop, &iwe,
267 pnetwork->network.Ssid.Ssid);
268 /*Add basic and extended rates */
269 current_val = start + iwe_stream_lcp_len(info);
270 iwe.cmd = SIOCGIWRATE;
271 iwe.u.bitrate.fixed = 0;
272 iwe.u.bitrate.disabled = 0;
273 iwe.u.bitrate.value = 0;
275 while (pnetwork->network.SupportedRates[i] != 0) {
276 /* Bit rate given in 500 kb/s units */
277 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
279 current_val = iwe_stream_add_value(info, start, current_val,
280 stop, &iwe, IW_EV_PARAM_LEN);
282 /* Check if we added any event */
283 if ((current_val - start) > iwe_stream_lcp_len(info))
285 /* parsing WPA/WPA2 IE */
287 u8 buf[MAX_WPA_IE_LEN];
288 u8 wpa_ie[255], rsn_ie[255];
289 u16 wpa_len = 0, rsn_len = 0;
292 out_len = r8712_get_sec_ie(pnetwork->network.IEs,
294 IELength, rsn_ie, &rsn_len,
297 memset(buf, 0, MAX_WPA_IE_LEN);
298 n = sprintf(buf, "wpa_ie=");
299 for (i = 0; i < wpa_len; i++) {
300 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
302 if (n >= MAX_WPA_IE_LEN)
305 memset(&iwe, 0, sizeof(iwe));
306 iwe.cmd = IWEVCUSTOM;
307 iwe.u.data.length = (u16)strlen(buf);
308 start = iwe_stream_add_point(info, start, stop,
310 memset(&iwe, 0, sizeof(iwe));
312 iwe.u.data.length = (u16)wpa_len;
313 start = iwe_stream_add_point(info, start, stop,
317 memset(buf, 0, MAX_WPA_IE_LEN);
318 n = sprintf(buf, "rsn_ie=");
319 for (i = 0; i < rsn_len; i++) {
320 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
322 if (n >= MAX_WPA_IE_LEN)
325 memset(&iwe, 0, sizeof(iwe));
326 iwe.cmd = IWEVCUSTOM;
327 iwe.u.data.length = strlen(buf);
328 start = iwe_stream_add_point(info, start, stop,
330 memset(&iwe, 0, sizeof(iwe));
332 iwe.u.data.length = rsn_len;
333 start = iwe_stream_add_point(info, start, stop, &iwe,
338 { /* parsing WPS IE */
342 if (r8712_get_wps_ie(pnetwork->network.IEs,
343 pnetwork->network.IELength,
344 wps_ie, &wps_ielen) == true) {
347 iwe.u.data.length = (u16)wps_ielen;
348 start = iwe_stream_add_point(info, start, stop,
353 /* Add quality statistics */
355 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
356 /* we only update signal_level (signal strength) that is rssi. */
357 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
358 IW_QUAL_NOISE_INVALID);
359 iwe.u.qual.level = rssi; /* signal strength */
360 iwe.u.qual.qual = 0; /* signal quality */
361 iwe.u.qual.noise = 0; /* noise level */
362 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
363 /* how to translate rssi to ?% */
367 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
369 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
372 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
373 padapter->securitypriv.ndisencryptstatus =
374 Ndis802_11Encryption1Enabled;
375 padapter->securitypriv.ndisauthtype =
376 Ndis802_11AuthModeAutoSwitch;
377 padapter->securitypriv.AuthAlgrthm = 3;
378 } else if (value & AUTH_ALG_SHARED_KEY) {
379 padapter->securitypriv.ndisencryptstatus =
380 Ndis802_11Encryption1Enabled;
381 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
382 padapter->securitypriv.AuthAlgrthm = 1;
383 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
384 if (padapter->securitypriv.ndisauthtype <
385 Ndis802_11AuthModeWPAPSK) {
386 padapter->securitypriv.ndisauthtype =
387 Ndis802_11AuthModeOpen;
388 padapter->securitypriv.AuthAlgrthm = 0;
395 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
399 u32 wep_key_idx, wep_key_len = 0;
400 struct NDIS_802_11_WEP *pwep = NULL;
401 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
402 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
403 struct security_priv *psecuritypriv = &padapter->securitypriv;
405 param->u.crypt.err = 0;
406 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
407 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
408 param->u.crypt.key_len)
410 if (is_broadcast_ether_addr(param->sta_addr)) {
411 if (param->u.crypt.idx >= WEP_KEYS) {
412 /* for large key indices, set the default (0) */
413 param->u.crypt.idx = 0;
417 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
418 printk(KERN_INFO "r8712u: wpa_set_encryption, crypt.alg ="
420 padapter->securitypriv.ndisencryptstatus =
421 Ndis802_11Encryption1Enabled;
422 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
423 padapter->securitypriv.XGrpPrivacy = _WEP40_;
424 wep_key_idx = param->u.crypt.idx;
425 wep_key_len = param->u.crypt.key_len;
426 if (wep_key_idx >= WEP_KEYS)
428 if (wep_key_len > 0) {
429 wep_key_len = wep_key_len <= 5 ? 5 : 13;
430 pwep = (struct NDIS_802_11_WEP *)_malloc((u32)
432 FIELD_OFFSET(struct NDIS_802_11_WEP,
436 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
437 pwep->KeyLength = wep_key_len;
438 pwep->Length = wep_key_len +
439 FIELD_OFFSET(struct NDIS_802_11_WEP,
441 if (wep_key_len == 13) {
442 padapter->securitypriv.PrivacyAlgrthm =
444 padapter->securitypriv.XGrpPrivacy =
449 pwep->KeyIndex = wep_key_idx;
450 pwep->KeyIndex |= 0x80000000;
451 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
452 if (param->u.crypt.set_tx) {
453 if (r8712_set_802_11_add_wep(padapter, pwep) ==
457 /* don't update "psecuritypriv->PrivacyAlgrthm" and
458 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
459 * r8712_set_key to fw/cam
461 if (wep_key_idx >= WEP_KEYS) {
465 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
466 skey[0]), pwep->KeyMaterial,
468 psecuritypriv->DefKeylen[wep_key_idx] =
470 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
474 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
475 struct sta_info *psta, *pbcmc_sta;
476 struct sta_priv *pstapriv = &padapter->stapriv;
478 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
479 WIFI_MP_STATE) == true) { /* sta mode */
480 psta = r8712_get_stainfo(pstapriv,
481 get_bssid(pmlmepriv));
483 psta->ieee8021x_blocked = false;
484 if ((padapter->securitypriv.ndisencryptstatus ==
485 Ndis802_11Encryption2Enabled) ||
486 (padapter->securitypriv.ndisencryptstatus ==
487 Ndis802_11Encryption3Enabled))
488 psta->XPrivacy = padapter->
489 securitypriv.PrivacyAlgrthm;
490 if (param->u.crypt.set_tx == 1)
491 handle_pairwise_key(psta, param,
494 handle_group_key(param, padapter);
496 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
498 pbcmc_sta->ieee8021x_blocked = false;
499 if ((padapter->securitypriv.ndisencryptstatus ==
500 Ndis802_11Encryption2Enabled) ||
501 (padapter->securitypriv.ndisencryptstatus ==
502 Ndis802_11Encryption3Enabled))
503 pbcmc_sta->XPrivacy =
504 padapter->securitypriv.
514 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
515 unsigned short ielen)
517 u8 *buf = NULL, *pos = NULL;
518 int group_cipher = 0, pairwise_cipher = 0;
521 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
524 buf = _malloc(ielen);
527 memcpy(buf, pie , ielen);
529 if (ielen < RSN_HEADER_LEN) {
533 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
534 &pairwise_cipher) == _SUCCESS) {
535 padapter->securitypriv.AuthAlgrthm = 2;
536 padapter->securitypriv.ndisauthtype =
537 Ndis802_11AuthModeWPAPSK;
539 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
540 &pairwise_cipher) == _SUCCESS) {
541 padapter->securitypriv.AuthAlgrthm = 2;
542 padapter->securitypriv.ndisauthtype =
543 Ndis802_11AuthModeWPA2PSK;
545 switch (group_cipher) {
546 case WPA_CIPHER_NONE:
547 padapter->securitypriv.XGrpPrivacy =
549 padapter->securitypriv.ndisencryptstatus =
550 Ndis802_11EncryptionDisabled;
552 case WPA_CIPHER_WEP40:
553 padapter->securitypriv.XGrpPrivacy = _WEP40_;
554 padapter->securitypriv.ndisencryptstatus =
555 Ndis802_11Encryption1Enabled;
557 case WPA_CIPHER_TKIP:
558 padapter->securitypriv.XGrpPrivacy = _TKIP_;
559 padapter->securitypriv.ndisencryptstatus =
560 Ndis802_11Encryption2Enabled;
562 case WPA_CIPHER_CCMP:
563 padapter->securitypriv.XGrpPrivacy = _AES_;
564 padapter->securitypriv.ndisencryptstatus =
565 Ndis802_11Encryption3Enabled;
567 case WPA_CIPHER_WEP104:
568 padapter->securitypriv.XGrpPrivacy = _WEP104_;
569 padapter->securitypriv.ndisencryptstatus =
570 Ndis802_11Encryption1Enabled;
573 switch (pairwise_cipher) {
574 case WPA_CIPHER_NONE:
575 padapter->securitypriv.PrivacyAlgrthm =
577 padapter->securitypriv.ndisencryptstatus =
578 Ndis802_11EncryptionDisabled;
580 case WPA_CIPHER_WEP40:
581 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
582 padapter->securitypriv.ndisencryptstatus =
583 Ndis802_11Encryption1Enabled;
585 case WPA_CIPHER_TKIP:
586 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
587 padapter->securitypriv.ndisencryptstatus =
588 Ndis802_11Encryption2Enabled;
590 case WPA_CIPHER_CCMP:
591 padapter->securitypriv.PrivacyAlgrthm = _AES_;
592 padapter->securitypriv.ndisencryptstatus =
593 Ndis802_11Encryption3Enabled;
595 case WPA_CIPHER_WEP104:
596 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
597 padapter->securitypriv.ndisencryptstatus =
598 Ndis802_11Encryption1Enabled;
601 padapter->securitypriv.wps_phase = false;
604 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
606 while (cnt < ielen) {
609 if ((eid == _VENDOR_SPECIFIC_IE_) &&
610 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
611 printk(KERN_INFO "r8712u: "
613 padapter->securitypriv.wps_ie_len =
615 (MAX_WPA_IE_LEN << 2)) ?
617 (MAX_WPA_IE_LEN << 2);
618 memcpy(padapter->securitypriv.wps_ie,
620 padapter->securitypriv.wps_ie_len);
621 padapter->securitypriv.wps_phase =
623 printk(KERN_INFO "r8712u: SET WPS_IE,"
624 " wps_phase==true\n");
628 cnt += buf[cnt + 1] + 2;
637 static int r8711_wx_get_name(struct net_device *dev,
638 struct iw_request_info *info,
639 union iwreq_data *wrqu, char *extra)
641 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
645 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
646 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
647 NDIS_802_11_RATES_EX *prates = NULL;
649 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
651 /* parsing HT_CAP_IE */
652 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
653 &ht_ielen, pcur_bss->IELength - 12);
654 if (p && ht_ielen > 0)
656 prates = &pcur_bss->SupportedRates;
657 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
659 snprintf(wrqu->name, IFNAMSIZ,
662 snprintf(wrqu->name, IFNAMSIZ,
664 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
666 snprintf(wrqu->name, IFNAMSIZ,
669 snprintf(wrqu->name, IFNAMSIZ,
673 snprintf(wrqu->name, IFNAMSIZ,
676 snprintf(wrqu->name, IFNAMSIZ,
680 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
684 static const long frequency_list[] = {
685 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
686 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
687 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
688 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
689 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
693 static int r8711_wx_set_freq(struct net_device *dev,
694 struct iw_request_info *info,
695 union iwreq_data *wrqu, char *extra)
697 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
698 struct iw_freq *fwrq = &wrqu->freq;
701 /* If setting by frequency, convert to a channel */
702 if ((fwrq->e == 1) &&
703 (fwrq->m >= (int) 2.412e8) &&
704 (fwrq->m <= (int) 2.487e8)) {
705 int f = fwrq->m / 100000;
707 while ((c < 14) && (f != frequency_list[c]))
712 /* Setting by channel number */
713 if ((fwrq->m > 14) || (fwrq->e > 0))
716 int channel = fwrq->m;
717 if ((channel < 1) || (channel > 14))
720 /* Yes ! We can set it !!! */
721 padapter->registrypriv.channel = channel;
727 static int r8711_wx_get_freq(struct net_device *dev,
728 struct iw_request_info *info,
729 union iwreq_data *wrqu, char *extra)
731 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
732 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
733 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
735 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
736 wrqu->freq.m = ieee80211_wlan_frequencies[
737 pcur_bss->Configuration.DSConfig-1] * 100000;
739 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
746 static int r8711_wx_set_mode(struct net_device *dev,
747 struct iw_request_info *a,
748 union iwreq_data *wrqu, char *b)
750 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
751 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
753 switch (wrqu->mode) {
755 networkType = Ndis802_11AutoUnknown;
758 networkType = Ndis802_11IBSS;
761 networkType = Ndis802_11APMode;
764 networkType = Ndis802_11Infrastructure;
769 if (Ndis802_11APMode == networkType)
770 r8712_setopmode_cmd(padapter, networkType);
772 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
774 r8712_set_802_11_infrastructure_mode(padapter, networkType);
778 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
779 union iwreq_data *wrqu, char *b)
781 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
782 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
784 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
785 wrqu->mode = IW_MODE_INFRA;
786 else if (check_fwstate(pmlmepriv,
787 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
788 wrqu->mode = IW_MODE_ADHOC;
789 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
790 wrqu->mode = IW_MODE_MASTER;
792 wrqu->mode = IW_MODE_AUTO;
796 static int r871x_wx_set_pmkid(struct net_device *dev,
797 struct iw_request_info *a,
798 union iwreq_data *wrqu, char *extra)
800 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
801 struct security_priv *psecuritypriv = &padapter->securitypriv;
802 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
803 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
804 u8 strIssueBssid[ETH_ALEN] = {0x00};
805 u8 j, blInserted = false;
806 int intReturn = false;
809 There are the BSSID information in the bssid.sa_data array.
810 If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
811 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
812 wpa_supplicant wants to add a PMKID/BSSID to driver.
813 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
814 remove a PMKID/BSSID from driver.
818 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
821 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
826 /* overwrite PMKID */
827 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
828 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
829 strIssueBssid, ETH_ALEN)) {
830 /* BSSID is matched, the same AP => rewrite
832 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid:"
833 " BSSID exists in the PMKList.\n");
834 memcpy(psecuritypriv->PMKIDList[j].PMKID,
835 pPMK->pmkid, IW_PMKID_LEN);
836 psecuritypriv->PMKIDList[j].bUsed = true;
837 psecuritypriv->PMKIDIndex = j + 1;
843 /* Find a new entry */
844 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: Use the"
845 " new entry index = %d for this PMKID.\n",
846 psecuritypriv->PMKIDIndex);
847 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
848 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
849 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
850 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
851 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
853 psecuritypriv->PMKIDIndex++ ;
854 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
855 psecuritypriv->PMKIDIndex = 0;
858 case IW_PMKSA_REMOVE:
860 for (j = 0; j < NUM_PMKID_CACHE; j++) {
861 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
862 strIssueBssid, ETH_ALEN)) {
863 /* BSSID is matched, the same AP => Remove
864 * this PMKID information and reset it. */
865 memset(psecuritypriv->PMKIDList[j].Bssid,
867 psecuritypriv->PMKIDList[j].bUsed = false;
873 memset(psecuritypriv->PMKIDList, 0,
874 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
875 psecuritypriv->PMKIDIndex = 0;
879 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: "
880 "unknown Command\n");
887 static int r8711_wx_get_sens(struct net_device *dev,
888 struct iw_request_info *info,
889 union iwreq_data *wrqu, char *extra)
891 wrqu->sens.value = 0;
892 wrqu->sens.fixed = 0; /* no auto select */
893 wrqu->sens.disabled = 1;
897 static int r8711_wx_get_range(struct net_device *dev,
898 struct iw_request_info *info,
899 union iwreq_data *wrqu, char *extra)
901 struct iw_range *range = (struct iw_range *)extra;
905 wrqu->data.length = sizeof(*range);
906 memset(range, 0, sizeof(*range));
907 /* Let's try to keep this struct in the same order as in
908 * linux/include/wireless.h
911 /* TODO: See what values we can set, and remove the ones we can't
912 * set, or fill them with some default data.
914 /* ~5 Mb/s real (802.11b) */
915 range->throughput = 5 * 1000 * 1000;
916 /* TODO: 8711 sensitivity ? */
917 /* signal level threshold range */
918 /* percent values between 0 and 100. */
919 range->max_qual.qual = 100;
920 range->max_qual.level = 100;
921 range->max_qual.noise = 100;
922 range->max_qual.updated = 7; /* Updated all three */
923 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
924 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
925 range->avg_qual.level = 20 + -98;
926 range->avg_qual.noise = 0;
927 range->avg_qual.updated = 7; /* Updated all three */
928 range->num_bitrates = RATE_COUNT;
929 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
930 range->bitrate[i] = rtl8180_rates[i];
931 range->min_frag = MIN_FRAG_THRESHOLD;
932 range->max_frag = MAX_FRAG_THRESHOLD;
934 range->we_version_compiled = WIRELESS_EXT;
935 range->we_version_source = 16;
936 range->num_channels = 14;
937 for (i = 0, val = 0; i < 14; i++) {
938 /* Include only legal frequencies for some countries */
939 range->freq[val].i = i + 1;
940 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
941 range->freq[val].e = 1;
943 if (val == IW_MAX_FREQUENCIES)
946 range->num_frequency = val;
947 range->enc_capa = IW_ENC_CAPA_WPA |
949 IW_ENC_CAPA_CIPHER_TKIP |
950 IW_ENC_CAPA_CIPHER_CCMP;
954 static int r8711_wx_get_rate(struct net_device *dev,
955 struct iw_request_info *info,
956 union iwreq_data *wrqu, char *extra);
958 static int r871x_wx_set_priv(struct net_device *dev,
959 struct iw_request_info *info,
960 union iwreq_data *awrq,
963 int ret = 0, len = 0;
965 struct _adapter *padapter = netdev_priv(dev);
966 struct iw_point *dwrq = (struct iw_point *)awrq;
972 if (copy_from_user(ext, dwrq->pointer, len)) {
977 if (0 == strcasecmp(ext, "RSSI")) {
978 /*Return received signal strength indicator in -db for */
981 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
982 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
984 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
985 sprintf(ext, "%s rssi %d",
986 pcur_network->network.Ssid.Ssid,
988 ((padapter->recvpriv.fw_rssi)>>1)-95
989 /*pcur_network->network.Rssi */
994 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
995 /*Return link speed in MBPS */
997 union iwreq_data wrqd;
1001 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
1005 mbps = wrqd.bitrate.value / 1000000;
1006 sprintf(ext, "LINKSPEED %d", mbps);
1007 } else if (0 == strcasecmp(ext, "MACADDR")) {
1008 /*Return mac address of the station */
1009 /*Macaddr = xx.xx.xx.xx.xx.xx */
1011 "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
1012 *(dev->dev_addr), *(dev->dev_addr+1),
1013 *(dev->dev_addr+2), *(dev->dev_addr+3),
1014 *(dev->dev_addr+4), *(dev->dev_addr+5));
1015 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
1016 /*Set scan type to active */
1017 /*OK if successful */
1018 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1019 pmlmepriv->passive_mode = 1;
1021 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1022 /*Set scan type to passive */
1023 /*OK if successful */
1024 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1025 pmlmepriv->passive_mode = 0;
1027 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1028 /*Set scan type to passive */
1029 /*OK if successful */
1030 r8712_disconnectCtrlEx_cmd(padapter
1031 , 1 /*u32 enableDrvCtrl */
1032 , 5 /*u32 tryPktCnt */
1033 , 100 /*u32 tryPktInterval */
1034 , 5000 /*u32 firstStageTO */
1037 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1038 /*Set scan type to passive */
1039 /*OK if successfu */
1040 r8712_disconnectCtrlEx_cmd(padapter
1041 , 0 /*u32 enableDrvCtrl */
1042 , 5 /*u32 tryPktCnt */
1043 , 100 /*u32 tryPktInterval */
1044 , 5000 /*u32 firstStageTO */
1048 printk(KERN_INFO "r8712u: r871x_wx_set_priv: unknown Command"
1052 if (copy_to_user(dwrq->pointer, ext,
1053 min(dwrq->length, (__u16)(strlen(ext)+1))))
1062 * s1. set_802_11_infrastructure_mode()
1063 * s2. set_802_11_authentication_mode()
1064 * s3. set_802_11_encryption_mode()
1065 * s4. set_802_11_bssid()
1067 * This function intends to handle the Set AP command, which specifies the
1068 * MAC# of a preferred Access Point.
1069 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1071 * For this operation to succeed, there is no need for the interface to be up.
1074 static int r8711_wx_set_wap(struct net_device *dev,
1075 struct iw_request_info *info,
1076 union iwreq_data *awrq,
1079 int ret = -EINPROGRESS;
1080 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1081 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1082 struct __queue *queue = &pmlmepriv->scanned_queue;
1083 struct sockaddr *temp = (struct sockaddr *)awrq;
1085 struct list_head *phead;
1087 struct wlan_network *pnetwork = NULL;
1088 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1090 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1092 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1094 if (temp->sa_family != ARPHRD_ETHER)
1096 authmode = padapter->securitypriv.ndisauthtype;
1097 spin_lock_irqsave(&queue->lock, irqL);
1098 phead = get_list_head(queue);
1099 pmlmepriv->pscanned = get_next(phead);
1101 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1103 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1104 struct wlan_network, list);
1105 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1106 dst_bssid = pnetwork->network.MacAddress;
1107 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1108 r8712_set_802_11_infrastructure_mode(padapter,
1109 pnetwork->network.InfrastructureMode);
1113 spin_unlock_irqrestore(&queue->lock, irqL);
1115 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1118 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1125 static int r8711_wx_get_wap(struct net_device *dev,
1126 struct iw_request_info *info,
1127 union iwreq_data *wrqu, char *extra)
1129 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1130 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1131 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1133 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1134 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1135 if (check_fwstate(pmlmepriv, _FW_LINKED |
1136 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
1137 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1142 static int r871x_wx_set_mlme(struct net_device *dev,
1143 struct iw_request_info *info,
1144 union iwreq_data *wrqu, char *extra)
1148 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1149 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1153 reason = cpu_to_le16(mlme->reason_code);
1154 switch (mlme->cmd) {
1155 case IW_MLME_DEAUTH:
1156 if (!r8712_set_802_11_disassociate(padapter))
1159 case IW_MLME_DISASSOC:
1160 if (!r8712_set_802_11_disassociate(padapter))
1171 * This function intends to handle the Set Scan command.
1172 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1174 * For this operation to succeed, the interface is brought Up beforehand.
1177 static int r8711_wx_set_scan(struct net_device *dev,
1178 struct iw_request_info *a,
1179 union iwreq_data *wrqu, char *extra)
1181 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1182 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1185 if (padapter->bDriverStopped == true) {
1186 printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
1187 "bDriverStopped=%d\n", padapter->bDriverStopped);
1190 if (padapter->bup == false)
1192 if (padapter->hw_init_completed == false)
1194 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1195 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1197 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1198 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1199 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1200 struct ndis_802_11_ssid ssid;
1202 u32 len = (u32) min((u8)req->essid_len,
1203 (u8)IW_ESSID_MAX_SIZE);
1204 memset((unsigned char *)&ssid, 0,
1205 sizeof(struct ndis_802_11_ssid));
1206 memcpy(ssid.Ssid, req->essid, len);
1207 ssid.SsidLength = len;
1208 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1209 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1210 _FW_UNDER_LINKING)) ||
1211 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1212 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1215 status = r8712_sitesurvey_cmd(padapter, &ssid);
1216 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1219 status = r8712_set_802_11_bssid_list_scan(padapter);
1220 if (status == false)
1225 static int r8711_wx_get_scan(struct net_device *dev,
1226 struct iw_request_info *a,
1227 union iwreq_data *wrqu, char *extra)
1229 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1230 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1231 struct __queue *queue = &pmlmepriv->scanned_queue;
1232 struct wlan_network *pnetwork = NULL;
1234 struct list_head *plist, *phead;
1236 char *stop = ev + wrqu->data.length;
1237 u32 ret = 0, cnt = 0;
1239 if (padapter->bDriverStopped)
1241 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1247 spin_lock_irqsave(&queue->lock, irqL);
1248 phead = get_list_head(queue);
1249 plist = get_next(phead);
1251 if (end_of_queue_search(phead, plist) == true)
1253 if ((stop - ev) < SCAN_ITEM_SIZE) {
1257 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1258 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1259 plist = get_next(plist);
1261 spin_unlock_irqrestore(&queue->lock, irqL);
1262 wrqu->data.length = ev - extra;
1263 wrqu->data.flags = 0;
1268 * s1. set_802_11_infrastructure_mode()
1269 * s2. set_802_11_authenticaion_mode()
1270 * s3. set_802_11_encryption_mode()
1271 * s4. set_802_11_ssid()
1273 * This function intends to handle the Set ESSID command.
1274 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1276 * For this operation to succeed, there is no need for the interface to be Up.
1279 static int r8711_wx_set_essid(struct net_device *dev,
1280 struct iw_request_info *a,
1281 union iwreq_data *wrqu, char *extra)
1283 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1284 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1285 struct __queue *queue = &pmlmepriv->scanned_queue;
1286 struct wlan_network *pnetwork = NULL;
1287 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1288 struct ndis_802_11_ssid ndis_ssid;
1289 u8 *dst_ssid, *src_ssid;
1290 struct list_head *phead;
1293 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1295 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1297 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1299 authmode = padapter->securitypriv.ndisauthtype;
1300 if (wrqu->essid.flags && wrqu->essid.length) {
1301 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1302 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1303 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1304 ndis_ssid.SsidLength = len;
1305 memcpy(ndis_ssid.Ssid, extra, len);
1306 src_ssid = ndis_ssid.Ssid;
1307 phead = get_list_head(queue);
1308 pmlmepriv->pscanned = get_next(phead);
1310 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1312 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1313 struct wlan_network, list);
1314 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1315 dst_ssid = pnetwork->network.Ssid.Ssid;
1316 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1317 && (pnetwork->network.Ssid.SsidLength ==
1318 ndis_ssid.SsidLength)) {
1319 if (check_fwstate(pmlmepriv,
1320 WIFI_ADHOC_STATE)) {
1321 if (pnetwork->network.
1325 cur_network.network.
1330 r8712_set_802_11_infrastructure_mode(
1332 pnetwork->network.InfrastructureMode);
1336 r8712_set_802_11_authentication_mode(padapter, authmode);
1337 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1339 return -EINPROGRESS;
1342 static int r8711_wx_get_essid(struct net_device *dev,
1343 struct iw_request_info *a,
1344 union iwreq_data *wrqu, char *extra)
1346 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1347 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1348 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1351 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1352 len = pcur_bss->Ssid.SsidLength;
1353 wrqu->essid.length = len;
1354 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1355 wrqu->essid.flags = 1;
1362 static int r8711_wx_set_rate(struct net_device *dev,
1363 struct iw_request_info *a,
1364 union iwreq_data *wrqu, char *extra)
1366 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1367 u32 target_rate = wrqu->bitrate.value;
1368 u32 fixed = wrqu->bitrate.fixed;
1370 u8 datarates[NumRates];
1371 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1374 if (target_rate == -1) {
1378 target_rate = target_rate / 100000;
1379 switch (target_rate) {
1421 for (i = 0; i < NumRates; i++) {
1422 if (ratevalue == mpdatarate[i]) {
1423 datarates[i] = mpdatarate[i];
1427 datarates[i] = 0xff;
1429 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1434 static int r8711_wx_get_rate(struct net_device *dev,
1435 struct iw_request_info *info,
1436 union iwreq_data *wrqu, char *extra)
1438 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1439 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1440 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1441 struct ieee80211_ht_cap *pht_capie;
1442 unsigned char rf_type = padapter->registrypriv.rf_config;
1445 u16 rate, max_rate = 0, ht_cap = false;
1447 u8 bw_40MHz = 0, short_GI = 0;
1451 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1452 p = r8712_get_ie(&pcur_bss->IEs[12],
1453 _HT_CAPABILITY_IE_, &ht_ielen,
1454 pcur_bss->IELength - 12);
1455 if (p && ht_ielen > 0) {
1457 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1458 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1459 bw_40MHz = (pht_capie->cap_info &
1460 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1461 short_GI = (pht_capie->cap_info &
1462 (IEEE80211_HT_CAP_SGI_20 |
1463 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1465 while ((pcur_bss->SupportedRates[i] != 0) &&
1466 (pcur_bss->SupportedRates[i] != 0xFF)) {
1467 rate = pcur_bss->SupportedRates[i] & 0x7F;
1468 if (rate > max_rate)
1470 wrqu->bitrate.fixed = 0; /* no auto select */
1471 wrqu->bitrate.value = rate*500000;
1474 if (ht_cap == true) {
1475 if (mcs_rate & 0x8000 /* MCS15 */
1477 RTL8712_RF_2T2R == rf_type)
1478 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1479 270) : ((short_GI) ? 144 : 130);
1480 else if (mcs_rate & 0x0080) /* MCS7 */
1481 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1482 135) : ((short_GI) ? 72 : 65);
1483 else /* default MCS7 */
1484 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1485 135) : ((short_GI) ? 72 : 65);
1486 max_rate *= 2; /* Mbps/2 */
1487 wrqu->bitrate.value = max_rate * 500000;
1489 wrqu->bitrate.value = max_rate * 500000;
1496 static int r8711_wx_get_rts(struct net_device *dev,
1497 struct iw_request_info *info,
1498 union iwreq_data *wrqu, char *extra)
1500 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1502 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1503 wrqu->rts.fixed = 0; /* no auto select */
1507 static int r8711_wx_set_frag(struct net_device *dev,
1508 struct iw_request_info *info,
1509 union iwreq_data *wrqu, char *extra)
1511 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1513 if (wrqu->frag.disabled)
1514 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1516 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1517 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1519 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1524 static int r8711_wx_get_frag(struct net_device *dev,
1525 struct iw_request_info *info,
1526 union iwreq_data *wrqu, char *extra)
1528 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1530 wrqu->frag.value = padapter->xmitpriv.frag_len;
1531 wrqu->frag.fixed = 0; /* no auto select */
1535 static int r8711_wx_get_retry(struct net_device *dev,
1536 struct iw_request_info *info,
1537 union iwreq_data *wrqu, char *extra)
1539 wrqu->retry.value = 7;
1540 wrqu->retry.fixed = 0; /* no auto select */
1541 wrqu->retry.disabled = 1;
1545 static int r8711_wx_set_enc(struct net_device *dev,
1546 struct iw_request_info *info,
1547 union iwreq_data *wrqu, char *keybuf)
1550 u32 keyindex_provided;
1551 struct NDIS_802_11_WEP wep;
1552 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1553 struct iw_point *erq = &(wrqu->encoding);
1554 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1556 key = erq->flags & IW_ENCODE_INDEX;
1557 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1558 if (erq->flags & IW_ENCODE_DISABLED) {
1559 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1560 "EncryptionDisabled\n");
1561 padapter->securitypriv.ndisencryptstatus =
1562 Ndis802_11EncryptionDisabled;
1563 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1564 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1565 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1566 authmode = Ndis802_11AuthModeOpen;
1567 padapter->securitypriv.ndisauthtype = authmode;
1574 keyindex_provided = 1;
1576 keyindex_provided = 0;
1577 key = padapter->securitypriv.PrivacyKeyIndex;
1579 /* set authentication mode */
1580 if (erq->flags & IW_ENCODE_OPEN) {
1581 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1582 "IW_ENCODE_OPEN\n");
1583 padapter->securitypriv.ndisencryptstatus =
1584 Ndis802_11Encryption1Enabled;
1585 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1586 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1587 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1588 authmode = Ndis802_11AuthModeOpen;
1589 padapter->securitypriv.ndisauthtype = authmode;
1590 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1591 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1592 "IW_ENCODE_RESTRICTED\n");
1593 padapter->securitypriv.ndisencryptstatus =
1594 Ndis802_11Encryption1Enabled;
1595 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1596 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1597 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1598 authmode = Ndis802_11AuthModeShared;
1599 padapter->securitypriv.ndisauthtype = authmode;
1601 padapter->securitypriv.ndisencryptstatus =
1602 Ndis802_11Encryption1Enabled;
1603 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1604 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1605 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1606 authmode = Ndis802_11AuthModeOpen;
1607 padapter->securitypriv.ndisauthtype = authmode;
1610 if (erq->length > 0) {
1611 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1612 wep.Length = wep.KeyLength +
1613 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1616 if (keyindex_provided == 1) { /* set key_id only, no given
1617 * KeyMaterial(erq->length==0).*/
1618 padapter->securitypriv.PrivacyKeyIndex = key;
1619 switch (padapter->securitypriv.DefKeylen[key]) {
1621 padapter->securitypriv.PrivacyAlgrthm =
1625 padapter->securitypriv.PrivacyAlgrthm =
1629 padapter->securitypriv.PrivacyAlgrthm =
1636 wep.KeyIndex |= 0x80000000; /* transmit key */
1637 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1638 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1643 static int r8711_wx_get_enc(struct net_device *dev,
1644 struct iw_request_info *info,
1645 union iwreq_data *wrqu, char *keybuf)
1648 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1649 struct iw_point *erq = &(wrqu->encoding);
1650 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1652 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1653 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1655 erq->flags |= IW_ENCODE_DISABLED;
1659 key = erq->flags & IW_ENCODE_INDEX;
1665 key = padapter->securitypriv.PrivacyKeyIndex;
1667 erq->flags = key + 1;
1668 switch (padapter->securitypriv.ndisencryptstatus) {
1669 case Ndis802_11EncryptionNotSupported:
1670 case Ndis802_11EncryptionDisabled:
1672 erq->flags |= IW_ENCODE_DISABLED;
1674 case Ndis802_11Encryption1Enabled:
1675 erq->length = padapter->securitypriv.DefKeylen[key];
1677 memcpy(keybuf, padapter->securitypriv.DefKey[
1678 key].skey, padapter->securitypriv.
1680 erq->flags |= IW_ENCODE_ENABLED;
1681 if (padapter->securitypriv.ndisauthtype ==
1682 Ndis802_11AuthModeOpen)
1683 erq->flags |= IW_ENCODE_OPEN;
1684 else if (padapter->securitypriv.ndisauthtype ==
1685 Ndis802_11AuthModeShared)
1686 erq->flags |= IW_ENCODE_RESTRICTED;
1689 erq->flags |= IW_ENCODE_DISABLED;
1692 case Ndis802_11Encryption2Enabled:
1693 case Ndis802_11Encryption3Enabled:
1695 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1700 erq->flags |= IW_ENCODE_DISABLED;
1706 static int r8711_wx_get_power(struct net_device *dev,
1707 struct iw_request_info *info,
1708 union iwreq_data *wrqu, char *extra)
1710 wrqu->power.value = 0;
1711 wrqu->power.fixed = 0; /* no auto select */
1712 wrqu->power.disabled = 1;
1716 static int r871x_wx_set_gen_ie(struct net_device *dev,
1717 struct iw_request_info *info,
1718 union iwreq_data *wrqu, char *extra)
1720 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1722 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1725 static int r871x_wx_set_auth(struct net_device *dev,
1726 struct iw_request_info *info,
1727 union iwreq_data *wrqu, char *extra)
1729 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1730 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1735 paramid = param->flags & IW_AUTH_INDEX;
1736 paramval = param->value;
1738 case IW_AUTH_WPA_VERSION:
1740 case IW_AUTH_CIPHER_PAIRWISE:
1742 case IW_AUTH_CIPHER_GROUP:
1744 case IW_AUTH_KEY_MGMT:
1746 * ??? does not use these parameters
1749 case IW_AUTH_TKIP_COUNTERMEASURES:
1751 /* wpa_supplicant is enabling tkip countermeasure. */
1752 padapter->securitypriv.btkip_countermeasure = true;
1754 /* wpa_supplicant is disabling tkip countermeasure. */
1755 padapter->securitypriv.btkip_countermeasure = false;
1758 case IW_AUTH_DROP_UNENCRYPTED:
1761 * wpa_supplicant calls set_wpa_enabled when the driver
1762 * is loaded and unloaded, regardless of if WPA is being
1763 * used. No other calls are made which can be used to
1764 * determine if encryption will be used or not prior to
1765 * association being expected. If encryption is not being
1766 * used, drop_unencrypted is set to false, else true -- we
1767 * can use this to determine if the CAP_PRIVACY_ON bit should
1770 if (padapter->securitypriv.ndisencryptstatus ==
1771 Ndis802_11Encryption1Enabled) {
1772 /* it means init value, or using wep,
1773 * ndisencryptstatus =
1774 * Ndis802_11Encryption1Enabled,
1775 * then it needn't reset it;
1781 padapter->securitypriv.ndisencryptstatus =
1782 Ndis802_11EncryptionDisabled;
1783 padapter->securitypriv.PrivacyAlgrthm =
1785 padapter->securitypriv.XGrpPrivacy =
1787 padapter->securitypriv.AuthAlgrthm = 0;
1788 padapter->securitypriv.ndisauthtype =
1789 Ndis802_11AuthModeOpen;
1792 case IW_AUTH_80211_AUTH_ALG:
1793 ret = wpa_set_auth_algs(dev, (u32)paramval);
1795 case IW_AUTH_WPA_ENABLED:
1797 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1799 case IW_AUTH_PRIVACY_INVOKED:
1808 static int r871x_wx_set_enc_ext(struct net_device *dev,
1809 struct iw_request_info *info,
1810 union iwreq_data *wrqu, char *extra)
1812 struct iw_point *pencoding = &wrqu->encoding;
1813 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1814 struct ieee_param *param = NULL;
1819 param_len = sizeof(struct ieee_param) + pext->key_len;
1820 param = (struct ieee_param *)_malloc(param_len);
1823 memset(param, 0, param_len);
1824 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1825 memset(param->sta_addr, 0xff, ETH_ALEN);
1826 switch (pext->alg) {
1827 case IW_ENCODE_ALG_NONE:
1830 case IW_ENCODE_ALG_WEP:
1833 case IW_ENCODE_ALG_TKIP:
1836 case IW_ENCODE_ALG_CCMP:
1842 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1843 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1844 param->u.crypt.set_tx = 0;
1845 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1846 param->u.crypt.set_tx = 1;
1847 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1848 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1849 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1850 if (pext->key_len) {
1851 param->u.crypt.key_len = pext->key_len;
1852 memcpy(param + 1, pext + 1, pext->key_len);
1854 ret = wpa_set_encryption(dev, param, param_len);
1859 static int r871x_wx_get_nick(struct net_device *dev,
1860 struct iw_request_info *info,
1861 union iwreq_data *wrqu, char *extra)
1864 wrqu->data.length = 8;
1865 wrqu->data.flags = 1;
1866 memcpy(extra, "rtl_wifi", 8);
1871 static int r8711_wx_read32(struct net_device *dev,
1872 struct iw_request_info *info,
1873 union iwreq_data *wrqu, char *keybuf)
1875 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1879 get_user(addr, (u32 __user *)wrqu->data.pointer);
1880 data32 = r8712_read32(padapter, addr);
1881 put_user(data32, (u32 __user *)wrqu->data.pointer);
1882 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1883 wrqu->data.flags = data32 & 0xffff;
1884 get_user(addr, (u32 __user *)wrqu->data.pointer);
1888 static int r8711_wx_write32(struct net_device *dev,
1889 struct iw_request_info *info,
1890 union iwreq_data *wrqu, char *keybuf)
1892 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1896 get_user(addr, (u32 __user *)wrqu->data.pointer);
1897 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
1898 r8712_write32(padapter, addr, data32);
1902 static int dummy(struct net_device *dev,
1903 struct iw_request_info *a,
1904 union iwreq_data *wrqu, char *b)
1909 static int r8711_drvext_hdl(struct net_device *dev,
1910 struct iw_request_info *info,
1911 union iwreq_data *wrqu, char *extra)
1916 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1917 struct iw_request_info *info,
1918 union iwreq_data *wrqu, char *extra)
1920 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1921 struct iw_point *p = &wrqu->data;
1922 struct oid_par_priv oid_par;
1923 struct mp_ioctl_handler *phandler;
1924 struct mp_ioctl_param *poidparam;
1925 unsigned long BytesRead, BytesWritten, BytesNeeded;
1926 u8 *pparmbuf = NULL, bset;
1931 if ((!p->length) || (!p->pointer)) {
1933 goto _r871x_mp_ioctl_hdl_exit;
1935 bset = (u8)(p->flags & 0xFFFF);
1938 pparmbuf = (u8 *)_malloc(len);
1939 if (pparmbuf == NULL) {
1941 goto _r871x_mp_ioctl_hdl_exit;
1943 if (copy_from_user(pparmbuf, p->pointer, len)) {
1945 goto _r871x_mp_ioctl_hdl_exit;
1947 poidparam = (struct mp_ioctl_param *)pparmbuf;
1948 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1950 goto _r871x_mp_ioctl_hdl_exit;
1952 phandler = mp_ioctl_hdl + poidparam->subcode;
1953 if ((phandler->paramsize != 0) &&
1954 (poidparam->len < phandler->paramsize)) {
1956 goto _r871x_mp_ioctl_hdl_exit;
1958 if (phandler->oid == 0 && phandler->handler)
1959 status = phandler->handler(&oid_par);
1960 else if (phandler->handler) {
1961 oid_par.adapter_context = padapter;
1962 oid_par.oid = phandler->oid;
1963 oid_par.information_buf = poidparam->data;
1964 oid_par.information_buf_len = poidparam->len;
1969 oid_par.bytes_rw = &BytesRead;
1970 oid_par.bytes_needed = &BytesNeeded;
1971 oid_par.type_of_oid = SET_OID;
1973 oid_par.bytes_rw = &BytesWritten;
1974 oid_par.bytes_needed = &BytesNeeded;
1975 oid_par.type_of_oid = QUERY_OID;
1977 status = phandler->handler(&oid_par);
1978 /* todo:check status, BytesNeeded, etc. */
1980 printk(KERN_INFO "r8712u: r871x_mp_ioctl_hdl(): err!,"
1981 " subcode=%d, oid=%d, handler=%p\n",
1982 poidparam->subcode, phandler->oid, phandler->handler);
1984 goto _r871x_mp_ioctl_hdl_exit;
1986 if (bset == 0x00) { /* query info */
1987 if (copy_to_user(p->pointer, pparmbuf, len))
1992 goto _r871x_mp_ioctl_hdl_exit;
1994 _r871x_mp_ioctl_hdl_exit:
1999 static int r871x_get_ap_info(struct net_device *dev,
2000 struct iw_request_info *info,
2001 union iwreq_data *wrqu, char *extra)
2003 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2004 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2005 struct __queue *queue = &pmlmepriv->scanned_queue;
2006 struct iw_point *pdata = &wrqu->data;
2007 struct wlan_network *pnetwork = NULL;
2008 u32 cnt = 0, wpa_ielen;
2010 struct list_head *plist, *phead;
2011 unsigned char *pbuf;
2015 if (padapter->bDriverStopped || (pdata == NULL))
2017 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
2024 if (pdata->length >= 32) {
2025 if (copy_from_user(data, pdata->pointer, 32))
2029 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2030 phead = get_list_head(queue);
2031 plist = get_next(phead);
2033 if (end_of_queue_search(phead, plist) == true)
2035 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2036 if (hwaddr_aton_i(data, bssid)) {
2037 printk(KERN_INFO "r8712u: Invalid BSSID '%s'.\n",
2039 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2043 printk(KERN_INFO "r8712u: BSSID:%pM\n", bssid);
2044 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2045 /* BSSID match, then check if supporting wpa/wpa2 */
2046 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2047 &wpa_ielen, pnetwork->network.IELength-12);
2048 if (pbuf && (wpa_ielen > 0)) {
2052 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2053 &wpa_ielen, pnetwork->network.IELength-12);
2054 if (pbuf && (wpa_ielen > 0)) {
2059 plist = get_next(plist);
2061 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2062 if (pdata->length >= 34) {
2063 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2064 (u8 *)&pdata->flags, 1))
2070 static int r871x_set_pid(struct net_device *dev,
2071 struct iw_request_info *info,
2072 union iwreq_data *wrqu, char *extra)
2074 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2075 struct iw_point *pdata = &wrqu->data;
2077 if ((padapter->bDriverStopped) || (pdata == NULL))
2079 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2084 static int r871x_set_chplan(struct net_device *dev,
2085 struct iw_request_info *info,
2086 union iwreq_data *wrqu, char *extra)
2089 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2090 struct iw_point *pdata = &wrqu->data;
2093 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2097 ch_plan = (int)*extra;
2098 r8712_set_chplan_cmd(padapter, ch_plan);
2105 static int r871x_wps_start(struct net_device *dev,
2106 struct iw_request_info *info,
2107 union iwreq_data *wrqu, char *extra)
2109 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2110 struct iw_point *pdata = &wrqu->data;
2111 u32 u32wps_start = 0;
2113 if ((padapter->bDriverStopped) || (pdata == NULL))
2115 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2117 if (u32wps_start == 0)
2118 u32wps_start = *extra;
2119 if (u32wps_start == 1) /* WPS Start */
2120 padapter->ledpriv.LedControlHandler(padapter,
2122 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2123 padapter->ledpriv.LedControlHandler(padapter,
2125 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2126 padapter->ledpriv.LedControlHandler(padapter,
2127 LED_CTL_STOP_WPS_FAIL);
2131 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2133 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2136 case IEEE_PARAM_WPA_ENABLED:
2137 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2138 switch ((value)&0xff) {
2140 padapter->securitypriv.ndisauthtype =
2141 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2142 padapter->securitypriv.ndisencryptstatus =
2143 Ndis802_11Encryption2Enabled;
2146 padapter->securitypriv.ndisauthtype =
2147 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2148 padapter->securitypriv.ndisencryptstatus =
2149 Ndis802_11Encryption3Enabled;
2153 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2155 case IEEE_PARAM_DROP_UNENCRYPTED:
2158 * wpa_supplicant calls set_wpa_enabled when the driver
2159 * is loaded and unloaded, regardless of if WPA is being
2160 * used. No other calls are made which can be used to
2161 * determine if encryption will be used or not prior to
2162 * association being expected. If encryption is not being
2163 * used, drop_unencrypted is set to false, else true -- we
2164 * can use this to determine if the CAP_PRIVACY_ON bit should
2168 case IEEE_PARAM_PRIVACY_INVOKED:
2170 case IEEE_PARAM_AUTH_ALGS:
2171 return wpa_set_auth_algs(dev, value);
2173 case IEEE_PARAM_IEEE_802_1X:
2175 case IEEE_PARAM_WPAX_SELECT:
2176 /* added for WPA2 mixed mode */
2184 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2186 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2189 case IEEE_MLME_STA_DEAUTH:
2190 if (!r8712_set_802_11_disassociate(padapter))
2193 case IEEE_MLME_STA_DISASSOC:
2194 if (!r8712_set_802_11_disassociate(padapter))
2203 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2205 struct ieee_param *param;
2207 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2209 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2211 param = (struct ieee_param *)_malloc(p->length);
2214 if (copy_from_user(param, p->pointer, p->length)) {
2218 switch (param->cmd) {
2219 case IEEE_CMD_SET_WPA_PARAM:
2220 ret = wpa_set_param(dev, param->u.wpa_param.name,
2221 param->u.wpa_param.value);
2223 case IEEE_CMD_SET_WPA_IE:
2224 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2225 (u16)param->u.wpa_ie.len);
2227 case IEEE_CMD_SET_ENCRYPTION:
2228 ret = wpa_set_encryption(dev, param, p->length);
2231 ret = wpa_mlme(dev, param->u.mlme.command,
2232 param->u.mlme.reason_code);
2238 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2244 /* based on "driver_ipw" and for hostapd */
2245 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2247 struct iwreq *wrq = (struct iwreq *)rq;
2250 case RTL_IOCTL_WPA_SUPPLICANT:
2251 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2258 static iw_handler r8711_handlers[] = {
2259 NULL, /* SIOCSIWCOMMIT */
2260 r8711_wx_get_name, /* SIOCGIWNAME */
2261 dummy, /* SIOCSIWNWID */
2262 dummy, /* SIOCGIWNWID */
2263 r8711_wx_set_freq, /* SIOCSIWFREQ */
2264 r8711_wx_get_freq, /* SIOCGIWFREQ */
2265 r8711_wx_set_mode, /* SIOCSIWMODE */
2266 r8711_wx_get_mode, /* SIOCGIWMODE */
2267 dummy, /* SIOCSIWSENS */
2268 r8711_wx_get_sens, /* SIOCGIWSENS */
2269 NULL, /* SIOCSIWRANGE */
2270 r8711_wx_get_range, /* SIOCGIWRANGE */
2271 r871x_wx_set_priv, /* SIOCSIWPRIV */
2272 NULL, /* SIOCGIWPRIV */
2273 NULL, /* SIOCSIWSTATS */
2274 NULL, /* SIOCGIWSTATS */
2275 dummy, /* SIOCSIWSPY */
2276 dummy, /* SIOCGIWSPY */
2277 NULL, /* SIOCGIWTHRSPY */
2278 NULL, /* SIOCWIWTHRSPY */
2279 r8711_wx_set_wap, /* SIOCSIWAP */
2280 r8711_wx_get_wap, /* SIOCGIWAP */
2281 r871x_wx_set_mlme, /* request MLME operation;
2282 * uses struct iw_mlme */
2283 dummy, /* SIOCGIWAPLIST -- deprecated */
2284 r8711_wx_set_scan, /* SIOCSIWSCAN */
2285 r8711_wx_get_scan, /* SIOCGIWSCAN */
2286 r8711_wx_set_essid, /* SIOCSIWESSID */
2287 r8711_wx_get_essid, /* SIOCGIWESSID */
2288 dummy, /* SIOCSIWNICKN */
2289 r871x_wx_get_nick, /* SIOCGIWNICKN */
2290 NULL, /* -- hole -- */
2291 NULL, /* -- hole -- */
2292 r8711_wx_set_rate, /* SIOCSIWRATE */
2293 r8711_wx_get_rate, /* SIOCGIWRATE */
2294 dummy, /* SIOCSIWRTS */
2295 r8711_wx_get_rts, /* SIOCGIWRTS */
2296 r8711_wx_set_frag, /* SIOCSIWFRAG */
2297 r8711_wx_get_frag, /* SIOCGIWFRAG */
2298 dummy, /* SIOCSIWTXPOW */
2299 dummy, /* SIOCGIWTXPOW */
2300 dummy, /* SIOCSIWRETRY */
2301 r8711_wx_get_retry, /* SIOCGIWRETRY */
2302 r8711_wx_set_enc, /* SIOCSIWENCODE */
2303 r8711_wx_get_enc, /* SIOCGIWENCODE */
2304 dummy, /* SIOCSIWPOWER */
2305 r8711_wx_get_power, /* SIOCGIWPOWER */
2306 NULL, /*---hole---*/
2307 NULL, /*---hole---*/
2308 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2309 NULL, /* SIOCGIWGENIE */
2310 r871x_wx_set_auth, /* SIOCSIWAUTH */
2311 NULL, /* SIOCGIWAUTH */
2312 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2313 NULL, /* SIOCGIWENCODEEXT */
2314 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2315 NULL, /*---hole---*/
2318 static const struct iw_priv_args r8711_private_args[] = {
2320 SIOCIWFIRSTPRIV + 0x0,
2321 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2324 SIOCIWFIRSTPRIV + 0x1,
2325 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2328 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2331 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2334 SIOCIWFIRSTPRIV + 0x4,
2335 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2338 SIOCIWFIRSTPRIV + 0x5,
2339 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2342 SIOCIWFIRSTPRIV + 0x6,
2343 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2346 SIOCIWFIRSTPRIV + 0x7,
2347 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2351 static iw_handler r8711_private_handler[] = {
2356 r871x_get_ap_info, /*for MM DTV platform*/
2362 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2364 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2365 struct iw_statistics *piwstats = &padapter->iwstats;
2370 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2371 piwstats->qual.qual = 0;
2372 piwstats->qual.level = 0;
2373 piwstats->qual.noise = 0;
2375 /* show percentage, we need transfer dbm to orignal value. */
2376 tmp_level = padapter->recvpriv.fw_rssi;
2377 tmp_qual = padapter->recvpriv.signal;
2378 tmp_noise = padapter->recvpriv.noise;
2379 piwstats->qual.level = tmp_level;
2380 piwstats->qual.qual = tmp_qual;
2381 piwstats->qual.noise = tmp_noise;
2383 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2384 return &padapter->iwstats;
2387 struct iw_handler_def r871x_handlers_def = {
2388 .standard = r8711_handlers,
2389 .num_standard = ARRAY_SIZE(r8711_handlers),
2390 .private = r8711_private_handler,
2391 .private_args = (struct iw_priv_args *)r8711_private_args,
2392 .num_private = ARRAY_SIZE(r8711_private_handler),
2393 .num_private_args = sizeof(r8711_private_args) /
2394 sizeof(struct iw_priv_args),
2395 .get_wireless_stats = r871x_get_wireless_stats