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;
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);
201 /* Add the protocol name */
202 iwe.cmd = SIOCGIWNAME;
203 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
204 SupportedRates)) == true) {
206 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
208 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
209 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
210 SupportedRates)) == true) {
212 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
214 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
217 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
219 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
221 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
223 iwe.cmd = SIOCGIWMODE;
224 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
226 cap = le16_to_cpu(cap);
227 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
228 if (cap & WLAN_CAPABILITY_BSS)
229 iwe.u.mode = (u32)IW_MODE_MASTER;
231 iwe.u.mode = (u32)IW_MODE_ADHOC;
232 start = iwe_stream_add_event(info, start, stop, &iwe,
235 /* Add frequency/channel */
236 iwe.cmd = SIOCGIWFREQ;
238 /* check legal index */
239 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
241 if (dsconfig >= 1 && dsconfig <= sizeof(
242 ieee80211_wlan_frequencies) / sizeof(long))
243 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
244 pnetwork->network.Configuration.
245 DSConfig - 1] * 100000);
249 iwe.u.freq.e = (s16)1;
250 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
251 start = iwe_stream_add_event(info, start, stop, &iwe,
253 /* Add encryption capability */
254 iwe.cmd = SIOCGIWENCODE;
255 if (cap & WLAN_CAPABILITY_PRIVACY)
256 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
259 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
260 iwe.u.data.length = (u16)0;
261 start = iwe_stream_add_point(info, start, stop, &iwe,
262 pnetwork->network.Ssid.Ssid);
263 /*Add basic and extended rates */
264 current_val = start + iwe_stream_lcp_len(info);
265 iwe.cmd = SIOCGIWRATE;
266 iwe.u.bitrate.fixed = 0;
267 iwe.u.bitrate.disabled = 0;
268 iwe.u.bitrate.value = 0;
270 while (pnetwork->network.SupportedRates[i] != 0) {
271 /* Bit rate given in 500 kb/s units */
272 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
274 current_val = iwe_stream_add_value(info, start, current_val,
275 stop, &iwe, IW_EV_PARAM_LEN);
277 /* Check if we added any event */
278 if ((current_val - start) > iwe_stream_lcp_len(info))
280 /* parsing WPA/WPA2 IE */
282 u8 buf[MAX_WPA_IE_LEN];
283 u8 wpa_ie[255], rsn_ie[255];
284 u16 wpa_len = 0, rsn_len = 0;
287 r8712_get_sec_ie(pnetwork->network.IEs,
288 pnetwork->network.IELength, rsn_ie, &rsn_len,
291 memset(buf, 0, MAX_WPA_IE_LEN);
292 n = sprintf(buf, "wpa_ie=");
293 for (i = 0; i < wpa_len; i++) {
294 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
296 if (n >= MAX_WPA_IE_LEN)
299 memset(&iwe, 0, sizeof(iwe));
300 iwe.cmd = IWEVCUSTOM;
301 iwe.u.data.length = (u16)strlen(buf);
302 start = iwe_stream_add_point(info, start, stop,
304 memset(&iwe, 0, sizeof(iwe));
306 iwe.u.data.length = (u16)wpa_len;
307 start = iwe_stream_add_point(info, start, stop,
311 memset(buf, 0, MAX_WPA_IE_LEN);
312 n = sprintf(buf, "rsn_ie=");
313 for (i = 0; i < rsn_len; i++) {
314 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
316 if (n >= MAX_WPA_IE_LEN)
319 memset(&iwe, 0, sizeof(iwe));
320 iwe.cmd = IWEVCUSTOM;
321 iwe.u.data.length = strlen(buf);
322 start = iwe_stream_add_point(info, start, stop,
324 memset(&iwe, 0, sizeof(iwe));
326 iwe.u.data.length = rsn_len;
327 start = iwe_stream_add_point(info, start, stop, &iwe,
332 { /* parsing WPS IE */
336 if (r8712_get_wps_ie(pnetwork->network.IEs,
337 pnetwork->network.IELength,
338 wps_ie, &wps_ielen) == true) {
341 iwe.u.data.length = (u16)wps_ielen;
342 start = iwe_stream_add_point(info, start, stop,
347 /* Add quality statistics */
349 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
350 /* we only update signal_level (signal strength) that is rssi. */
351 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
352 IW_QUAL_NOISE_INVALID);
353 iwe.u.qual.level = rssi; /* signal strength */
354 iwe.u.qual.qual = 0; /* signal quality */
355 iwe.u.qual.noise = 0; /* noise level */
356 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
357 /* how to translate rssi to ?% */
361 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
363 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
366 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
367 padapter->securitypriv.ndisencryptstatus =
368 Ndis802_11Encryption1Enabled;
369 padapter->securitypriv.ndisauthtype =
370 Ndis802_11AuthModeAutoSwitch;
371 padapter->securitypriv.AuthAlgrthm = 3;
372 } else if (value & AUTH_ALG_SHARED_KEY) {
373 padapter->securitypriv.ndisencryptstatus =
374 Ndis802_11Encryption1Enabled;
375 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
376 padapter->securitypriv.AuthAlgrthm = 1;
377 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
378 if (padapter->securitypriv.ndisauthtype <
379 Ndis802_11AuthModeWPAPSK) {
380 padapter->securitypriv.ndisauthtype =
381 Ndis802_11AuthModeOpen;
382 padapter->securitypriv.AuthAlgrthm = 0;
389 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
393 u32 wep_key_idx, wep_key_len = 0;
394 struct NDIS_802_11_WEP *pwep = NULL;
395 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
396 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
397 struct security_priv *psecuritypriv = &padapter->securitypriv;
399 param->u.crypt.err = 0;
400 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
401 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
402 param->u.crypt.key_len)
404 if (is_broadcast_ether_addr(param->sta_addr)) {
405 if (param->u.crypt.idx >= WEP_KEYS) {
406 /* for large key indices, set the default (0) */
407 param->u.crypt.idx = 0;
411 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
412 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
413 padapter->securitypriv.ndisencryptstatus =
414 Ndis802_11Encryption1Enabled;
415 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
416 padapter->securitypriv.XGrpPrivacy = _WEP40_;
417 wep_key_idx = param->u.crypt.idx;
418 wep_key_len = param->u.crypt.key_len;
419 if (wep_key_idx >= WEP_KEYS)
421 if (wep_key_len > 0) {
422 wep_key_len = wep_key_len <= 5 ? 5 : 13;
423 pwep = kmalloc((u32)(wep_key_len +
424 FIELD_OFFSET(struct NDIS_802_11_WEP,
425 KeyMaterial)), GFP_ATOMIC);
428 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
429 pwep->KeyLength = wep_key_len;
430 pwep->Length = wep_key_len +
431 FIELD_OFFSET(struct NDIS_802_11_WEP,
433 if (wep_key_len == 13) {
434 padapter->securitypriv.PrivacyAlgrthm =
436 padapter->securitypriv.XGrpPrivacy =
441 pwep->KeyIndex = wep_key_idx;
442 pwep->KeyIndex |= 0x80000000;
443 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
444 if (param->u.crypt.set_tx) {
445 if (r8712_set_802_11_add_wep(padapter, pwep) ==
449 /* don't update "psecuritypriv->PrivacyAlgrthm" and
450 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
451 * r8712_set_key to fw/cam
453 if (wep_key_idx >= WEP_KEYS) {
457 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
458 skey[0]), pwep->KeyMaterial,
460 psecuritypriv->DefKeylen[wep_key_idx] =
462 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
466 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
467 struct sta_info *psta, *pbcmc_sta;
468 struct sta_priv *pstapriv = &padapter->stapriv;
470 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
471 WIFI_MP_STATE) == true) { /* sta mode */
472 psta = r8712_get_stainfo(pstapriv,
473 get_bssid(pmlmepriv));
475 psta->ieee8021x_blocked = false;
476 if ((padapter->securitypriv.ndisencryptstatus ==
477 Ndis802_11Encryption2Enabled) ||
478 (padapter->securitypriv.ndisencryptstatus ==
479 Ndis802_11Encryption3Enabled))
480 psta->XPrivacy = padapter->
481 securitypriv.PrivacyAlgrthm;
482 if (param->u.crypt.set_tx == 1)
483 handle_pairwise_key(psta, param,
486 handle_group_key(param, padapter);
488 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
490 pbcmc_sta->ieee8021x_blocked = false;
491 if ((padapter->securitypriv.ndisencryptstatus ==
492 Ndis802_11Encryption2Enabled) ||
493 (padapter->securitypriv.ndisencryptstatus ==
494 Ndis802_11Encryption3Enabled))
495 pbcmc_sta->XPrivacy =
496 padapter->securitypriv.
506 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
507 unsigned short ielen)
510 int group_cipher = 0, pairwise_cipher = 0;
513 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
516 buf = kmemdup(pie, ielen, GFP_ATOMIC);
519 if (ielen < RSN_HEADER_LEN) {
523 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
524 &pairwise_cipher) == _SUCCESS) {
525 padapter->securitypriv.AuthAlgrthm = 2;
526 padapter->securitypriv.ndisauthtype =
527 Ndis802_11AuthModeWPAPSK;
529 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
530 &pairwise_cipher) == _SUCCESS) {
531 padapter->securitypriv.AuthAlgrthm = 2;
532 padapter->securitypriv.ndisauthtype =
533 Ndis802_11AuthModeWPA2PSK;
535 switch (group_cipher) {
536 case WPA_CIPHER_NONE:
537 padapter->securitypriv.XGrpPrivacy =
539 padapter->securitypriv.ndisencryptstatus =
540 Ndis802_11EncryptionDisabled;
542 case WPA_CIPHER_WEP40:
543 padapter->securitypriv.XGrpPrivacy = _WEP40_;
544 padapter->securitypriv.ndisencryptstatus =
545 Ndis802_11Encryption1Enabled;
547 case WPA_CIPHER_TKIP:
548 padapter->securitypriv.XGrpPrivacy = _TKIP_;
549 padapter->securitypriv.ndisencryptstatus =
550 Ndis802_11Encryption2Enabled;
552 case WPA_CIPHER_CCMP:
553 padapter->securitypriv.XGrpPrivacy = _AES_;
554 padapter->securitypriv.ndisencryptstatus =
555 Ndis802_11Encryption3Enabled;
557 case WPA_CIPHER_WEP104:
558 padapter->securitypriv.XGrpPrivacy = _WEP104_;
559 padapter->securitypriv.ndisencryptstatus =
560 Ndis802_11Encryption1Enabled;
563 switch (pairwise_cipher) {
564 case WPA_CIPHER_NONE:
565 padapter->securitypriv.PrivacyAlgrthm =
567 padapter->securitypriv.ndisencryptstatus =
568 Ndis802_11EncryptionDisabled;
570 case WPA_CIPHER_WEP40:
571 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
572 padapter->securitypriv.ndisencryptstatus =
573 Ndis802_11Encryption1Enabled;
575 case WPA_CIPHER_TKIP:
576 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
577 padapter->securitypriv.ndisencryptstatus =
578 Ndis802_11Encryption2Enabled;
580 case WPA_CIPHER_CCMP:
581 padapter->securitypriv.PrivacyAlgrthm = _AES_;
582 padapter->securitypriv.ndisencryptstatus =
583 Ndis802_11Encryption3Enabled;
585 case WPA_CIPHER_WEP104:
586 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
587 padapter->securitypriv.ndisencryptstatus =
588 Ndis802_11Encryption1Enabled;
591 padapter->securitypriv.wps_phase = false;
594 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
596 while (cnt < ielen) {
599 if ((eid == _VENDOR_SPECIFIC_IE_) &&
600 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
601 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
602 padapter->securitypriv.wps_ie_len =
604 (MAX_WPA_IE_LEN << 2)) ?
606 (MAX_WPA_IE_LEN << 2);
607 memcpy(padapter->securitypriv.wps_ie,
609 padapter->securitypriv.wps_ie_len);
610 padapter->securitypriv.wps_phase =
612 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
616 cnt += buf[cnt + 1] + 2;
625 static int r8711_wx_get_name(struct net_device *dev,
626 struct iw_request_info *info,
627 union iwreq_data *wrqu, char *extra)
629 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
633 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
634 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
635 NDIS_802_11_RATES_EX *prates = NULL;
637 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
639 /* parsing HT_CAP_IE */
640 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
641 &ht_ielen, pcur_bss->IELength - 12);
642 if (p && ht_ielen > 0)
644 prates = &pcur_bss->SupportedRates;
645 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
647 snprintf(wrqu->name, IFNAMSIZ,
650 snprintf(wrqu->name, IFNAMSIZ,
652 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
654 snprintf(wrqu->name, IFNAMSIZ,
657 snprintf(wrqu->name, IFNAMSIZ,
661 snprintf(wrqu->name, IFNAMSIZ,
664 snprintf(wrqu->name, IFNAMSIZ,
668 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
672 static const long frequency_list[] = {
673 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
674 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
675 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
676 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
677 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
681 static int r8711_wx_set_freq(struct net_device *dev,
682 struct iw_request_info *info,
683 union iwreq_data *wrqu, char *extra)
685 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
686 struct iw_freq *fwrq = &wrqu->freq;
689 /* If setting by frequency, convert to a channel */
690 if ((fwrq->e == 1) &&
691 (fwrq->m >= (int) 2.412e8) &&
692 (fwrq->m <= (int) 2.487e8)) {
693 int f = fwrq->m / 100000;
696 while ((c < 14) && (f != frequency_list[c]))
701 /* Setting by channel number */
702 if ((fwrq->m > 14) || (fwrq->e > 0))
705 int channel = fwrq->m;
707 if ((channel < 1) || (channel > 14))
710 /* Yes ! We can set it !!! */
711 padapter->registrypriv.channel = channel;
717 static int r8711_wx_get_freq(struct net_device *dev,
718 struct iw_request_info *info,
719 union iwreq_data *wrqu, char *extra)
721 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
722 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
723 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
725 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
726 wrqu->freq.m = ieee80211_wlan_frequencies[
727 pcur_bss->Configuration.DSConfig-1] * 100000;
729 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
736 static int r8711_wx_set_mode(struct net_device *dev,
737 struct iw_request_info *a,
738 union iwreq_data *wrqu, char *b)
740 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
741 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
743 switch (wrqu->mode) {
745 networkType = Ndis802_11AutoUnknown;
748 networkType = Ndis802_11IBSS;
751 networkType = Ndis802_11APMode;
754 networkType = Ndis802_11Infrastructure;
759 if (Ndis802_11APMode == networkType)
760 r8712_setopmode_cmd(padapter, networkType);
762 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
764 r8712_set_802_11_infrastructure_mode(padapter, networkType);
768 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
769 union iwreq_data *wrqu, char *b)
771 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
772 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
774 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
775 wrqu->mode = IW_MODE_INFRA;
776 else if (check_fwstate(pmlmepriv,
777 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
778 wrqu->mode = IW_MODE_ADHOC;
779 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
780 wrqu->mode = IW_MODE_MASTER;
782 wrqu->mode = IW_MODE_AUTO;
786 static int r871x_wx_set_pmkid(struct net_device *dev,
787 struct iw_request_info *a,
788 union iwreq_data *wrqu, char *extra)
790 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
791 struct security_priv *psecuritypriv = &padapter->securitypriv;
792 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
793 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
794 u8 strIssueBssid[ETH_ALEN] = {0x00};
795 u8 j, blInserted = false;
796 int intReturn = false;
799 There are the BSSID information in the bssid.sa_data array.
800 If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
801 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
802 wpa_supplicant wants to add a PMKID/BSSID to driver.
803 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
804 remove a PMKID/BSSID from driver.
808 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
811 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
816 /* overwrite PMKID */
817 for (j = 0; j < NUM_PMKID_CACHE; j++) {
818 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
819 strIssueBssid, ETH_ALEN)) {
820 /* BSSID is matched, the same AP => rewrite
822 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
824 memcpy(psecuritypriv->PMKIDList[j].PMKID,
825 pPMK->pmkid, IW_PMKID_LEN);
826 psecuritypriv->PMKIDList[j].bUsed = true;
827 psecuritypriv->PMKIDIndex = j + 1;
833 /* Find a new entry */
834 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
835 __func__, psecuritypriv->PMKIDIndex);
836 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
837 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
838 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
839 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
840 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
842 psecuritypriv->PMKIDIndex++;
843 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
844 psecuritypriv->PMKIDIndex = 0;
847 case IW_PMKSA_REMOVE:
849 for (j = 0; j < NUM_PMKID_CACHE; j++) {
850 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
851 strIssueBssid, ETH_ALEN)) {
852 /* BSSID is matched, the same AP => Remove
853 * this PMKID information and reset it. */
854 memset(psecuritypriv->PMKIDList[j].Bssid,
856 psecuritypriv->PMKIDList[j].bUsed = false;
862 memset(psecuritypriv->PMKIDList, 0,
863 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
864 psecuritypriv->PMKIDIndex = 0;
868 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
875 static int r8711_wx_get_sens(struct net_device *dev,
876 struct iw_request_info *info,
877 union iwreq_data *wrqu, char *extra)
879 wrqu->sens.value = 0;
880 wrqu->sens.fixed = 0; /* no auto select */
881 wrqu->sens.disabled = 1;
885 static int r8711_wx_get_range(struct net_device *dev,
886 struct iw_request_info *info,
887 union iwreq_data *wrqu, char *extra)
889 struct iw_range *range = (struct iw_range *)extra;
893 wrqu->data.length = sizeof(*range);
894 memset(range, 0, sizeof(*range));
895 /* Let's try to keep this struct in the same order as in
896 * linux/include/wireless.h
899 /* TODO: See what values we can set, and remove the ones we can't
900 * set, or fill them with some default data.
902 /* ~5 Mb/s real (802.11b) */
903 range->throughput = 5 * 1000 * 1000;
904 /* TODO: 8711 sensitivity ? */
905 /* signal level threshold range */
906 /* percent values between 0 and 100. */
907 range->max_qual.qual = 100;
908 range->max_qual.level = 100;
909 range->max_qual.noise = 100;
910 range->max_qual.updated = 7; /* Updated all three */
911 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
912 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
913 range->avg_qual.level = 20 + -98;
914 range->avg_qual.noise = 0;
915 range->avg_qual.updated = 7; /* Updated all three */
916 range->num_bitrates = RATE_COUNT;
917 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
918 range->bitrate[i] = rtl8180_rates[i];
919 range->min_frag = MIN_FRAG_THRESHOLD;
920 range->max_frag = MAX_FRAG_THRESHOLD;
922 range->we_version_compiled = WIRELESS_EXT;
923 range->we_version_source = 16;
924 range->num_channels = 14;
925 for (i = 0, val = 0; i < 14; i++) {
926 /* Include only legal frequencies for some countries */
927 range->freq[val].i = i + 1;
928 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
929 range->freq[val].e = 1;
931 if (val == IW_MAX_FREQUENCIES)
934 range->num_frequency = val;
935 range->enc_capa = IW_ENC_CAPA_WPA |
937 IW_ENC_CAPA_CIPHER_TKIP |
938 IW_ENC_CAPA_CIPHER_CCMP;
942 static int r8711_wx_get_rate(struct net_device *dev,
943 struct iw_request_info *info,
944 union iwreq_data *wrqu, char *extra);
946 static int r871x_wx_set_priv(struct net_device *dev,
947 struct iw_request_info *info,
948 union iwreq_data *awrq,
951 int ret = 0, len = 0;
953 struct _adapter *padapter = netdev_priv(dev);
954 struct iw_point *dwrq = (struct iw_point *)awrq;
957 ext = memdup_user(dwrq->pointer, len);
961 if (0 == strcasecmp(ext, "RSSI")) {
962 /*Return received signal strength indicator in -db for */
965 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
966 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
968 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
969 sprintf(ext, "%s rssi %d",
970 pcur_network->network.Ssid.Ssid,
972 ((padapter->recvpriv.fw_rssi)>>1)-95
973 /*pcur_network->network.Rssi */
978 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
979 /*Return link speed in MBPS */
981 union iwreq_data wrqd;
985 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
989 mbps = wrqd.bitrate.value / 1000000;
990 sprintf(ext, "LINKSPEED %d", mbps);
991 } else if (0 == strcasecmp(ext, "MACADDR")) {
992 /*Return mac address of the station */
993 /* Macaddr = xx:xx:xx:xx:xx:xx */
994 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
995 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
996 /*Set scan type to active */
997 /*OK if successful */
998 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1000 pmlmepriv->passive_mode = 1;
1002 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1003 /*Set scan type to passive */
1004 /*OK if successful */
1005 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1007 pmlmepriv->passive_mode = 0;
1009 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1010 /*Set scan type to passive */
1011 /*OK if successful */
1012 r8712_disconnectCtrlEx_cmd(padapter
1013 , 1 /*u32 enableDrvCtrl */
1014 , 5 /*u32 tryPktCnt */
1015 , 100 /*u32 tryPktInterval */
1016 , 5000 /*u32 firstStageTO */
1019 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1020 /*Set scan type to passive */
1021 /*OK if successfu */
1022 r8712_disconnectCtrlEx_cmd(padapter
1023 , 0 /*u32 enableDrvCtrl */
1024 , 5 /*u32 tryPktCnt */
1025 , 100 /*u32 tryPktInterval */
1026 , 5000 /*u32 firstStageTO */
1030 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1034 if (copy_to_user(dwrq->pointer, ext,
1035 min(dwrq->length, (__u16)(strlen(ext)+1))))
1044 * s1. set_802_11_infrastructure_mode()
1045 * s2. set_802_11_authentication_mode()
1046 * s3. set_802_11_encryption_mode()
1047 * s4. set_802_11_bssid()
1049 * This function intends to handle the Set AP command, which specifies the
1050 * MAC# of a preferred Access Point.
1051 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1053 * For this operation to succeed, there is no need for the interface to be up.
1056 static int r8711_wx_set_wap(struct net_device *dev,
1057 struct iw_request_info *info,
1058 union iwreq_data *awrq,
1061 int ret = -EINPROGRESS;
1062 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1063 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1064 struct __queue *queue = &pmlmepriv->scanned_queue;
1065 struct sockaddr *temp = (struct sockaddr *)awrq;
1067 struct list_head *phead;
1069 struct wlan_network *pnetwork = NULL;
1070 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1072 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1074 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1076 if (temp->sa_family != ARPHRD_ETHER)
1078 authmode = padapter->securitypriv.ndisauthtype;
1079 spin_lock_irqsave(&queue->lock, irqL);
1080 phead = &queue->queue;
1081 pmlmepriv->pscanned = phead->next;
1083 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1085 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1086 struct wlan_network, list);
1087 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1088 dst_bssid = pnetwork->network.MacAddress;
1089 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1090 r8712_set_802_11_infrastructure_mode(padapter,
1091 pnetwork->network.InfrastructureMode);
1095 spin_unlock_irqrestore(&queue->lock, irqL);
1097 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1100 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1107 static int r8711_wx_get_wap(struct net_device *dev,
1108 struct iw_request_info *info,
1109 union iwreq_data *wrqu, char *extra)
1111 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1112 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1113 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1115 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1116 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1118 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1120 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1124 static int r871x_wx_set_mlme(struct net_device *dev,
1125 struct iw_request_info *info,
1126 union iwreq_data *wrqu, char *extra)
1129 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1130 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1134 switch (mlme->cmd) {
1135 case IW_MLME_DEAUTH:
1136 if (!r8712_set_802_11_disassociate(padapter))
1139 case IW_MLME_DISASSOC:
1140 if (!r8712_set_802_11_disassociate(padapter))
1151 * This function intends to handle the Set Scan command.
1152 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1154 * For this operation to succeed, the interface is brought Up beforehand.
1157 static int r8711_wx_set_scan(struct net_device *dev,
1158 struct iw_request_info *a,
1159 union iwreq_data *wrqu, char *extra)
1161 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1162 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1165 if (padapter->bDriverStopped == true) {
1166 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1167 __func__, padapter->bDriverStopped);
1170 if (padapter->bup == false)
1172 if (padapter->hw_init_completed == false)
1174 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1175 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1177 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1178 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1180 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1181 struct ndis_802_11_ssid ssid;
1183 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1185 memset((unsigned char *)&ssid, 0,
1186 sizeof(struct ndis_802_11_ssid));
1187 memcpy(ssid.Ssid, req->essid, len);
1188 ssid.SsidLength = len;
1189 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1190 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1191 _FW_UNDER_LINKING)) ||
1192 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1193 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1196 status = r8712_sitesurvey_cmd(padapter, &ssid);
1197 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1200 status = r8712_set_802_11_bssid_list_scan(padapter);
1201 if (status == false)
1206 static int r8711_wx_get_scan(struct net_device *dev,
1207 struct iw_request_info *a,
1208 union iwreq_data *wrqu, char *extra)
1210 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1211 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1212 struct __queue *queue = &pmlmepriv->scanned_queue;
1213 struct wlan_network *pnetwork = NULL;
1215 struct list_head *plist, *phead;
1217 char *stop = ev + wrqu->data.length;
1218 u32 ret = 0, cnt = 0;
1220 if (padapter->bDriverStopped)
1222 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1228 spin_lock_irqsave(&queue->lock, irqL);
1229 phead = &queue->queue;
1230 plist = phead->next;
1232 if (end_of_queue_search(phead, plist) == true)
1234 if ((stop - ev) < SCAN_ITEM_SIZE) {
1238 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1239 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1240 plist = plist->next;
1242 spin_unlock_irqrestore(&queue->lock, irqL);
1243 wrqu->data.length = ev - extra;
1244 wrqu->data.flags = 0;
1249 * s1. set_802_11_infrastructure_mode()
1250 * s2. set_802_11_authenticaion_mode()
1251 * s3. set_802_11_encryption_mode()
1252 * s4. set_802_11_ssid()
1254 * This function intends to handle the Set ESSID command.
1255 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1257 * For this operation to succeed, there is no need for the interface to be Up.
1260 static int r8711_wx_set_essid(struct net_device *dev,
1261 struct iw_request_info *a,
1262 union iwreq_data *wrqu, char *extra)
1264 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1265 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1266 struct __queue *queue = &pmlmepriv->scanned_queue;
1267 struct wlan_network *pnetwork = NULL;
1268 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1269 struct ndis_802_11_ssid ndis_ssid;
1270 u8 *dst_ssid, *src_ssid;
1271 struct list_head *phead;
1274 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1276 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1278 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1280 authmode = padapter->securitypriv.ndisauthtype;
1281 if (wrqu->essid.flags && wrqu->essid.length) {
1282 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1283 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1284 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1285 ndis_ssid.SsidLength = len;
1286 memcpy(ndis_ssid.Ssid, extra, len);
1287 src_ssid = ndis_ssid.Ssid;
1288 phead = &queue->queue;
1289 pmlmepriv->pscanned = phead->next;
1291 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1293 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1294 struct wlan_network, list);
1295 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1296 dst_ssid = pnetwork->network.Ssid.Ssid;
1297 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1298 && (pnetwork->network.Ssid.SsidLength ==
1299 ndis_ssid.SsidLength)) {
1300 if (check_fwstate(pmlmepriv,
1301 WIFI_ADHOC_STATE)) {
1302 if (pnetwork->network.
1306 cur_network.network.
1311 r8712_set_802_11_infrastructure_mode(
1313 pnetwork->network.InfrastructureMode);
1317 r8712_set_802_11_authentication_mode(padapter, authmode);
1318 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1320 return -EINPROGRESS;
1323 static int r8711_wx_get_essid(struct net_device *dev,
1324 struct iw_request_info *a,
1325 union iwreq_data *wrqu, char *extra)
1327 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1328 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1329 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1332 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1333 len = pcur_bss->Ssid.SsidLength;
1334 wrqu->essid.length = len;
1335 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1336 wrqu->essid.flags = 1;
1343 static int r8711_wx_set_rate(struct net_device *dev,
1344 struct iw_request_info *a,
1345 union iwreq_data *wrqu, char *extra)
1347 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1348 u32 target_rate = wrqu->bitrate.value;
1349 u32 fixed = wrqu->bitrate.fixed;
1351 u8 datarates[NumRates];
1352 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1355 if (target_rate == -1) {
1359 target_rate = target_rate / 100000;
1360 switch (target_rate) {
1402 for (i = 0; i < NumRates; i++) {
1403 if (ratevalue == mpdatarate[i]) {
1404 datarates[i] = mpdatarate[i];
1408 datarates[i] = 0xff;
1410 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1415 static int r8711_wx_get_rate(struct net_device *dev,
1416 struct iw_request_info *info,
1417 union iwreq_data *wrqu, char *extra)
1419 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1420 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1421 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1422 struct ieee80211_ht_cap *pht_capie;
1423 unsigned char rf_type = padapter->registrypriv.rf_config;
1426 u16 rate, max_rate = 0, ht_cap = false;
1428 u8 bw_40MHz = 0, short_GI = 0;
1432 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1433 p = r8712_get_ie(&pcur_bss->IEs[12],
1434 _HT_CAPABILITY_IE_, &ht_ielen,
1435 pcur_bss->IELength - 12);
1436 if (p && ht_ielen > 0) {
1438 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1439 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1440 bw_40MHz = (pht_capie->cap_info &
1441 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1442 short_GI = (pht_capie->cap_info &
1443 (IEEE80211_HT_CAP_SGI_20 |
1444 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1446 while ((pcur_bss->SupportedRates[i] != 0) &&
1447 (pcur_bss->SupportedRates[i] != 0xFF)) {
1448 rate = pcur_bss->SupportedRates[i] & 0x7F;
1449 if (rate > max_rate)
1451 wrqu->bitrate.fixed = 0; /* no auto select */
1452 wrqu->bitrate.value = rate*500000;
1455 if (ht_cap == true) {
1456 if (mcs_rate & 0x8000 /* MCS15 */
1458 RTL8712_RF_2T2R == rf_type)
1459 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1460 270) : ((short_GI) ? 144 : 130);
1461 else /* default MCS7 */
1462 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1463 135) : ((short_GI) ? 72 : 65);
1464 max_rate *= 2; /* Mbps/2 */
1466 wrqu->bitrate.value = max_rate * 500000;
1472 static int r8711_wx_get_rts(struct net_device *dev,
1473 struct iw_request_info *info,
1474 union iwreq_data *wrqu, char *extra)
1476 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1478 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1479 wrqu->rts.fixed = 0; /* no auto select */
1483 static int r8711_wx_set_frag(struct net_device *dev,
1484 struct iw_request_info *info,
1485 union iwreq_data *wrqu, char *extra)
1487 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1489 if (wrqu->frag.disabled)
1490 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1492 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1493 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1495 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1500 static int r8711_wx_get_frag(struct net_device *dev,
1501 struct iw_request_info *info,
1502 union iwreq_data *wrqu, char *extra)
1504 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1506 wrqu->frag.value = padapter->xmitpriv.frag_len;
1507 wrqu->frag.fixed = 0; /* no auto select */
1511 static int r8711_wx_get_retry(struct net_device *dev,
1512 struct iw_request_info *info,
1513 union iwreq_data *wrqu, char *extra)
1515 wrqu->retry.value = 7;
1516 wrqu->retry.fixed = 0; /* no auto select */
1517 wrqu->retry.disabled = 1;
1521 static int r8711_wx_set_enc(struct net_device *dev,
1522 struct iw_request_info *info,
1523 union iwreq_data *wrqu, char *keybuf)
1526 u32 keyindex_provided;
1527 struct NDIS_802_11_WEP wep;
1528 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1529 struct iw_point *erq = &(wrqu->encoding);
1530 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1532 key = erq->flags & IW_ENCODE_INDEX;
1533 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1534 if (erq->flags & IW_ENCODE_DISABLED) {
1535 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1536 padapter->securitypriv.ndisencryptstatus =
1537 Ndis802_11EncryptionDisabled;
1538 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1539 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1540 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1541 authmode = Ndis802_11AuthModeOpen;
1542 padapter->securitypriv.ndisauthtype = authmode;
1549 keyindex_provided = 1;
1551 keyindex_provided = 0;
1552 key = padapter->securitypriv.PrivacyKeyIndex;
1554 /* set authentication mode */
1555 if (erq->flags & IW_ENCODE_OPEN) {
1556 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1557 padapter->securitypriv.ndisencryptstatus =
1558 Ndis802_11Encryption1Enabled;
1559 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1560 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1561 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1562 authmode = Ndis802_11AuthModeOpen;
1563 padapter->securitypriv.ndisauthtype = authmode;
1564 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1566 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1567 padapter->securitypriv.ndisencryptstatus =
1568 Ndis802_11Encryption1Enabled;
1569 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1570 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1571 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1572 authmode = Ndis802_11AuthModeShared;
1573 padapter->securitypriv.ndisauthtype = authmode;
1575 padapter->securitypriv.ndisencryptstatus =
1576 Ndis802_11Encryption1Enabled;
1577 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1578 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1579 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1580 authmode = Ndis802_11AuthModeOpen;
1581 padapter->securitypriv.ndisauthtype = authmode;
1584 if (erq->length > 0) {
1585 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1586 wep.Length = wep.KeyLength +
1587 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1590 if (keyindex_provided == 1) { /* set key_id only, no given
1591 * KeyMaterial(erq->length==0).*/
1592 padapter->securitypriv.PrivacyKeyIndex = key;
1593 switch (padapter->securitypriv.DefKeylen[key]) {
1595 padapter->securitypriv.PrivacyAlgrthm =
1599 padapter->securitypriv.PrivacyAlgrthm =
1603 padapter->securitypriv.PrivacyAlgrthm =
1610 wep.KeyIndex |= 0x80000000; /* transmit key */
1611 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1612 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1617 static int r8711_wx_get_enc(struct net_device *dev,
1618 struct iw_request_info *info,
1619 union iwreq_data *wrqu, char *keybuf)
1622 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1623 struct iw_point *erq = &(wrqu->encoding);
1624 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1626 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1627 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1629 erq->flags |= IW_ENCODE_DISABLED;
1633 key = erq->flags & IW_ENCODE_INDEX;
1639 key = padapter->securitypriv.PrivacyKeyIndex;
1641 erq->flags = key + 1;
1642 switch (padapter->securitypriv.ndisencryptstatus) {
1643 case Ndis802_11EncryptionNotSupported:
1644 case Ndis802_11EncryptionDisabled:
1646 erq->flags |= IW_ENCODE_DISABLED;
1648 case Ndis802_11Encryption1Enabled:
1649 erq->length = padapter->securitypriv.DefKeylen[key];
1651 memcpy(keybuf, padapter->securitypriv.DefKey[
1652 key].skey, padapter->securitypriv.
1654 erq->flags |= IW_ENCODE_ENABLED;
1655 if (padapter->securitypriv.ndisauthtype ==
1656 Ndis802_11AuthModeOpen)
1657 erq->flags |= IW_ENCODE_OPEN;
1658 else if (padapter->securitypriv.ndisauthtype ==
1659 Ndis802_11AuthModeShared)
1660 erq->flags |= IW_ENCODE_RESTRICTED;
1663 erq->flags |= IW_ENCODE_DISABLED;
1666 case Ndis802_11Encryption2Enabled:
1667 case Ndis802_11Encryption3Enabled:
1669 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1674 erq->flags |= IW_ENCODE_DISABLED;
1680 static int r8711_wx_get_power(struct net_device *dev,
1681 struct iw_request_info *info,
1682 union iwreq_data *wrqu, char *extra)
1684 wrqu->power.value = 0;
1685 wrqu->power.fixed = 0; /* no auto select */
1686 wrqu->power.disabled = 1;
1690 static int r871x_wx_set_gen_ie(struct net_device *dev,
1691 struct iw_request_info *info,
1692 union iwreq_data *wrqu, char *extra)
1694 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1696 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1699 static int r871x_wx_set_auth(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);
1704 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1709 paramid = param->flags & IW_AUTH_INDEX;
1710 paramval = param->value;
1712 case IW_AUTH_WPA_VERSION:
1714 case IW_AUTH_CIPHER_PAIRWISE:
1716 case IW_AUTH_CIPHER_GROUP:
1718 case IW_AUTH_KEY_MGMT:
1720 * ??? does not use these parameters
1723 case IW_AUTH_TKIP_COUNTERMEASURES:
1725 /* wpa_supplicant is enabling tkip countermeasure. */
1726 padapter->securitypriv.btkip_countermeasure = true;
1728 /* wpa_supplicant is disabling tkip countermeasure. */
1729 padapter->securitypriv.btkip_countermeasure = false;
1732 case IW_AUTH_DROP_UNENCRYPTED:
1735 * wpa_supplicant calls set_wpa_enabled when the driver
1736 * is loaded and unloaded, regardless of if WPA is being
1737 * used. No other calls are made which can be used to
1738 * determine if encryption will be used or not prior to
1739 * association being expected. If encryption is not being
1740 * used, drop_unencrypted is set to false, else true -- we
1741 * can use this to determine if the CAP_PRIVACY_ON bit should
1744 if (padapter->securitypriv.ndisencryptstatus ==
1745 Ndis802_11Encryption1Enabled) {
1746 /* it means init value, or using wep,
1747 * ndisencryptstatus =
1748 * Ndis802_11Encryption1Enabled,
1749 * then it needn't reset it;
1755 padapter->securitypriv.ndisencryptstatus =
1756 Ndis802_11EncryptionDisabled;
1757 padapter->securitypriv.PrivacyAlgrthm =
1759 padapter->securitypriv.XGrpPrivacy =
1761 padapter->securitypriv.AuthAlgrthm = 0;
1762 padapter->securitypriv.ndisauthtype =
1763 Ndis802_11AuthModeOpen;
1766 case IW_AUTH_80211_AUTH_ALG:
1767 ret = wpa_set_auth_algs(dev, (u32)paramval);
1769 case IW_AUTH_WPA_ENABLED:
1771 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1773 case IW_AUTH_PRIVACY_INVOKED:
1782 static int r871x_wx_set_enc_ext(struct net_device *dev,
1783 struct iw_request_info *info,
1784 union iwreq_data *wrqu, char *extra)
1786 struct iw_point *pencoding = &wrqu->encoding;
1787 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1788 struct ieee_param *param = NULL;
1793 switch (pext->alg) {
1794 case IW_ENCODE_ALG_NONE:
1797 case IW_ENCODE_ALG_WEP:
1800 case IW_ENCODE_ALG_TKIP:
1803 case IW_ENCODE_ALG_CCMP:
1810 param_len = sizeof(struct ieee_param) + pext->key_len;
1811 param = kzalloc(param_len, GFP_ATOMIC);
1814 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1815 memset(param->sta_addr, 0xff, ETH_ALEN);
1817 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1818 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1819 param->u.crypt.set_tx = 0;
1820 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1821 param->u.crypt.set_tx = 1;
1822 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1823 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1824 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1825 if (pext->key_len) {
1826 param->u.crypt.key_len = pext->key_len;
1827 memcpy(param + 1, pext + 1, pext->key_len);
1829 ret = wpa_set_encryption(dev, param, param_len);
1834 static int r871x_wx_get_nick(struct net_device *dev,
1835 struct iw_request_info *info,
1836 union iwreq_data *wrqu, char *extra)
1839 wrqu->data.length = 8;
1840 wrqu->data.flags = 1;
1841 memcpy(extra, "rtl_wifi", 8);
1846 static int r8711_wx_read32(struct net_device *dev,
1847 struct iw_request_info *info,
1848 union iwreq_data *wrqu, char *keybuf)
1850 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1854 get_user(addr, (u32 __user *)wrqu->data.pointer);
1855 data32 = r8712_read32(padapter, addr);
1856 put_user(data32, (u32 __user *)wrqu->data.pointer);
1857 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1858 wrqu->data.flags = data32 & 0xffff;
1859 get_user(addr, (u32 __user *)wrqu->data.pointer);
1863 static int r8711_wx_write32(struct net_device *dev,
1864 struct iw_request_info *info,
1865 union iwreq_data *wrqu, char *keybuf)
1867 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1871 get_user(addr, (u32 __user *)wrqu->data.pointer);
1872 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
1873 r8712_write32(padapter, addr, data32);
1877 static int dummy(struct net_device *dev,
1878 struct iw_request_info *a,
1879 union iwreq_data *wrqu, char *b)
1884 static int r8711_drvext_hdl(struct net_device *dev,
1885 struct iw_request_info *info,
1886 union iwreq_data *wrqu, char *extra)
1891 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1892 struct iw_request_info *info,
1893 union iwreq_data *wrqu, char *extra)
1895 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1896 struct iw_point *p = &wrqu->data;
1897 struct oid_par_priv oid_par;
1898 struct mp_ioctl_handler *phandler;
1899 struct mp_ioctl_param *poidparam;
1900 unsigned long BytesRead, BytesWritten, BytesNeeded;
1901 u8 *pparmbuf = NULL, bset;
1906 if ((!p->length) || (!p->pointer)) {
1908 goto _r871x_mp_ioctl_hdl_exit;
1910 bset = (u8)(p->flags & 0xFFFF);
1913 pparmbuf = kmalloc(len, GFP_ATOMIC);
1914 if (pparmbuf == NULL) {
1916 goto _r871x_mp_ioctl_hdl_exit;
1918 if (copy_from_user(pparmbuf, p->pointer, len)) {
1920 goto _r871x_mp_ioctl_hdl_exit;
1922 poidparam = (struct mp_ioctl_param *)pparmbuf;
1923 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1925 goto _r871x_mp_ioctl_hdl_exit;
1927 phandler = mp_ioctl_hdl + poidparam->subcode;
1928 if ((phandler->paramsize != 0) &&
1929 (poidparam->len < phandler->paramsize)) {
1931 goto _r871x_mp_ioctl_hdl_exit;
1933 if (phandler->oid == 0 && phandler->handler)
1934 status = phandler->handler(&oid_par);
1935 else if (phandler->handler) {
1936 oid_par.adapter_context = padapter;
1937 oid_par.oid = phandler->oid;
1938 oid_par.information_buf = poidparam->data;
1939 oid_par.information_buf_len = poidparam->len;
1944 oid_par.bytes_rw = &BytesRead;
1945 oid_par.bytes_needed = &BytesNeeded;
1946 oid_par.type_of_oid = SET_OID;
1948 oid_par.bytes_rw = &BytesWritten;
1949 oid_par.bytes_needed = &BytesNeeded;
1950 oid_par.type_of_oid = QUERY_OID;
1952 status = phandler->handler(&oid_par);
1953 /* todo:check status, BytesNeeded, etc. */
1955 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1956 __func__, poidparam->subcode, phandler->oid,
1959 goto _r871x_mp_ioctl_hdl_exit;
1961 if (bset == 0x00) { /* query info */
1962 if (copy_to_user(p->pointer, pparmbuf, len))
1967 goto _r871x_mp_ioctl_hdl_exit;
1969 _r871x_mp_ioctl_hdl_exit:
1974 static int r871x_get_ap_info(struct net_device *dev,
1975 struct iw_request_info *info,
1976 union iwreq_data *wrqu, char *extra)
1978 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1979 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1980 struct __queue *queue = &pmlmepriv->scanned_queue;
1981 struct iw_point *pdata = &wrqu->data;
1982 struct wlan_network *pnetwork = NULL;
1983 u32 cnt = 0, wpa_ielen;
1985 struct list_head *plist, *phead;
1986 unsigned char *pbuf;
1990 if (padapter->bDriverStopped || (pdata == NULL))
1992 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1999 if (pdata->length >= 32) {
2000 if (copy_from_user(data, pdata->pointer, 32))
2004 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2005 phead = &queue->queue;
2006 plist = phead->next;
2008 if (end_of_queue_search(phead, plist) == true)
2010 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2011 if (hwaddr_aton_i(data, bssid)) {
2012 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
2014 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2018 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
2019 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2020 /* BSSID match, then check if supporting wpa/wpa2 */
2021 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2022 &wpa_ielen, pnetwork->network.IELength-12);
2023 if (pbuf && (wpa_ielen > 0)) {
2027 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2028 &wpa_ielen, pnetwork->network.IELength-12);
2029 if (pbuf && (wpa_ielen > 0)) {
2034 plist = plist->next;
2036 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2037 if (pdata->length >= 34) {
2038 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2039 (u8 *)&pdata->flags, 1))
2045 static int r871x_set_pid(struct net_device *dev,
2046 struct iw_request_info *info,
2047 union iwreq_data *wrqu, char *extra)
2049 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2050 struct iw_point *pdata = &wrqu->data;
2052 if ((padapter->bDriverStopped) || (pdata == NULL))
2054 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2059 static int r871x_set_chplan(struct net_device *dev,
2060 struct iw_request_info *info,
2061 union iwreq_data *wrqu, char *extra)
2064 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2065 struct iw_point *pdata = &wrqu->data;
2068 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2072 ch_plan = (int)*extra;
2073 r8712_set_chplan_cmd(padapter, ch_plan);
2080 static int r871x_wps_start(struct net_device *dev,
2081 struct iw_request_info *info,
2082 union iwreq_data *wrqu, char *extra)
2084 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2085 struct iw_point *pdata = &wrqu->data;
2086 u32 u32wps_start = 0;
2088 if ((padapter->bDriverStopped) || (pdata == NULL))
2090 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2092 if (u32wps_start == 0)
2093 u32wps_start = *extra;
2094 if (u32wps_start == 1) /* WPS Start */
2095 padapter->ledpriv.LedControlHandler(padapter,
2097 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2098 padapter->ledpriv.LedControlHandler(padapter,
2100 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2101 padapter->ledpriv.LedControlHandler(padapter,
2102 LED_CTL_STOP_WPS_FAIL);
2106 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2108 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2111 case IEEE_PARAM_WPA_ENABLED:
2112 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2113 switch ((value)&0xff) {
2115 padapter->securitypriv.ndisauthtype =
2116 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2117 padapter->securitypriv.ndisencryptstatus =
2118 Ndis802_11Encryption2Enabled;
2121 padapter->securitypriv.ndisauthtype =
2122 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2123 padapter->securitypriv.ndisencryptstatus =
2124 Ndis802_11Encryption3Enabled;
2128 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2130 case IEEE_PARAM_DROP_UNENCRYPTED:
2133 * wpa_supplicant calls set_wpa_enabled when the driver
2134 * is loaded and unloaded, regardless of if WPA is being
2135 * used. No other calls are made which can be used to
2136 * determine if encryption will be used or not prior to
2137 * association being expected. If encryption is not being
2138 * used, drop_unencrypted is set to false, else true -- we
2139 * can use this to determine if the CAP_PRIVACY_ON bit should
2143 case IEEE_PARAM_PRIVACY_INVOKED:
2145 case IEEE_PARAM_AUTH_ALGS:
2146 return wpa_set_auth_algs(dev, value);
2147 case IEEE_PARAM_IEEE_802_1X:
2149 case IEEE_PARAM_WPAX_SELECT:
2150 /* added for WPA2 mixed mode */
2158 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2160 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2163 case IEEE_MLME_STA_DEAUTH:
2164 if (!r8712_set_802_11_disassociate(padapter))
2167 case IEEE_MLME_STA_DISASSOC:
2168 if (!r8712_set_802_11_disassociate(padapter))
2177 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2179 struct ieee_param *param;
2181 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2183 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2185 param = memdup_user(p->pointer, p->length);
2187 return PTR_ERR(param);
2188 switch (param->cmd) {
2189 case IEEE_CMD_SET_WPA_PARAM:
2190 ret = wpa_set_param(dev, param->u.wpa_param.name,
2191 param->u.wpa_param.value);
2193 case IEEE_CMD_SET_WPA_IE:
2194 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2195 (u16)param->u.wpa_ie.len);
2197 case IEEE_CMD_SET_ENCRYPTION:
2198 ret = wpa_set_encryption(dev, param, p->length);
2201 ret = wpa_mlme(dev, param->u.mlme.command,
2202 param->u.mlme.reason_code);
2208 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2214 /* based on "driver_ipw" and for hostapd */
2215 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2217 struct iwreq *wrq = (struct iwreq *)rq;
2220 case RTL_IOCTL_WPA_SUPPLICANT:
2221 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2228 static iw_handler r8711_handlers[] = {
2229 NULL, /* SIOCSIWCOMMIT */
2230 r8711_wx_get_name, /* SIOCGIWNAME */
2231 dummy, /* SIOCSIWNWID */
2232 dummy, /* SIOCGIWNWID */
2233 r8711_wx_set_freq, /* SIOCSIWFREQ */
2234 r8711_wx_get_freq, /* SIOCGIWFREQ */
2235 r8711_wx_set_mode, /* SIOCSIWMODE */
2236 r8711_wx_get_mode, /* SIOCGIWMODE */
2237 dummy, /* SIOCSIWSENS */
2238 r8711_wx_get_sens, /* SIOCGIWSENS */
2239 NULL, /* SIOCSIWRANGE */
2240 r8711_wx_get_range, /* SIOCGIWRANGE */
2241 r871x_wx_set_priv, /* SIOCSIWPRIV */
2242 NULL, /* SIOCGIWPRIV */
2243 NULL, /* SIOCSIWSTATS */
2244 NULL, /* SIOCGIWSTATS */
2245 dummy, /* SIOCSIWSPY */
2246 dummy, /* SIOCGIWSPY */
2247 NULL, /* SIOCGIWTHRSPY */
2248 NULL, /* SIOCWIWTHRSPY */
2249 r8711_wx_set_wap, /* SIOCSIWAP */
2250 r8711_wx_get_wap, /* SIOCGIWAP */
2251 r871x_wx_set_mlme, /* request MLME operation;
2252 * uses struct iw_mlme */
2253 dummy, /* SIOCGIWAPLIST -- deprecated */
2254 r8711_wx_set_scan, /* SIOCSIWSCAN */
2255 r8711_wx_get_scan, /* SIOCGIWSCAN */
2256 r8711_wx_set_essid, /* SIOCSIWESSID */
2257 r8711_wx_get_essid, /* SIOCGIWESSID */
2258 dummy, /* SIOCSIWNICKN */
2259 r871x_wx_get_nick, /* SIOCGIWNICKN */
2260 NULL, /* -- hole -- */
2261 NULL, /* -- hole -- */
2262 r8711_wx_set_rate, /* SIOCSIWRATE */
2263 r8711_wx_get_rate, /* SIOCGIWRATE */
2264 dummy, /* SIOCSIWRTS */
2265 r8711_wx_get_rts, /* SIOCGIWRTS */
2266 r8711_wx_set_frag, /* SIOCSIWFRAG */
2267 r8711_wx_get_frag, /* SIOCGIWFRAG */
2268 dummy, /* SIOCSIWTXPOW */
2269 dummy, /* SIOCGIWTXPOW */
2270 dummy, /* SIOCSIWRETRY */
2271 r8711_wx_get_retry, /* SIOCGIWRETRY */
2272 r8711_wx_set_enc, /* SIOCSIWENCODE */
2273 r8711_wx_get_enc, /* SIOCGIWENCODE */
2274 dummy, /* SIOCSIWPOWER */
2275 r8711_wx_get_power, /* SIOCGIWPOWER */
2276 NULL, /*---hole---*/
2277 NULL, /*---hole---*/
2278 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2279 NULL, /* SIOCGIWGENIE */
2280 r871x_wx_set_auth, /* SIOCSIWAUTH */
2281 NULL, /* SIOCGIWAUTH */
2282 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2283 NULL, /* SIOCGIWENCODEEXT */
2284 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2285 NULL, /*---hole---*/
2288 static const struct iw_priv_args r8711_private_args[] = {
2290 SIOCIWFIRSTPRIV + 0x0,
2291 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2294 SIOCIWFIRSTPRIV + 0x1,
2295 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2298 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2301 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2304 SIOCIWFIRSTPRIV + 0x4,
2305 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2308 SIOCIWFIRSTPRIV + 0x5,
2309 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2312 SIOCIWFIRSTPRIV + 0x6,
2313 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2316 SIOCIWFIRSTPRIV + 0x7,
2317 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2321 static iw_handler r8711_private_handler[] = {
2326 r871x_get_ap_info, /*for MM DTV platform*/
2332 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2334 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2335 struct iw_statistics *piwstats = &padapter->iwstats;
2340 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2341 piwstats->qual.qual = 0;
2342 piwstats->qual.level = 0;
2343 piwstats->qual.noise = 0;
2345 /* show percentage, we need transfer dbm to orignal value. */
2346 tmp_level = padapter->recvpriv.fw_rssi;
2347 tmp_qual = padapter->recvpriv.signal;
2348 tmp_noise = padapter->recvpriv.noise;
2349 piwstats->qual.level = tmp_level;
2350 piwstats->qual.qual = tmp_qual;
2351 piwstats->qual.noise = tmp_noise;
2353 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2354 return &padapter->iwstats;
2357 struct iw_handler_def r871x_handlers_def = {
2358 .standard = r8711_handlers,
2359 .num_standard = ARRAY_SIZE(r8711_handlers),
2360 .private = r8711_private_handler,
2361 .private_args = (struct iw_priv_args *)r8711_private_args,
2362 .num_private = ARRAY_SIZE(r8711_private_handler),
2363 .num_private_args = sizeof(r8711_private_args) /
2364 sizeof(struct iw_priv_args),
2365 .get_wireless_stats = r871x_get_wireless_stats