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>
46 #include <linux/semaphore.h>
47 #include <net/iw_handler.h>
48 #include <linux/if_arp.h>
50 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
52 #define SCAN_ITEM_SIZE 768
53 #define MAX_CUSTOM_LEN 64
57 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
58 6000000, 9000000, 12000000, 18000000,
59 24000000, 36000000, 48000000, 54000000};
61 static const long ieee80211_wlan_frequencies[] = {
62 2412, 2417, 2422, 2427,
63 2432, 2437, 2442, 2447,
64 2452, 2457, 2462, 2467,
68 static const char * const iw_operation_mode[] = {
69 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
74 * hwaddr_aton - Convert ASCII string to MAC address
75 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
76 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
77 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
79 static int hwaddr_aton_i(const char *txt, u8 *addr)
83 for (i = 0; i < 6; i++) {
86 a = hex_to_bin(*txt++);
89 b = hex_to_bin(*txt++);
92 *addr++ = (a << 4) | b;
93 if (i < 5 && *txt++ != ':')
99 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
101 union iwreq_data wrqu;
102 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
104 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
105 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
107 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
110 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
112 union iwreq_data wrqu;
114 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
115 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
116 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
119 static inline void handle_pairwise_key(struct sta_info *psta,
120 struct ieee_param *param,
121 struct _adapter *padapter)
124 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
125 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
126 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
127 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
129 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
131 padapter->securitypriv. busetkipkey = false;
132 _set_timer(&padapter->securitypriv.tkip_timer, 50);
134 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
137 static inline void handle_group_key(struct ieee_param *param,
138 struct _adapter *padapter)
140 if (0 < param->u.crypt.idx &&
141 param->u.crypt.idx < 3) {
142 /* group key idx is 1 or 2 */
143 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
144 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
145 > 16 ? 16 : param->u.crypt.key_len));
146 memcpy(padapter->securitypriv.XGrptxmickey[param->
147 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
148 memcpy(padapter->securitypriv. XGrprxmickey[param->
149 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
150 padapter->securitypriv.binstallGrpkey = true;
151 r8712_set_key(padapter, &padapter->securitypriv,
153 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
154 if (padapter->registrypriv.power_mgnt != padapter->
155 pwrctrlpriv.pwr_mode)
156 _set_timer(&(padapter->mlmepriv.dhcp_timer),
162 static inline char *translate_scan(struct _adapter *padapter,
163 struct iw_request_info *info,
164 struct wlan_network *pnetwork,
165 char *start, char *stop)
168 struct ieee80211_ht_cap *pht_capie;
171 u32 i = 0, ht_ielen = 0;
172 u16 cap, ht_cap = false, mcs_rate;
173 u8 rssi, bw_40MHz = 0, short_GI = 0;
175 if ((pnetwork->network.Configuration.DSConfig < 1) ||
176 (pnetwork->network.Configuration.DSConfig > 14)) {
177 if (pnetwork->network.Configuration.DSConfig < 1)
178 pnetwork->network.Configuration.DSConfig = 1;
180 pnetwork->network.Configuration.DSConfig = 14;
184 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
185 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
186 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
188 iwe.cmd = SIOCGIWESSID;
189 iwe.u.data.flags = 1;
190 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
191 start = iwe_stream_add_point(info, start, stop, &iwe,
192 pnetwork->network.Ssid.Ssid);
193 /* parsing HT_CAP_IE */
194 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
195 &ht_ielen, pnetwork->network.IELength - 12);
196 if (p && ht_ielen > 0) {
198 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
199 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
200 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
202 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
203 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
205 /* Add the protocol name */
206 iwe.cmd = SIOCGIWNAME;
207 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
208 SupportedRates)) == true) {
210 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
212 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
213 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
214 SupportedRates)) == true) {
216 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
218 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
221 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
223 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
225 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
227 iwe.cmd = SIOCGIWMODE;
228 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
230 cap = le16_to_cpu(cap);
231 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
232 if (cap & WLAN_CAPABILITY_BSS)
233 iwe.u.mode = (u32)IW_MODE_MASTER;
235 iwe.u.mode = (u32)IW_MODE_ADHOC;
236 start = iwe_stream_add_event(info, start, stop, &iwe,
239 /* Add frequency/channel */
240 iwe.cmd = SIOCGIWFREQ;
242 /* check legal index */
243 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
245 if (dsconfig >= 1 && dsconfig <= sizeof(
246 ieee80211_wlan_frequencies) / sizeof(long))
247 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
248 pnetwork->network.Configuration.
249 DSConfig - 1] * 100000);
253 iwe.u.freq.e = (s16)1;
254 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
255 start = iwe_stream_add_event(info, start, stop, &iwe,
257 /* Add encryption capability */
258 iwe.cmd = SIOCGIWENCODE;
259 if (cap & WLAN_CAPABILITY_PRIVACY)
260 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
263 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
264 iwe.u.data.length = (u16)0;
265 start = iwe_stream_add_point(info, start, stop, &iwe,
266 pnetwork->network.Ssid.Ssid);
267 /*Add basic and extended rates */
268 current_val = start + iwe_stream_lcp_len(info);
269 iwe.cmd = SIOCGIWRATE;
270 iwe.u.bitrate.fixed = 0;
271 iwe.u.bitrate.disabled = 0;
272 iwe.u.bitrate.value = 0;
274 while (pnetwork->network.SupportedRates[i] != 0) {
275 /* Bit rate given in 500 kb/s units */
276 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
278 current_val = iwe_stream_add_value(info, start, current_val,
279 stop, &iwe, IW_EV_PARAM_LEN);
281 /* Check if we added any event */
282 if ((current_val - start) > iwe_stream_lcp_len(info))
284 /* parsing WPA/WPA2 IE */
286 u8 buf[MAX_WPA_IE_LEN];
287 u8 wpa_ie[255], rsn_ie[255];
288 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 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
419 padapter->securitypriv.ndisencryptstatus =
420 Ndis802_11Encryption1Enabled;
421 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
422 padapter->securitypriv.XGrpPrivacy = _WEP40_;
423 wep_key_idx = param->u.crypt.idx;
424 wep_key_len = param->u.crypt.key_len;
425 if (wep_key_idx >= WEP_KEYS)
427 if (wep_key_len > 0) {
428 wep_key_len = wep_key_len <= 5 ? 5 : 13;
429 pwep = kmalloc((u32)(wep_key_len +
430 FIELD_OFFSET(struct NDIS_802_11_WEP,
431 KeyMaterial)), GFP_ATOMIC);
434 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
435 pwep->KeyLength = wep_key_len;
436 pwep->Length = wep_key_len +
437 FIELD_OFFSET(struct NDIS_802_11_WEP,
439 if (wep_key_len == 13) {
440 padapter->securitypriv.PrivacyAlgrthm =
442 padapter->securitypriv.XGrpPrivacy =
447 pwep->KeyIndex = wep_key_idx;
448 pwep->KeyIndex |= 0x80000000;
449 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
450 if (param->u.crypt.set_tx) {
451 if (r8712_set_802_11_add_wep(padapter, pwep) ==
455 /* don't update "psecuritypriv->PrivacyAlgrthm" and
456 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
457 * r8712_set_key to fw/cam
459 if (wep_key_idx >= WEP_KEYS) {
463 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
464 skey[0]), pwep->KeyMaterial,
466 psecuritypriv->DefKeylen[wep_key_idx] =
468 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
472 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
473 struct sta_info *psta, *pbcmc_sta;
474 struct sta_priv *pstapriv = &padapter->stapriv;
476 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
477 WIFI_MP_STATE) == true) { /* sta mode */
478 psta = r8712_get_stainfo(pstapriv,
479 get_bssid(pmlmepriv));
481 psta->ieee8021x_blocked = false;
482 if ((padapter->securitypriv.ndisencryptstatus ==
483 Ndis802_11Encryption2Enabled) ||
484 (padapter->securitypriv.ndisencryptstatus ==
485 Ndis802_11Encryption3Enabled))
486 psta->XPrivacy = padapter->
487 securitypriv.PrivacyAlgrthm;
488 if (param->u.crypt.set_tx == 1)
489 handle_pairwise_key(psta, param,
492 handle_group_key(param, padapter);
494 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
496 pbcmc_sta->ieee8021x_blocked = false;
497 if ((padapter->securitypriv.ndisencryptstatus ==
498 Ndis802_11Encryption2Enabled) ||
499 (padapter->securitypriv.ndisencryptstatus ==
500 Ndis802_11Encryption3Enabled))
501 pbcmc_sta->XPrivacy =
502 padapter->securitypriv.
512 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
513 unsigned short ielen)
515 u8 *buf = NULL, *pos = NULL;
516 int group_cipher = 0, pairwise_cipher = 0;
519 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
522 buf = kmemdup(pie, ielen, GFP_ATOMIC);
526 if (ielen < RSN_HEADER_LEN) {
530 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
531 &pairwise_cipher) == _SUCCESS) {
532 padapter->securitypriv.AuthAlgrthm = 2;
533 padapter->securitypriv.ndisauthtype =
534 Ndis802_11AuthModeWPAPSK;
536 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
537 &pairwise_cipher) == _SUCCESS) {
538 padapter->securitypriv.AuthAlgrthm = 2;
539 padapter->securitypriv.ndisauthtype =
540 Ndis802_11AuthModeWPA2PSK;
542 switch (group_cipher) {
543 case WPA_CIPHER_NONE:
544 padapter->securitypriv.XGrpPrivacy =
546 padapter->securitypriv.ndisencryptstatus =
547 Ndis802_11EncryptionDisabled;
549 case WPA_CIPHER_WEP40:
550 padapter->securitypriv.XGrpPrivacy = _WEP40_;
551 padapter->securitypriv.ndisencryptstatus =
552 Ndis802_11Encryption1Enabled;
554 case WPA_CIPHER_TKIP:
555 padapter->securitypriv.XGrpPrivacy = _TKIP_;
556 padapter->securitypriv.ndisencryptstatus =
557 Ndis802_11Encryption2Enabled;
559 case WPA_CIPHER_CCMP:
560 padapter->securitypriv.XGrpPrivacy = _AES_;
561 padapter->securitypriv.ndisencryptstatus =
562 Ndis802_11Encryption3Enabled;
564 case WPA_CIPHER_WEP104:
565 padapter->securitypriv.XGrpPrivacy = _WEP104_;
566 padapter->securitypriv.ndisencryptstatus =
567 Ndis802_11Encryption1Enabled;
570 switch (pairwise_cipher) {
571 case WPA_CIPHER_NONE:
572 padapter->securitypriv.PrivacyAlgrthm =
574 padapter->securitypriv.ndisencryptstatus =
575 Ndis802_11EncryptionDisabled;
577 case WPA_CIPHER_WEP40:
578 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
579 padapter->securitypriv.ndisencryptstatus =
580 Ndis802_11Encryption1Enabled;
582 case WPA_CIPHER_TKIP:
583 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
584 padapter->securitypriv.ndisencryptstatus =
585 Ndis802_11Encryption2Enabled;
587 case WPA_CIPHER_CCMP:
588 padapter->securitypriv.PrivacyAlgrthm = _AES_;
589 padapter->securitypriv.ndisencryptstatus =
590 Ndis802_11Encryption3Enabled;
592 case WPA_CIPHER_WEP104:
593 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
594 padapter->securitypriv.ndisencryptstatus =
595 Ndis802_11Encryption1Enabled;
598 padapter->securitypriv.wps_phase = false;
601 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
603 while (cnt < ielen) {
606 if ((eid == _VENDOR_SPECIFIC_IE_) &&
607 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
608 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
609 padapter->securitypriv.wps_ie_len =
611 (MAX_WPA_IE_LEN << 2)) ?
613 (MAX_WPA_IE_LEN << 2);
614 memcpy(padapter->securitypriv.wps_ie,
616 padapter->securitypriv.wps_ie_len);
617 padapter->securitypriv.wps_phase =
619 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
623 cnt += buf[cnt + 1] + 2;
632 static int r8711_wx_get_name(struct net_device *dev,
633 struct iw_request_info *info,
634 union iwreq_data *wrqu, char *extra)
636 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
640 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
641 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
642 NDIS_802_11_RATES_EX *prates = NULL;
644 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
646 /* parsing HT_CAP_IE */
647 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
648 &ht_ielen, pcur_bss->IELength - 12);
649 if (p && ht_ielen > 0)
651 prates = &pcur_bss->SupportedRates;
652 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
654 snprintf(wrqu->name, IFNAMSIZ,
657 snprintf(wrqu->name, IFNAMSIZ,
659 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
661 snprintf(wrqu->name, IFNAMSIZ,
664 snprintf(wrqu->name, IFNAMSIZ,
668 snprintf(wrqu->name, IFNAMSIZ,
671 snprintf(wrqu->name, IFNAMSIZ,
675 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
679 static const long frequency_list[] = {
680 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
681 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
682 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
683 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
684 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
688 static int r8711_wx_set_freq(struct net_device *dev,
689 struct iw_request_info *info,
690 union iwreq_data *wrqu, char *extra)
692 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
693 struct iw_freq *fwrq = &wrqu->freq;
696 /* If setting by frequency, convert to a channel */
697 if ((fwrq->e == 1) &&
698 (fwrq->m >= (int) 2.412e8) &&
699 (fwrq->m <= (int) 2.487e8)) {
700 int f = fwrq->m / 100000;
703 while ((c < 14) && (f != frequency_list[c]))
708 /* Setting by channel number */
709 if ((fwrq->m > 14) || (fwrq->e > 0))
712 int channel = fwrq->m;
714 if ((channel < 1) || (channel > 14))
717 /* Yes ! We can set it !!! */
718 padapter->registrypriv.channel = channel;
724 static int r8711_wx_get_freq(struct net_device *dev,
725 struct iw_request_info *info,
726 union iwreq_data *wrqu, char *extra)
728 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
729 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
730 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
732 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
733 wrqu->freq.m = ieee80211_wlan_frequencies[
734 pcur_bss->Configuration.DSConfig-1] * 100000;
736 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
743 static int r8711_wx_set_mode(struct net_device *dev,
744 struct iw_request_info *a,
745 union iwreq_data *wrqu, char *b)
747 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
748 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
750 switch (wrqu->mode) {
752 networkType = Ndis802_11AutoUnknown;
755 networkType = Ndis802_11IBSS;
758 networkType = Ndis802_11APMode;
761 networkType = Ndis802_11Infrastructure;
766 if (Ndis802_11APMode == networkType)
767 r8712_setopmode_cmd(padapter, networkType);
769 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
771 r8712_set_802_11_infrastructure_mode(padapter, networkType);
775 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
776 union iwreq_data *wrqu, char *b)
778 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
779 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
781 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
782 wrqu->mode = IW_MODE_INFRA;
783 else if (check_fwstate(pmlmepriv,
784 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
785 wrqu->mode = IW_MODE_ADHOC;
786 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
787 wrqu->mode = IW_MODE_MASTER;
789 wrqu->mode = IW_MODE_AUTO;
793 static int r871x_wx_set_pmkid(struct net_device *dev,
794 struct iw_request_info *a,
795 union iwreq_data *wrqu, char *extra)
797 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
798 struct security_priv *psecuritypriv = &padapter->securitypriv;
799 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
800 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
801 u8 strIssueBssid[ETH_ALEN] = {0x00};
802 u8 j, blInserted = false;
803 int intReturn = false;
806 There are the BSSID information in the bssid.sa_data array.
807 If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
808 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
809 wpa_supplicant wants to add a PMKID/BSSID to driver.
810 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
811 remove a PMKID/BSSID from driver.
815 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
818 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
823 /* overwrite PMKID */
824 for (j = 0; j < NUM_PMKID_CACHE; j++) {
825 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
826 strIssueBssid, ETH_ALEN)) {
827 /* BSSID is matched, the same AP => rewrite
829 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
831 memcpy(psecuritypriv->PMKIDList[j].PMKID,
832 pPMK->pmkid, IW_PMKID_LEN);
833 psecuritypriv->PMKIDList[j].bUsed = true;
834 psecuritypriv->PMKIDIndex = j + 1;
840 /* Find a new entry */
841 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
842 __func__, psecuritypriv->PMKIDIndex);
843 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
844 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
845 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
846 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
847 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
849 psecuritypriv->PMKIDIndex++;
850 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
851 psecuritypriv->PMKIDIndex = 0;
854 case IW_PMKSA_REMOVE:
856 for (j = 0; j < NUM_PMKID_CACHE; j++) {
857 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
858 strIssueBssid, ETH_ALEN)) {
859 /* BSSID is matched, the same AP => Remove
860 * this PMKID information and reset it. */
861 memset(psecuritypriv->PMKIDList[j].Bssid,
863 psecuritypriv->PMKIDList[j].bUsed = false;
869 memset(psecuritypriv->PMKIDList, 0,
870 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
871 psecuritypriv->PMKIDIndex = 0;
875 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
882 static int r8711_wx_get_sens(struct net_device *dev,
883 struct iw_request_info *info,
884 union iwreq_data *wrqu, char *extra)
886 wrqu->sens.value = 0;
887 wrqu->sens.fixed = 0; /* no auto select */
888 wrqu->sens.disabled = 1;
892 static int r8711_wx_get_range(struct net_device *dev,
893 struct iw_request_info *info,
894 union iwreq_data *wrqu, char *extra)
896 struct iw_range *range = (struct iw_range *)extra;
900 wrqu->data.length = sizeof(*range);
901 memset(range, 0, sizeof(*range));
902 /* Let's try to keep this struct in the same order as in
903 * linux/include/wireless.h
906 /* TODO: See what values we can set, and remove the ones we can't
907 * set, or fill them with some default data.
909 /* ~5 Mb/s real (802.11b) */
910 range->throughput = 5 * 1000 * 1000;
911 /* TODO: 8711 sensitivity ? */
912 /* signal level threshold range */
913 /* percent values between 0 and 100. */
914 range->max_qual.qual = 100;
915 range->max_qual.level = 100;
916 range->max_qual.noise = 100;
917 range->max_qual.updated = 7; /* Updated all three */
918 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
919 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
920 range->avg_qual.level = 20 + -98;
921 range->avg_qual.noise = 0;
922 range->avg_qual.updated = 7; /* Updated all three */
923 range->num_bitrates = RATE_COUNT;
924 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
925 range->bitrate[i] = rtl8180_rates[i];
926 range->min_frag = MIN_FRAG_THRESHOLD;
927 range->max_frag = MAX_FRAG_THRESHOLD;
929 range->we_version_compiled = WIRELESS_EXT;
930 range->we_version_source = 16;
931 range->num_channels = 14;
932 for (i = 0, val = 0; i < 14; i++) {
933 /* Include only legal frequencies for some countries */
934 range->freq[val].i = i + 1;
935 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
936 range->freq[val].e = 1;
938 if (val == IW_MAX_FREQUENCIES)
941 range->num_frequency = val;
942 range->enc_capa = IW_ENC_CAPA_WPA |
944 IW_ENC_CAPA_CIPHER_TKIP |
945 IW_ENC_CAPA_CIPHER_CCMP;
949 static int r8711_wx_get_rate(struct net_device *dev,
950 struct iw_request_info *info,
951 union iwreq_data *wrqu, char *extra);
953 static int r871x_wx_set_priv(struct net_device *dev,
954 struct iw_request_info *info,
955 union iwreq_data *awrq,
958 int ret = 0, len = 0;
960 struct _adapter *padapter = netdev_priv(dev);
961 struct iw_point *dwrq = (struct iw_point *)awrq;
964 ext = memdup_user(dwrq->pointer, len);
968 if (0 == strcasecmp(ext, "RSSI")) {
969 /*Return received signal strength indicator in -db for */
972 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
973 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
975 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
976 sprintf(ext, "%s rssi %d",
977 pcur_network->network.Ssid.Ssid,
979 ((padapter->recvpriv.fw_rssi)>>1)-95
980 /*pcur_network->network.Rssi */
985 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
986 /*Return link speed in MBPS */
988 union iwreq_data wrqd;
992 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
996 mbps = wrqd.bitrate.value / 1000000;
997 sprintf(ext, "LINKSPEED %d", mbps);
998 } else if (0 == strcasecmp(ext, "MACADDR")) {
999 /*Return mac address of the station */
1000 /* Macaddr = xx:xx:xx:xx:xx:xx */
1001 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
1002 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
1003 /*Set scan type to active */
1004 /*OK if successful */
1005 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1007 pmlmepriv->passive_mode = 1;
1009 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1010 /*Set scan type to passive */
1011 /*OK if successful */
1012 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1014 pmlmepriv->passive_mode = 0;
1016 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1017 /*Set scan type to passive */
1018 /*OK if successful */
1019 r8712_disconnectCtrlEx_cmd(padapter
1020 , 1 /*u32 enableDrvCtrl */
1021 , 5 /*u32 tryPktCnt */
1022 , 100 /*u32 tryPktInterval */
1023 , 5000 /*u32 firstStageTO */
1026 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1027 /*Set scan type to passive */
1028 /*OK if successfu */
1029 r8712_disconnectCtrlEx_cmd(padapter
1030 , 0 /*u32 enableDrvCtrl */
1031 , 5 /*u32 tryPktCnt */
1032 , 100 /*u32 tryPktInterval */
1033 , 5000 /*u32 firstStageTO */
1037 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1041 if (copy_to_user(dwrq->pointer, ext,
1042 min(dwrq->length, (__u16)(strlen(ext)+1))))
1051 * s1. set_802_11_infrastructure_mode()
1052 * s2. set_802_11_authentication_mode()
1053 * s3. set_802_11_encryption_mode()
1054 * s4. set_802_11_bssid()
1056 * This function intends to handle the Set AP command, which specifies the
1057 * MAC# of a preferred Access Point.
1058 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1060 * For this operation to succeed, there is no need for the interface to be up.
1063 static int r8711_wx_set_wap(struct net_device *dev,
1064 struct iw_request_info *info,
1065 union iwreq_data *awrq,
1068 int ret = -EINPROGRESS;
1069 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1070 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1071 struct __queue *queue = &pmlmepriv->scanned_queue;
1072 struct sockaddr *temp = (struct sockaddr *)awrq;
1074 struct list_head *phead;
1076 struct wlan_network *pnetwork = NULL;
1077 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1079 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1081 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1083 if (temp->sa_family != ARPHRD_ETHER)
1085 authmode = padapter->securitypriv.ndisauthtype;
1086 spin_lock_irqsave(&queue->lock, irqL);
1087 phead = &queue->queue;
1088 pmlmepriv->pscanned = phead->next;
1090 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1092 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1093 struct wlan_network, list);
1094 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1095 dst_bssid = pnetwork->network.MacAddress;
1096 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1097 r8712_set_802_11_infrastructure_mode(padapter,
1098 pnetwork->network.InfrastructureMode);
1102 spin_unlock_irqrestore(&queue->lock, irqL);
1104 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1107 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1114 static int r8711_wx_get_wap(struct net_device *dev,
1115 struct iw_request_info *info,
1116 union iwreq_data *wrqu, char *extra)
1118 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1119 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1120 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1122 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1123 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1125 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1127 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1131 static int r871x_wx_set_mlme(struct net_device *dev,
1132 struct iw_request_info *info,
1133 union iwreq_data *wrqu, char *extra)
1137 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1138 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1142 reason = cpu_to_le16(mlme->reason_code);
1143 switch (mlme->cmd) {
1144 case IW_MLME_DEAUTH:
1145 if (!r8712_set_802_11_disassociate(padapter))
1148 case IW_MLME_DISASSOC:
1149 if (!r8712_set_802_11_disassociate(padapter))
1160 * This function intends to handle the Set Scan command.
1161 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1163 * For this operation to succeed, the interface is brought Up beforehand.
1166 static int r8711_wx_set_scan(struct net_device *dev,
1167 struct iw_request_info *a,
1168 union iwreq_data *wrqu, char *extra)
1170 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1171 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1174 if (padapter->bDriverStopped == true) {
1175 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1176 __func__, padapter->bDriverStopped);
1179 if (padapter->bup == false)
1181 if (padapter->hw_init_completed == false)
1183 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1184 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1186 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1187 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1189 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1190 struct ndis_802_11_ssid ssid;
1192 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1194 memset((unsigned char *)&ssid, 0,
1195 sizeof(struct ndis_802_11_ssid));
1196 memcpy(ssid.Ssid, req->essid, len);
1197 ssid.SsidLength = len;
1198 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1199 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1200 _FW_UNDER_LINKING)) ||
1201 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1202 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1205 status = r8712_sitesurvey_cmd(padapter, &ssid);
1206 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1209 status = r8712_set_802_11_bssid_list_scan(padapter);
1210 if (status == false)
1215 static int r8711_wx_get_scan(struct net_device *dev,
1216 struct iw_request_info *a,
1217 union iwreq_data *wrqu, char *extra)
1219 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1220 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1221 struct __queue *queue = &pmlmepriv->scanned_queue;
1222 struct wlan_network *pnetwork = NULL;
1224 struct list_head *plist, *phead;
1226 char *stop = ev + wrqu->data.length;
1227 u32 ret = 0, cnt = 0;
1229 if (padapter->bDriverStopped)
1231 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1237 spin_lock_irqsave(&queue->lock, irqL);
1238 phead = &queue->queue;
1239 plist = phead->next;
1241 if (end_of_queue_search(phead, plist) == true)
1243 if ((stop - ev) < SCAN_ITEM_SIZE) {
1247 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1248 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1249 plist = plist->next;
1251 spin_unlock_irqrestore(&queue->lock, irqL);
1252 wrqu->data.length = ev - extra;
1253 wrqu->data.flags = 0;
1258 * s1. set_802_11_infrastructure_mode()
1259 * s2. set_802_11_authenticaion_mode()
1260 * s3. set_802_11_encryption_mode()
1261 * s4. set_802_11_ssid()
1263 * This function intends to handle the Set ESSID command.
1264 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1266 * For this operation to succeed, there is no need for the interface to be Up.
1269 static int r8711_wx_set_essid(struct net_device *dev,
1270 struct iw_request_info *a,
1271 union iwreq_data *wrqu, char *extra)
1273 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1274 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1275 struct __queue *queue = &pmlmepriv->scanned_queue;
1276 struct wlan_network *pnetwork = NULL;
1277 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1278 struct ndis_802_11_ssid ndis_ssid;
1279 u8 *dst_ssid, *src_ssid;
1280 struct list_head *phead;
1283 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1285 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1287 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1289 authmode = padapter->securitypriv.ndisauthtype;
1290 if (wrqu->essid.flags && wrqu->essid.length) {
1291 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1292 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1293 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1294 ndis_ssid.SsidLength = len;
1295 memcpy(ndis_ssid.Ssid, extra, len);
1296 src_ssid = ndis_ssid.Ssid;
1297 phead = &queue->queue;
1298 pmlmepriv->pscanned = phead->next;
1300 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1302 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1303 struct wlan_network, list);
1304 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1305 dst_ssid = pnetwork->network.Ssid.Ssid;
1306 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1307 && (pnetwork->network.Ssid.SsidLength ==
1308 ndis_ssid.SsidLength)) {
1309 if (check_fwstate(pmlmepriv,
1310 WIFI_ADHOC_STATE)) {
1311 if (pnetwork->network.
1315 cur_network.network.
1320 r8712_set_802_11_infrastructure_mode(
1322 pnetwork->network.InfrastructureMode);
1326 r8712_set_802_11_authentication_mode(padapter, authmode);
1327 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1329 return -EINPROGRESS;
1332 static int r8711_wx_get_essid(struct net_device *dev,
1333 struct iw_request_info *a,
1334 union iwreq_data *wrqu, char *extra)
1336 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1337 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1338 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1341 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1342 len = pcur_bss->Ssid.SsidLength;
1343 wrqu->essid.length = len;
1344 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1345 wrqu->essid.flags = 1;
1352 static int r8711_wx_set_rate(struct net_device *dev,
1353 struct iw_request_info *a,
1354 union iwreq_data *wrqu, char *extra)
1356 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1357 u32 target_rate = wrqu->bitrate.value;
1358 u32 fixed = wrqu->bitrate.fixed;
1360 u8 datarates[NumRates];
1361 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1364 if (target_rate == -1) {
1368 target_rate = target_rate / 100000;
1369 switch (target_rate) {
1411 for (i = 0; i < NumRates; i++) {
1412 if (ratevalue == mpdatarate[i]) {
1413 datarates[i] = mpdatarate[i];
1417 datarates[i] = 0xff;
1419 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1424 static int r8711_wx_get_rate(struct net_device *dev,
1425 struct iw_request_info *info,
1426 union iwreq_data *wrqu, char *extra)
1428 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1429 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1430 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1431 struct ieee80211_ht_cap *pht_capie;
1432 unsigned char rf_type = padapter->registrypriv.rf_config;
1435 u16 rate, max_rate = 0, ht_cap = false;
1437 u8 bw_40MHz = 0, short_GI = 0;
1441 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1442 p = r8712_get_ie(&pcur_bss->IEs[12],
1443 _HT_CAPABILITY_IE_, &ht_ielen,
1444 pcur_bss->IELength - 12);
1445 if (p && ht_ielen > 0) {
1447 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1448 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1449 bw_40MHz = (pht_capie->cap_info &
1450 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1451 short_GI = (pht_capie->cap_info &
1452 (IEEE80211_HT_CAP_SGI_20 |
1453 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1455 while ((pcur_bss->SupportedRates[i] != 0) &&
1456 (pcur_bss->SupportedRates[i] != 0xFF)) {
1457 rate = pcur_bss->SupportedRates[i] & 0x7F;
1458 if (rate > max_rate)
1460 wrqu->bitrate.fixed = 0; /* no auto select */
1461 wrqu->bitrate.value = rate*500000;
1464 if (ht_cap == true) {
1465 if (mcs_rate & 0x8000 /* MCS15 */
1467 RTL8712_RF_2T2R == rf_type)
1468 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1469 270) : ((short_GI) ? 144 : 130);
1470 else /* default MCS7 */
1471 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1472 135) : ((short_GI) ? 72 : 65);
1473 max_rate *= 2; /* Mbps/2 */
1475 wrqu->bitrate.value = max_rate * 500000;
1481 static int r8711_wx_get_rts(struct net_device *dev,
1482 struct iw_request_info *info,
1483 union iwreq_data *wrqu, char *extra)
1485 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1487 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1488 wrqu->rts.fixed = 0; /* no auto select */
1492 static int r8711_wx_set_frag(struct net_device *dev,
1493 struct iw_request_info *info,
1494 union iwreq_data *wrqu, char *extra)
1496 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1498 if (wrqu->frag.disabled)
1499 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1501 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1502 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1504 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1509 static int r8711_wx_get_frag(struct net_device *dev,
1510 struct iw_request_info *info,
1511 union iwreq_data *wrqu, char *extra)
1513 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1515 wrqu->frag.value = padapter->xmitpriv.frag_len;
1516 wrqu->frag.fixed = 0; /* no auto select */
1520 static int r8711_wx_get_retry(struct net_device *dev,
1521 struct iw_request_info *info,
1522 union iwreq_data *wrqu, char *extra)
1524 wrqu->retry.value = 7;
1525 wrqu->retry.fixed = 0; /* no auto select */
1526 wrqu->retry.disabled = 1;
1530 static int r8711_wx_set_enc(struct net_device *dev,
1531 struct iw_request_info *info,
1532 union iwreq_data *wrqu, char *keybuf)
1535 u32 keyindex_provided;
1536 struct NDIS_802_11_WEP wep;
1537 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1538 struct iw_point *erq = &(wrqu->encoding);
1539 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1541 key = erq->flags & IW_ENCODE_INDEX;
1542 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1543 if (erq->flags & IW_ENCODE_DISABLED) {
1544 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1545 padapter->securitypriv.ndisencryptstatus =
1546 Ndis802_11EncryptionDisabled;
1547 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1548 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1549 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1550 authmode = Ndis802_11AuthModeOpen;
1551 padapter->securitypriv.ndisauthtype = authmode;
1558 keyindex_provided = 1;
1560 keyindex_provided = 0;
1561 key = padapter->securitypriv.PrivacyKeyIndex;
1563 /* set authentication mode */
1564 if (erq->flags & IW_ENCODE_OPEN) {
1565 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1566 padapter->securitypriv.ndisencryptstatus =
1567 Ndis802_11Encryption1Enabled;
1568 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1569 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1570 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1571 authmode = Ndis802_11AuthModeOpen;
1572 padapter->securitypriv.ndisauthtype = authmode;
1573 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1575 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1576 padapter->securitypriv.ndisencryptstatus =
1577 Ndis802_11Encryption1Enabled;
1578 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1579 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1580 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1581 authmode = Ndis802_11AuthModeShared;
1582 padapter->securitypriv.ndisauthtype = authmode;
1584 padapter->securitypriv.ndisencryptstatus =
1585 Ndis802_11Encryption1Enabled;
1586 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1587 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1588 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1589 authmode = Ndis802_11AuthModeOpen;
1590 padapter->securitypriv.ndisauthtype = authmode;
1593 if (erq->length > 0) {
1594 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1595 wep.Length = wep.KeyLength +
1596 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1599 if (keyindex_provided == 1) { /* set key_id only, no given
1600 * KeyMaterial(erq->length==0).*/
1601 padapter->securitypriv.PrivacyKeyIndex = key;
1602 switch (padapter->securitypriv.DefKeylen[key]) {
1604 padapter->securitypriv.PrivacyAlgrthm =
1608 padapter->securitypriv.PrivacyAlgrthm =
1612 padapter->securitypriv.PrivacyAlgrthm =
1619 wep.KeyIndex |= 0x80000000; /* transmit key */
1620 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1621 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1626 static int r8711_wx_get_enc(struct net_device *dev,
1627 struct iw_request_info *info,
1628 union iwreq_data *wrqu, char *keybuf)
1631 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1632 struct iw_point *erq = &(wrqu->encoding);
1633 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1635 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1636 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1638 erq->flags |= IW_ENCODE_DISABLED;
1642 key = erq->flags & IW_ENCODE_INDEX;
1648 key = padapter->securitypriv.PrivacyKeyIndex;
1650 erq->flags = key + 1;
1651 switch (padapter->securitypriv.ndisencryptstatus) {
1652 case Ndis802_11EncryptionNotSupported:
1653 case Ndis802_11EncryptionDisabled:
1655 erq->flags |= IW_ENCODE_DISABLED;
1657 case Ndis802_11Encryption1Enabled:
1658 erq->length = padapter->securitypriv.DefKeylen[key];
1660 memcpy(keybuf, padapter->securitypriv.DefKey[
1661 key].skey, padapter->securitypriv.
1663 erq->flags |= IW_ENCODE_ENABLED;
1664 if (padapter->securitypriv.ndisauthtype ==
1665 Ndis802_11AuthModeOpen)
1666 erq->flags |= IW_ENCODE_OPEN;
1667 else if (padapter->securitypriv.ndisauthtype ==
1668 Ndis802_11AuthModeShared)
1669 erq->flags |= IW_ENCODE_RESTRICTED;
1672 erq->flags |= IW_ENCODE_DISABLED;
1675 case Ndis802_11Encryption2Enabled:
1676 case Ndis802_11Encryption3Enabled:
1678 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1683 erq->flags |= IW_ENCODE_DISABLED;
1689 static int r8711_wx_get_power(struct net_device *dev,
1690 struct iw_request_info *info,
1691 union iwreq_data *wrqu, char *extra)
1693 wrqu->power.value = 0;
1694 wrqu->power.fixed = 0; /* no auto select */
1695 wrqu->power.disabled = 1;
1699 static int r871x_wx_set_gen_ie(struct net_device *dev,
1700 struct iw_request_info *info,
1701 union iwreq_data *wrqu, char *extra)
1703 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1705 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1708 static int r871x_wx_set_auth(struct net_device *dev,
1709 struct iw_request_info *info,
1710 union iwreq_data *wrqu, char *extra)
1712 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1713 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1718 paramid = param->flags & IW_AUTH_INDEX;
1719 paramval = param->value;
1721 case IW_AUTH_WPA_VERSION:
1723 case IW_AUTH_CIPHER_PAIRWISE:
1725 case IW_AUTH_CIPHER_GROUP:
1727 case IW_AUTH_KEY_MGMT:
1729 * ??? does not use these parameters
1732 case IW_AUTH_TKIP_COUNTERMEASURES:
1734 /* wpa_supplicant is enabling tkip countermeasure. */
1735 padapter->securitypriv.btkip_countermeasure = true;
1737 /* wpa_supplicant is disabling tkip countermeasure. */
1738 padapter->securitypriv.btkip_countermeasure = false;
1741 case IW_AUTH_DROP_UNENCRYPTED:
1744 * wpa_supplicant calls set_wpa_enabled when the driver
1745 * is loaded and unloaded, regardless of if WPA is being
1746 * used. No other calls are made which can be used to
1747 * determine if encryption will be used or not prior to
1748 * association being expected. If encryption is not being
1749 * used, drop_unencrypted is set to false, else true -- we
1750 * can use this to determine if the CAP_PRIVACY_ON bit should
1753 if (padapter->securitypriv.ndisencryptstatus ==
1754 Ndis802_11Encryption1Enabled) {
1755 /* it means init value, or using wep,
1756 * ndisencryptstatus =
1757 * Ndis802_11Encryption1Enabled,
1758 * then it needn't reset it;
1764 padapter->securitypriv.ndisencryptstatus =
1765 Ndis802_11EncryptionDisabled;
1766 padapter->securitypriv.PrivacyAlgrthm =
1768 padapter->securitypriv.XGrpPrivacy =
1770 padapter->securitypriv.AuthAlgrthm = 0;
1771 padapter->securitypriv.ndisauthtype =
1772 Ndis802_11AuthModeOpen;
1775 case IW_AUTH_80211_AUTH_ALG:
1776 ret = wpa_set_auth_algs(dev, (u32)paramval);
1778 case IW_AUTH_WPA_ENABLED:
1780 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1782 case IW_AUTH_PRIVACY_INVOKED:
1791 static int r871x_wx_set_enc_ext(struct net_device *dev,
1792 struct iw_request_info *info,
1793 union iwreq_data *wrqu, char *extra)
1795 struct iw_point *pencoding = &wrqu->encoding;
1796 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1797 struct ieee_param *param = NULL;
1802 switch (pext->alg) {
1803 case IW_ENCODE_ALG_NONE:
1806 case IW_ENCODE_ALG_WEP:
1809 case IW_ENCODE_ALG_TKIP:
1812 case IW_ENCODE_ALG_CCMP:
1819 param_len = sizeof(struct ieee_param) + pext->key_len;
1820 param = kzalloc(param_len, GFP_ATOMIC);
1823 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1824 memset(param->sta_addr, 0xff, ETH_ALEN);
1826 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1827 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1828 param->u.crypt.set_tx = 0;
1829 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1830 param->u.crypt.set_tx = 1;
1831 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1832 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1833 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1834 if (pext->key_len) {
1835 param->u.crypt.key_len = pext->key_len;
1836 memcpy(param + 1, pext + 1, pext->key_len);
1838 ret = wpa_set_encryption(dev, param, param_len);
1843 static int r871x_wx_get_nick(struct net_device *dev,
1844 struct iw_request_info *info,
1845 union iwreq_data *wrqu, char *extra)
1848 wrqu->data.length = 8;
1849 wrqu->data.flags = 1;
1850 memcpy(extra, "rtl_wifi", 8);
1855 static int r8711_wx_read32(struct net_device *dev,
1856 struct iw_request_info *info,
1857 union iwreq_data *wrqu, char *keybuf)
1859 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1863 get_user(addr, (u32 __user *)wrqu->data.pointer);
1864 data32 = r8712_read32(padapter, addr);
1865 put_user(data32, (u32 __user *)wrqu->data.pointer);
1866 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1867 wrqu->data.flags = data32 & 0xffff;
1868 get_user(addr, (u32 __user *)wrqu->data.pointer);
1872 static int r8711_wx_write32(struct net_device *dev,
1873 struct iw_request_info *info,
1874 union iwreq_data *wrqu, char *keybuf)
1876 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1880 get_user(addr, (u32 __user *)wrqu->data.pointer);
1881 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
1882 r8712_write32(padapter, addr, data32);
1886 static int dummy(struct net_device *dev,
1887 struct iw_request_info *a,
1888 union iwreq_data *wrqu, char *b)
1893 static int r8711_drvext_hdl(struct net_device *dev,
1894 struct iw_request_info *info,
1895 union iwreq_data *wrqu, char *extra)
1900 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1901 struct iw_request_info *info,
1902 union iwreq_data *wrqu, char *extra)
1904 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1905 struct iw_point *p = &wrqu->data;
1906 struct oid_par_priv oid_par;
1907 struct mp_ioctl_handler *phandler;
1908 struct mp_ioctl_param *poidparam;
1909 unsigned long BytesRead, BytesWritten, BytesNeeded;
1910 u8 *pparmbuf = NULL, bset;
1915 if ((!p->length) || (!p->pointer)) {
1917 goto _r871x_mp_ioctl_hdl_exit;
1919 bset = (u8)(p->flags & 0xFFFF);
1922 pparmbuf = kmalloc(len, GFP_ATOMIC);
1923 if (pparmbuf == NULL) {
1925 goto _r871x_mp_ioctl_hdl_exit;
1927 if (copy_from_user(pparmbuf, p->pointer, len)) {
1929 goto _r871x_mp_ioctl_hdl_exit;
1931 poidparam = (struct mp_ioctl_param *)pparmbuf;
1932 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1934 goto _r871x_mp_ioctl_hdl_exit;
1936 phandler = mp_ioctl_hdl + poidparam->subcode;
1937 if ((phandler->paramsize != 0) &&
1938 (poidparam->len < phandler->paramsize)) {
1940 goto _r871x_mp_ioctl_hdl_exit;
1942 if (phandler->oid == 0 && phandler->handler)
1943 status = phandler->handler(&oid_par);
1944 else if (phandler->handler) {
1945 oid_par.adapter_context = padapter;
1946 oid_par.oid = phandler->oid;
1947 oid_par.information_buf = poidparam->data;
1948 oid_par.information_buf_len = poidparam->len;
1953 oid_par.bytes_rw = &BytesRead;
1954 oid_par.bytes_needed = &BytesNeeded;
1955 oid_par.type_of_oid = SET_OID;
1957 oid_par.bytes_rw = &BytesWritten;
1958 oid_par.bytes_needed = &BytesNeeded;
1959 oid_par.type_of_oid = QUERY_OID;
1961 status = phandler->handler(&oid_par);
1962 /* todo:check status, BytesNeeded, etc. */
1964 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1965 __func__, poidparam->subcode, phandler->oid,
1968 goto _r871x_mp_ioctl_hdl_exit;
1970 if (bset == 0x00) { /* query info */
1971 if (copy_to_user(p->pointer, pparmbuf, len))
1976 goto _r871x_mp_ioctl_hdl_exit;
1978 _r871x_mp_ioctl_hdl_exit:
1983 static int r871x_get_ap_info(struct net_device *dev,
1984 struct iw_request_info *info,
1985 union iwreq_data *wrqu, char *extra)
1987 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1988 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1989 struct __queue *queue = &pmlmepriv->scanned_queue;
1990 struct iw_point *pdata = &wrqu->data;
1991 struct wlan_network *pnetwork = NULL;
1992 u32 cnt = 0, wpa_ielen;
1994 struct list_head *plist, *phead;
1995 unsigned char *pbuf;
1999 if (padapter->bDriverStopped || (pdata == NULL))
2001 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
2008 if (pdata->length >= 32) {
2009 if (copy_from_user(data, pdata->pointer, 32))
2013 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2014 phead = &queue->queue;
2015 plist = phead->next;
2017 if (end_of_queue_search(phead, plist) == true)
2019 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2020 if (hwaddr_aton_i(data, bssid)) {
2021 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
2023 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2027 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
2028 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2029 /* BSSID match, then check if supporting wpa/wpa2 */
2030 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2031 &wpa_ielen, pnetwork->network.IELength-12);
2032 if (pbuf && (wpa_ielen > 0)) {
2036 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2037 &wpa_ielen, pnetwork->network.IELength-12);
2038 if (pbuf && (wpa_ielen > 0)) {
2043 plist = plist->next;
2045 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2046 if (pdata->length >= 34) {
2047 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2048 (u8 *)&pdata->flags, 1))
2054 static int r871x_set_pid(struct net_device *dev,
2055 struct iw_request_info *info,
2056 union iwreq_data *wrqu, char *extra)
2058 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2059 struct iw_point *pdata = &wrqu->data;
2061 if ((padapter->bDriverStopped) || (pdata == NULL))
2063 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2068 static int r871x_set_chplan(struct net_device *dev,
2069 struct iw_request_info *info,
2070 union iwreq_data *wrqu, char *extra)
2073 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2074 struct iw_point *pdata = &wrqu->data;
2077 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2081 ch_plan = (int)*extra;
2082 r8712_set_chplan_cmd(padapter, ch_plan);
2089 static int r871x_wps_start(struct net_device *dev,
2090 struct iw_request_info *info,
2091 union iwreq_data *wrqu, char *extra)
2093 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2094 struct iw_point *pdata = &wrqu->data;
2095 u32 u32wps_start = 0;
2097 if ((padapter->bDriverStopped) || (pdata == NULL))
2099 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2101 if (u32wps_start == 0)
2102 u32wps_start = *extra;
2103 if (u32wps_start == 1) /* WPS Start */
2104 padapter->ledpriv.LedControlHandler(padapter,
2106 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2107 padapter->ledpriv.LedControlHandler(padapter,
2109 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2110 padapter->ledpriv.LedControlHandler(padapter,
2111 LED_CTL_STOP_WPS_FAIL);
2115 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2117 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2120 case IEEE_PARAM_WPA_ENABLED:
2121 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2122 switch ((value)&0xff) {
2124 padapter->securitypriv.ndisauthtype =
2125 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2126 padapter->securitypriv.ndisencryptstatus =
2127 Ndis802_11Encryption2Enabled;
2130 padapter->securitypriv.ndisauthtype =
2131 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2132 padapter->securitypriv.ndisencryptstatus =
2133 Ndis802_11Encryption3Enabled;
2137 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2139 case IEEE_PARAM_DROP_UNENCRYPTED:
2142 * wpa_supplicant calls set_wpa_enabled when the driver
2143 * is loaded and unloaded, regardless of if WPA is being
2144 * used. No other calls are made which can be used to
2145 * determine if encryption will be used or not prior to
2146 * association being expected. If encryption is not being
2147 * used, drop_unencrypted is set to false, else true -- we
2148 * can use this to determine if the CAP_PRIVACY_ON bit should
2152 case IEEE_PARAM_PRIVACY_INVOKED:
2154 case IEEE_PARAM_AUTH_ALGS:
2155 return wpa_set_auth_algs(dev, value);
2156 case IEEE_PARAM_IEEE_802_1X:
2158 case IEEE_PARAM_WPAX_SELECT:
2159 /* added for WPA2 mixed mode */
2167 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2169 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2172 case IEEE_MLME_STA_DEAUTH:
2173 if (!r8712_set_802_11_disassociate(padapter))
2176 case IEEE_MLME_STA_DISASSOC:
2177 if (!r8712_set_802_11_disassociate(padapter))
2186 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2188 struct ieee_param *param;
2190 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2192 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2194 param = memdup_user(p->pointer, p->length);
2196 return PTR_ERR(param);
2197 switch (param->cmd) {
2198 case IEEE_CMD_SET_WPA_PARAM:
2199 ret = wpa_set_param(dev, param->u.wpa_param.name,
2200 param->u.wpa_param.value);
2202 case IEEE_CMD_SET_WPA_IE:
2203 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2204 (u16)param->u.wpa_ie.len);
2206 case IEEE_CMD_SET_ENCRYPTION:
2207 ret = wpa_set_encryption(dev, param, p->length);
2210 ret = wpa_mlme(dev, param->u.mlme.command,
2211 param->u.mlme.reason_code);
2217 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2223 /* based on "driver_ipw" and for hostapd */
2224 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2226 struct iwreq *wrq = (struct iwreq *)rq;
2229 case RTL_IOCTL_WPA_SUPPLICANT:
2230 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2237 static iw_handler r8711_handlers[] = {
2238 NULL, /* SIOCSIWCOMMIT */
2239 r8711_wx_get_name, /* SIOCGIWNAME */
2240 dummy, /* SIOCSIWNWID */
2241 dummy, /* SIOCGIWNWID */
2242 r8711_wx_set_freq, /* SIOCSIWFREQ */
2243 r8711_wx_get_freq, /* SIOCGIWFREQ */
2244 r8711_wx_set_mode, /* SIOCSIWMODE */
2245 r8711_wx_get_mode, /* SIOCGIWMODE */
2246 dummy, /* SIOCSIWSENS */
2247 r8711_wx_get_sens, /* SIOCGIWSENS */
2248 NULL, /* SIOCSIWRANGE */
2249 r8711_wx_get_range, /* SIOCGIWRANGE */
2250 r871x_wx_set_priv, /* SIOCSIWPRIV */
2251 NULL, /* SIOCGIWPRIV */
2252 NULL, /* SIOCSIWSTATS */
2253 NULL, /* SIOCGIWSTATS */
2254 dummy, /* SIOCSIWSPY */
2255 dummy, /* SIOCGIWSPY */
2256 NULL, /* SIOCGIWTHRSPY */
2257 NULL, /* SIOCWIWTHRSPY */
2258 r8711_wx_set_wap, /* SIOCSIWAP */
2259 r8711_wx_get_wap, /* SIOCGIWAP */
2260 r871x_wx_set_mlme, /* request MLME operation;
2261 * uses struct iw_mlme */
2262 dummy, /* SIOCGIWAPLIST -- deprecated */
2263 r8711_wx_set_scan, /* SIOCSIWSCAN */
2264 r8711_wx_get_scan, /* SIOCGIWSCAN */
2265 r8711_wx_set_essid, /* SIOCSIWESSID */
2266 r8711_wx_get_essid, /* SIOCGIWESSID */
2267 dummy, /* SIOCSIWNICKN */
2268 r871x_wx_get_nick, /* SIOCGIWNICKN */
2269 NULL, /* -- hole -- */
2270 NULL, /* -- hole -- */
2271 r8711_wx_set_rate, /* SIOCSIWRATE */
2272 r8711_wx_get_rate, /* SIOCGIWRATE */
2273 dummy, /* SIOCSIWRTS */
2274 r8711_wx_get_rts, /* SIOCGIWRTS */
2275 r8711_wx_set_frag, /* SIOCSIWFRAG */
2276 r8711_wx_get_frag, /* SIOCGIWFRAG */
2277 dummy, /* SIOCSIWTXPOW */
2278 dummy, /* SIOCGIWTXPOW */
2279 dummy, /* SIOCSIWRETRY */
2280 r8711_wx_get_retry, /* SIOCGIWRETRY */
2281 r8711_wx_set_enc, /* SIOCSIWENCODE */
2282 r8711_wx_get_enc, /* SIOCGIWENCODE */
2283 dummy, /* SIOCSIWPOWER */
2284 r8711_wx_get_power, /* SIOCGIWPOWER */
2285 NULL, /*---hole---*/
2286 NULL, /*---hole---*/
2287 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2288 NULL, /* SIOCGIWGENIE */
2289 r871x_wx_set_auth, /* SIOCSIWAUTH */
2290 NULL, /* SIOCGIWAUTH */
2291 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2292 NULL, /* SIOCGIWENCODEEXT */
2293 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2294 NULL, /*---hole---*/
2297 static const struct iw_priv_args r8711_private_args[] = {
2299 SIOCIWFIRSTPRIV + 0x0,
2300 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2303 SIOCIWFIRSTPRIV + 0x1,
2304 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2307 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2310 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2313 SIOCIWFIRSTPRIV + 0x4,
2314 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2317 SIOCIWFIRSTPRIV + 0x5,
2318 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2321 SIOCIWFIRSTPRIV + 0x6,
2322 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2325 SIOCIWFIRSTPRIV + 0x7,
2326 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2330 static iw_handler r8711_private_handler[] = {
2335 r871x_get_ap_info, /*for MM DTV platform*/
2341 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2343 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2344 struct iw_statistics *piwstats = &padapter->iwstats;
2349 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2350 piwstats->qual.qual = 0;
2351 piwstats->qual.level = 0;
2352 piwstats->qual.noise = 0;
2354 /* show percentage, we need transfer dbm to orignal value. */
2355 tmp_level = padapter->recvpriv.fw_rssi;
2356 tmp_qual = padapter->recvpriv.signal;
2357 tmp_noise = padapter->recvpriv.noise;
2358 piwstats->qual.level = tmp_level;
2359 piwstats->qual.qual = tmp_qual;
2360 piwstats->qual.noise = tmp_noise;
2362 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2363 return &padapter->iwstats;
2366 struct iw_handler_def r871x_handlers_def = {
2367 .standard = r8711_handlers,
2368 .num_standard = ARRAY_SIZE(r8711_handlers),
2369 .private = r8711_private_handler,
2370 .private_args = (struct iw_priv_args *)r8711_private_args,
2371 .num_private = ARRAY_SIZE(r8711_private_handler),
2372 .num_private_args = sizeof(r8711_private_args) /
2373 sizeof(struct iw_priv_args),
2374 .get_wireless_stats = r871x_get_wireless_stats