1 /******************************************************************************
2 * rtl871x_ioctl_linux.c
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.h"
37 #include "rtl871x_mlme.h"
38 #include "rtl871x_ioctl.h"
39 #include "rtl871x_ioctl_set.h"
40 #include "rtl871x_mp_ioctl.h"
41 #include "mlme_osdep.h"
42 #include <linux/wireless.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/init.h>
46 #include <linux/version.h>
48 #include <linux/semaphore.h>
49 #include <net/iw_handler.h>
50 #include <linux/if_arp.h>
52 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
54 #define SCAN_ITEM_SIZE 768
55 #define MAX_CUSTOM_LEN 64
59 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
60 6000000, 9000000, 12000000, 18000000,
61 24000000, 36000000, 48000000, 54000000};
63 static const long ieee80211_wlan_frequencies[] = {
64 2412, 2417, 2422, 2427,
65 2432, 2437, 2442, 2447,
66 2452, 2457, 2462, 2467,
70 static const char * const iw_operation_mode[] = {
71 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
76 * hwaddr_aton - Convert ASCII string to MAC address
77 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
78 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
79 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
81 static int hwaddr_aton_i(const char *txt, u8 *addr)
85 for (i = 0; i < 6; i++) {
88 a = hex_to_bin(*txt++);
91 b = hex_to_bin(*txt++);
94 *addr++ = (a << 4) | b;
95 if (i < 5 && *txt++ != ':')
101 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
103 union iwreq_data wrqu;
104 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
106 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
107 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
109 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
112 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
114 union iwreq_data wrqu;
116 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
117 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
118 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
121 static inline void handle_pairwise_key(struct sta_info *psta,
122 struct ieee_param *param,
123 struct _adapter *padapter)
126 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
127 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
128 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
129 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
131 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
133 padapter->securitypriv. busetkipkey = false;
134 _set_timer(&padapter->securitypriv.tkip_timer, 50);
136 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
139 static inline void handle_group_key(struct ieee_param *param,
140 struct _adapter *padapter)
142 if (0 < param->u.crypt.idx &&
143 param->u.crypt.idx < 3) {
144 /* group key idx is 1 or 2 */
145 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
146 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
147 > 16 ? 16 : param->u.crypt.key_len));
148 memcpy(padapter->securitypriv.XGrptxmickey[param->
149 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
150 memcpy(padapter->securitypriv. XGrprxmickey[param->
151 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
152 padapter->securitypriv.binstallGrpkey = true;
153 r8712_set_key(padapter, &padapter->securitypriv,
155 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
156 if (padapter->registrypriv.power_mgnt != padapter->
157 pwrctrlpriv.pwr_mode)
158 _set_timer(&(padapter->mlmepriv.dhcp_timer),
164 static inline char *translate_scan(struct _adapter *padapter,
165 struct iw_request_info *info,
166 struct wlan_network *pnetwork,
167 char *start, char *stop)
170 struct ieee80211_ht_cap *pht_capie;
173 u32 i = 0, ht_ielen = 0;
174 u16 cap, ht_cap = false, mcs_rate;
175 u8 rssi, bw_40MHz = 0, short_GI = 0;
177 if ((pnetwork->network.Configuration.DSConfig < 1) ||
178 (pnetwork->network.Configuration.DSConfig > 14)) {
179 if (pnetwork->network.Configuration.DSConfig < 1)
180 pnetwork->network.Configuration.DSConfig = 1;
182 pnetwork->network.Configuration.DSConfig = 14;
186 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
187 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
188 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
190 iwe.cmd = SIOCGIWESSID;
191 iwe.u.data.flags = 1;
192 iwe.u.data.length = (u16)min((u16)pnetwork->network.Ssid.SsidLength,
194 start = iwe_stream_add_point(info, start, stop, &iwe,
195 pnetwork->network.Ssid.Ssid);
196 /* parsing HT_CAP_IE */
197 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
198 &ht_ielen, pnetwork->network.IELength - 12);
199 if (p && ht_ielen > 0) {
201 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
202 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
203 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
205 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
206 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
208 /* Add the protocol name */
209 iwe.cmd = SIOCGIWNAME;
210 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
211 SupportedRates)) == true) {
213 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
215 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
216 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
217 SupportedRates)) == true) {
219 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
221 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
224 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
226 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
228 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
230 iwe.cmd = SIOCGIWMODE;
231 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
233 cap = le16_to_cpu(cap);
234 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
235 if (cap & WLAN_CAPABILITY_BSS)
236 iwe.u.mode = (u32)IW_MODE_MASTER;
238 iwe.u.mode = (u32)IW_MODE_ADHOC;
239 start = iwe_stream_add_event(info, start, stop, &iwe,
242 /* Add frequency/channel */
243 iwe.cmd = SIOCGIWFREQ;
245 /* check legel index */
246 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
247 if (dsconfig >= 1 && dsconfig <= sizeof(
248 ieee80211_wlan_frequencies) / sizeof(long))
249 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
250 pnetwork->network.Configuration.
251 DSConfig - 1] * 100000);
255 iwe.u.freq.e = (s16)1;
256 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
257 start = iwe_stream_add_event(info, start, stop, &iwe,
259 /* Add encryption capability */
260 iwe.cmd = SIOCGIWENCODE;
261 if (cap & WLAN_CAPABILITY_PRIVACY)
262 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
265 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
266 iwe.u.data.length = (u16)0;
267 start = iwe_stream_add_point(info, start, stop, &iwe,
268 pnetwork->network.Ssid.Ssid);
269 /*Add basic and extended rates */
270 current_val = start + iwe_stream_lcp_len(info);
271 iwe.cmd = SIOCGIWRATE;
272 iwe.u.bitrate.fixed = 0;
273 iwe.u.bitrate.disabled = 0;
274 iwe.u.bitrate.value = 0;
276 while (pnetwork->network.SupportedRates[i] != 0) {
277 /* Bit rate given in 500 kb/s units */
278 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
280 current_val = iwe_stream_add_value(info, start, current_val,
281 stop, &iwe, IW_EV_PARAM_LEN);
283 /* Check if we added any event */
284 if ((current_val - start) > iwe_stream_lcp_len(info))
286 /* parsing WPA/WPA2 IE */
288 u8 buf[MAX_WPA_IE_LEN];
289 u8 wpa_ie[255], rsn_ie[255];
290 u16 wpa_len = 0, rsn_len = 0;
293 out_len = r8712_get_sec_ie(pnetwork->network.IEs,
295 IELength, rsn_ie, &rsn_len,
298 memset(buf, 0, MAX_WPA_IE_LEN);
299 n = sprintf(buf, "wpa_ie=");
300 for (i = 0; i < wpa_len; i++) {
301 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
303 if (n >= MAX_WPA_IE_LEN)
306 memset(&iwe, 0, sizeof(iwe));
307 iwe.cmd = IWEVCUSTOM;
308 iwe.u.data.length = (u16)strlen(buf);
309 start = iwe_stream_add_point(info, start, stop,
311 memset(&iwe, 0, sizeof(iwe));
313 iwe.u.data.length = (u16)wpa_len;
314 start = iwe_stream_add_point(info, start, stop,
318 memset(buf, 0, MAX_WPA_IE_LEN);
319 n = sprintf(buf, "rsn_ie=");
320 for (i = 0; i < rsn_len; i++) {
321 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
323 if (n >= MAX_WPA_IE_LEN)
326 memset(&iwe, 0, sizeof(iwe));
327 iwe.cmd = IWEVCUSTOM;
328 iwe.u.data.length = strlen(buf);
329 start = iwe_stream_add_point(info, start, stop,
331 memset(&iwe, 0, sizeof(iwe));
333 iwe.u.data.length = rsn_len;
334 start = iwe_stream_add_point(info, start, stop, &iwe,
339 { /* parsing WPS IE */
343 if (r8712_get_wps_ie(pnetwork->network.IEs,
344 pnetwork->network.IELength,
345 wps_ie, &wps_ielen) == true) {
348 iwe.u.data.length = (u16)wps_ielen;
349 start = iwe_stream_add_point(info, start, stop,
354 /* Add quality statistics */
356 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
357 /* we only update signal_level (signal strength) that is rssi. */
358 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
359 IW_QUAL_NOISE_INVALID);
360 iwe.u.qual.level = rssi; /* signal strength */
361 iwe.u.qual.qual = 0; /* signal quality */
362 iwe.u.qual.noise = 0; /* noise level */
363 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
364 /* how to translate rssi to ?% */
368 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
370 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
373 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
374 padapter->securitypriv.ndisencryptstatus =
375 Ndis802_11Encryption1Enabled;
376 padapter->securitypriv.ndisauthtype =
377 Ndis802_11AuthModeAutoSwitch;
378 padapter->securitypriv.AuthAlgrthm = 3;
379 } else if (value & AUTH_ALG_SHARED_KEY) {
380 padapter->securitypriv.ndisencryptstatus =
381 Ndis802_11Encryption1Enabled;
382 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
383 padapter->securitypriv.AuthAlgrthm = 1;
384 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
385 if (padapter->securitypriv.ndisauthtype <
386 Ndis802_11AuthModeWPAPSK) {
387 padapter->securitypriv.ndisauthtype =
388 Ndis802_11AuthModeOpen;
389 padapter->securitypriv.AuthAlgrthm = 0;
396 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
400 u32 wep_key_idx, wep_key_len = 0;
401 struct NDIS_802_11_WEP *pwep = NULL;
402 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
403 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
404 struct security_priv *psecuritypriv = &padapter->securitypriv;
406 param->u.crypt.err = 0;
407 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
408 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
409 param->u.crypt.key_len)
411 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
412 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
413 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
414 if (param->u.crypt.idx >= WEP_KEYS) {
415 /* for large key indices, set the default (0) */
416 param->u.crypt.idx = 0;
420 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
421 printk(KERN_INFO "r8712u: wpa_set_encryption, crypt.alg ="
423 padapter->securitypriv.ndisencryptstatus =
424 Ndis802_11Encryption1Enabled;
425 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
426 padapter->securitypriv.XGrpPrivacy = _WEP40_;
427 wep_key_idx = param->u.crypt.idx;
428 wep_key_len = param->u.crypt.key_len;
429 if (wep_key_idx >= WEP_KEYS)
431 if (wep_key_len > 0) {
432 wep_key_len = wep_key_len <= 5 ? 5 : 13;
433 pwep = (struct NDIS_802_11_WEP *)_malloc((u32)
435 FIELD_OFFSET(struct NDIS_802_11_WEP,
439 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
440 pwep->KeyLength = wep_key_len;
441 pwep->Length = wep_key_len +
442 FIELD_OFFSET(struct NDIS_802_11_WEP,
444 if (wep_key_len == 13) {
445 padapter->securitypriv.PrivacyAlgrthm =
447 padapter->securitypriv.XGrpPrivacy =
452 pwep->KeyIndex = wep_key_idx;
453 pwep->KeyIndex |= 0x80000000;
454 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
455 if (param->u.crypt.set_tx) {
456 if (r8712_set_802_11_add_wep(padapter, pwep) ==
460 /* don't update "psecuritypriv->PrivacyAlgrthm" and
461 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
462 * r8712_set_key to fw/cam
464 if (wep_key_idx >= WEP_KEYS) {
468 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
469 skey[0]), pwep->KeyMaterial,
471 psecuritypriv->DefKeylen[wep_key_idx] =
473 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
477 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
478 struct sta_info *psta, *pbcmc_sta;
479 struct sta_priv *pstapriv = &padapter->stapriv;
481 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
482 WIFI_MP_STATE) == true) { /* sta mode */
483 psta = r8712_get_stainfo(pstapriv,
484 get_bssid(pmlmepriv));
486 psta->ieee8021x_blocked = false;
487 if ((padapter->securitypriv.ndisencryptstatus ==
488 Ndis802_11Encryption2Enabled) ||
489 (padapter->securitypriv.ndisencryptstatus ==
490 Ndis802_11Encryption3Enabled))
491 psta->XPrivacy = padapter->
492 securitypriv.PrivacyAlgrthm;
493 if (param->u.crypt.set_tx == 1)
494 handle_pairwise_key(psta, param,
497 handle_group_key(param, padapter);
499 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
501 pbcmc_sta->ieee8021x_blocked = false;
502 if ((padapter->securitypriv.ndisencryptstatus ==
503 Ndis802_11Encryption2Enabled) ||
504 (padapter->securitypriv.ndisencryptstatus ==
505 Ndis802_11Encryption3Enabled))
506 pbcmc_sta->XPrivacy =
507 padapter->securitypriv.
517 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
518 unsigned short ielen)
520 u8 *buf = NULL, *pos = NULL;
521 int group_cipher = 0, pairwise_cipher = 0;
524 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
527 buf = _malloc(ielen);
530 memcpy(buf, pie , ielen);
532 if (ielen < RSN_HEADER_LEN) {
536 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
537 &pairwise_cipher) == _SUCCESS) {
538 padapter->securitypriv.AuthAlgrthm = 2;
539 padapter->securitypriv.ndisauthtype =
540 Ndis802_11AuthModeWPAPSK;
542 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
543 &pairwise_cipher) == _SUCCESS) {
544 padapter->securitypriv.AuthAlgrthm = 2;
545 padapter->securitypriv.ndisauthtype =
546 Ndis802_11AuthModeWPA2PSK;
548 switch (group_cipher) {
549 case WPA_CIPHER_NONE:
550 padapter->securitypriv.XGrpPrivacy =
552 padapter->securitypriv.ndisencryptstatus =
553 Ndis802_11EncryptionDisabled;
555 case WPA_CIPHER_WEP40:
556 padapter->securitypriv.XGrpPrivacy = _WEP40_;
557 padapter->securitypriv.ndisencryptstatus =
558 Ndis802_11Encryption1Enabled;
560 case WPA_CIPHER_TKIP:
561 padapter->securitypriv.XGrpPrivacy = _TKIP_;
562 padapter->securitypriv.ndisencryptstatus =
563 Ndis802_11Encryption2Enabled;
565 case WPA_CIPHER_CCMP:
566 padapter->securitypriv.XGrpPrivacy = _AES_;
567 padapter->securitypriv.ndisencryptstatus =
568 Ndis802_11Encryption3Enabled;
570 case WPA_CIPHER_WEP104:
571 padapter->securitypriv.XGrpPrivacy = _WEP104_;
572 padapter->securitypriv.ndisencryptstatus =
573 Ndis802_11Encryption1Enabled;
576 switch (pairwise_cipher) {
577 case WPA_CIPHER_NONE:
578 padapter->securitypriv.PrivacyAlgrthm =
580 padapter->securitypriv.ndisencryptstatus =
581 Ndis802_11EncryptionDisabled;
583 case WPA_CIPHER_WEP40:
584 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
585 padapter->securitypriv.ndisencryptstatus =
586 Ndis802_11Encryption1Enabled;
588 case WPA_CIPHER_TKIP:
589 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
590 padapter->securitypriv.ndisencryptstatus =
591 Ndis802_11Encryption2Enabled;
593 case WPA_CIPHER_CCMP:
594 padapter->securitypriv.PrivacyAlgrthm = _AES_;
595 padapter->securitypriv.ndisencryptstatus =
596 Ndis802_11Encryption3Enabled;
598 case WPA_CIPHER_WEP104:
599 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
600 padapter->securitypriv.ndisencryptstatus =
601 Ndis802_11Encryption1Enabled;
604 padapter->securitypriv.wps_phase = false;
607 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
609 while (cnt < ielen) {
612 if ((eid == _VENDOR_SPECIFIC_IE_) &&
613 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
614 printk(KERN_INFO "r8712u: "
616 padapter->securitypriv.wps_ie_len =
618 (MAX_WPA_IE_LEN << 2)) ?
620 (MAX_WPA_IE_LEN << 2);
621 memcpy(padapter->securitypriv.wps_ie,
623 padapter->securitypriv.wps_ie_len);
624 padapter->securitypriv.wps_phase =
626 printk(KERN_INFO "r8712u: SET WPS_IE,"
627 " wps_phase==true\n");
631 cnt += buf[cnt + 1] + 2;
640 static int r8711_wx_get_name(struct net_device *dev,
641 struct iw_request_info *info,
642 union iwreq_data *wrqu, char *extra)
644 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
648 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
649 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
650 NDIS_802_11_RATES_EX *prates = NULL;
652 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
654 /* parsing HT_CAP_IE */
655 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
656 &ht_ielen, pcur_bss->IELength - 12);
657 if (p && ht_ielen > 0)
659 prates = &pcur_bss->SupportedRates;
660 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
662 snprintf(wrqu->name, IFNAMSIZ,
665 snprintf(wrqu->name, IFNAMSIZ,
667 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
669 snprintf(wrqu->name, IFNAMSIZ,
672 snprintf(wrqu->name, IFNAMSIZ,
676 snprintf(wrqu->name, IFNAMSIZ,
679 snprintf(wrqu->name, IFNAMSIZ,
683 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
687 static const long frequency_list[] = {
688 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
689 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
690 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
691 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
692 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
696 static int r8711_wx_set_freq(struct net_device *dev,
697 struct iw_request_info *info,
698 union iwreq_data *wrqu, char *extra)
700 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
701 struct iw_freq *fwrq = &wrqu->freq;
704 /* If setting by frequency, convert to a channel */
705 if ((fwrq->e == 1) &&
706 (fwrq->m >= (int) 2.412e8) &&
707 (fwrq->m <= (int) 2.487e8)) {
708 int f = fwrq->m / 100000;
710 while ((c < 14) && (f != frequency_list[c]))
715 /* Setting by channel number */
716 if ((fwrq->m > 14) || (fwrq->e > 0))
719 int channel = fwrq->m;
720 if ((channel < 1) || (channel > 14))
723 /* Yes ! We can set it !!! */
724 padapter->registrypriv.channel = channel;
730 static int r8711_wx_get_freq(struct net_device *dev,
731 struct iw_request_info *info,
732 union iwreq_data *wrqu, char *extra)
734 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
735 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
736 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
738 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
739 wrqu->freq.m = ieee80211_wlan_frequencies[
740 pcur_bss->Configuration.DSConfig-1] * 100000;
742 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
748 static int r8711_wx_set_mode(struct net_device *dev,
749 struct iw_request_info *a,
750 union iwreq_data *wrqu, char *b)
752 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
753 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
755 switch (wrqu->mode) {
757 networkType = Ndis802_11AutoUnknown;
760 networkType = Ndis802_11IBSS;
763 networkType = Ndis802_11APMode;
766 networkType = Ndis802_11Infrastructure;
771 if (Ndis802_11APMode == networkType)
772 r8712_setopmode_cmd(padapter, networkType);
774 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
775 if (!r8712_set_802_11_infrastructure_mode(padapter, networkType))
780 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
781 union iwreq_data *wrqu, char *b)
783 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
784 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
786 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
787 wrqu->mode = IW_MODE_INFRA;
788 else if (check_fwstate(pmlmepriv,
789 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
790 wrqu->mode = IW_MODE_ADHOC;
791 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
792 wrqu->mode = IW_MODE_MASTER;
794 wrqu->mode = IW_MODE_AUTO;
798 static int r871x_wx_set_pmkid(struct net_device *dev,
799 struct iw_request_info *a,
800 union iwreq_data *wrqu, char *extra)
802 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
803 struct security_priv *psecuritypriv = &padapter->securitypriv;
804 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
805 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
806 u8 strIssueBssid[ETH_ALEN] = {0x00};
807 u8 j, blInserted = false;
808 int intReturn = false;
811 There are the BSSID information in the bssid.sa_data array.
812 If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear
813 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
814 wpa_supplicant wants to add a PMKID/BSSID to driver.
815 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
816 remove a PMKID/BSSID from driver.
820 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
823 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
828 /* overwrite PMKID */
829 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
830 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
831 strIssueBssid, ETH_ALEN)) {
832 /* BSSID is matched, the same AP => rewrite
834 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid:"
835 " BSSID exists in the PMKList.\n");
836 memcpy(psecuritypriv->PMKIDList[j].PMKID,
837 pPMK->pmkid, IW_PMKID_LEN);
838 psecuritypriv->PMKIDList[j].bUsed = true;
839 psecuritypriv->PMKIDIndex = j + 1;
845 /* Find a new entry */
846 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: Use the"
847 " new entry index = %d for this PMKID.\n",
848 psecuritypriv->PMKIDIndex);
849 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
850 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
851 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
852 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
853 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
855 psecuritypriv->PMKIDIndex++ ;
856 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
857 psecuritypriv->PMKIDIndex = 0;
860 case IW_PMKSA_REMOVE:
862 for (j = 0; j < NUM_PMKID_CACHE; j++) {
863 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
864 strIssueBssid, ETH_ALEN)) {
865 /* BSSID is matched, the same AP => Remove
866 * this PMKID information and reset it. */
867 memset(psecuritypriv->PMKIDList[j].Bssid,
869 psecuritypriv->PMKIDList[j].bUsed = false;
875 memset(psecuritypriv->PMKIDList, 0,
876 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
877 psecuritypriv->PMKIDIndex = 0;
881 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: "
882 "unknown Command\n");
889 static int r8711_wx_get_sens(struct net_device *dev,
890 struct iw_request_info *info,
891 union iwreq_data *wrqu, char *extra)
893 wrqu->sens.value = 0;
894 wrqu->sens.fixed = 0; /* no auto select */
895 wrqu->sens.disabled = 1;
899 static int r8711_wx_get_range(struct net_device *dev,
900 struct iw_request_info *info,
901 union iwreq_data *wrqu, char *extra)
903 struct iw_range *range = (struct iw_range *)extra;
907 wrqu->data.length = sizeof(*range);
908 memset(range, 0, sizeof(*range));
909 /* Let's try to keep this struct in the same order as in
910 * linux/include/wireless.h
913 /* TODO: See what values we can set, and remove the ones we can't
914 * set, or fill them with some default data.
916 /* ~5 Mb/s real (802.11b) */
917 range->throughput = 5 * 1000 * 1000;
918 /* TODO: 8711 sensitivity ? */
919 /* signal level threshold range */
920 /* percent values between 0 and 100. */
921 range->max_qual.qual = 100;
922 range->max_qual.level = 100;
923 range->max_qual.noise = 100;
924 range->max_qual.updated = 7; /* Updated all three */
925 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
926 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
927 range->avg_qual.level = 20 + -98;
928 range->avg_qual.noise = 0;
929 range->avg_qual.updated = 7; /* Updated all three */
930 range->num_bitrates = RATE_COUNT;
931 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
932 range->bitrate[i] = rtl8180_rates[i];
933 range->min_frag = MIN_FRAG_THRESHOLD;
934 range->max_frag = MAX_FRAG_THRESHOLD;
936 range->we_version_compiled = WIRELESS_EXT;
937 range->we_version_source = 16;
938 range->num_channels = 14;
939 for (i = 0, val = 0; i < 14; i++) {
940 /* Include only legal frequencies for some countries */
941 range->freq[val].i = i + 1;
942 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
943 range->freq[val].e = 1;
945 if (val == IW_MAX_FREQUENCIES)
948 range->num_frequency = val;
949 range->enc_capa = IW_ENC_CAPA_WPA |
951 IW_ENC_CAPA_CIPHER_TKIP |
952 IW_ENC_CAPA_CIPHER_CCMP;
956 static int r8711_wx_get_rate(struct net_device *dev,
957 struct iw_request_info *info,
958 union iwreq_data *wrqu, char *extra);
960 static int r871x_wx_set_priv(struct net_device *dev,
961 struct iw_request_info *info,
962 union iwreq_data *awrq,
965 int ret = 0, len = 0;
967 struct _adapter *padapter = netdev_priv(dev);
968 struct iw_point *dwrq = (struct iw_point *)awrq;
974 if (copy_from_user(ext, dwrq->pointer, len)) {
979 if (0 == strcasecmp(ext, "RSSI")) {
980 /*Return received signal strength indicator in -db for */
983 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
984 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
986 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
987 sprintf(ext, "%s rssi %d",
988 pcur_network->network.Ssid.Ssid,
990 ((padapter->recvpriv.fw_rssi)>>1)-95
991 /*pcur_network->network.Rssi */
996 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
997 /*Return link speed in MBPS */
999 union iwreq_data wrqd;
1003 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
1007 mbps = wrqd.bitrate.value / 1000000;
1008 sprintf(ext, "LINKSPEED %d", mbps);
1009 } else if (0 == strcasecmp(ext, "MACADDR")) {
1010 /*Return mac address of the station */
1011 /*Macaddr = xx.xx.xx.xx.xx.xx */
1013 "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
1014 *(dev->dev_addr), *(dev->dev_addr+1),
1015 *(dev->dev_addr+2), *(dev->dev_addr+3),
1016 *(dev->dev_addr+4), *(dev->dev_addr+5));
1017 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
1018 /*Set scan type to active */
1019 /*OK if successful */
1020 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1021 pmlmepriv->passive_mode = 1;
1023 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1024 /*Set scan type to passive */
1025 /*OK if successful */
1026 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1027 pmlmepriv->passive_mode = 0;
1029 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1030 /*Set scan type to passive */
1031 /*OK if successful */
1032 r8712_disconnectCtrlEx_cmd(padapter
1033 , 1 /*u32 enableDrvCtrl */
1034 , 5 /*u32 tryPktCnt */
1035 , 100 /*u32 tryPktInterval */
1036 , 5000 /*u32 firstStageTO */
1039 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1040 /*Set scan type to passive */
1041 /*OK if successfu */
1042 r8712_disconnectCtrlEx_cmd(padapter
1043 , 0 /*u32 enableDrvCtrl */
1044 , 5 /*u32 tryPktCnt */
1045 , 100 /*u32 tryPktInterval */
1046 , 5000 /*u32 firstStageTO */
1050 printk(KERN_INFO "r8712u: r871x_wx_set_priv: unknown Command"
1054 if (copy_to_user(dwrq->pointer, ext,
1055 min(dwrq->length, (__u16)(strlen(ext)+1))))
1064 * s1. set_802_11_infrastructure_mode()
1065 * s2. set_802_11_authentication_mode()
1066 * s3. set_802_11_encryption_mode()
1067 * s4. set_802_11_bssid()
1069 * This function intends to handle the Set AP command, which specifies the
1070 * MAC# of a preferred Access Point.
1071 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1073 * For this operation to succeed, there is no need for the interface to be Up.
1076 static int r8711_wx_set_wap(struct net_device *dev,
1077 struct iw_request_info *info,
1078 union iwreq_data *awrq,
1081 int ret = -EINPROGRESS;
1082 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1083 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1084 struct __queue *queue = &pmlmepriv->scanned_queue;
1085 struct sockaddr *temp = (struct sockaddr *)awrq;
1087 struct list_head *phead;
1089 struct wlan_network *pnetwork = NULL;
1090 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1092 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1094 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1096 if (temp->sa_family != ARPHRD_ETHER)
1098 authmode = padapter->securitypriv.ndisauthtype;
1099 spin_lock_irqsave(&queue->lock, irqL);
1100 phead = get_list_head(queue);
1101 pmlmepriv->pscanned = get_next(phead);
1103 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1105 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1106 struct wlan_network, list);
1107 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1108 dst_bssid = pnetwork->network.MacAddress;
1109 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1110 if (r8712_set_802_11_infrastructure_mode(padapter,
1111 pnetwork->network.InfrastructureMode) == false)
1116 spin_unlock_irqrestore(&queue->lock, irqL);
1118 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1121 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1128 static int r8711_wx_get_wap(struct net_device *dev,
1129 struct iw_request_info *info,
1130 union iwreq_data *wrqu, char *extra)
1132 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1133 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1134 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1136 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1137 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1138 if (check_fwstate(pmlmepriv, _FW_LINKED |
1139 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
1140 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1145 static int r871x_wx_set_mlme(struct net_device *dev,
1146 struct iw_request_info *info,
1147 union iwreq_data *wrqu, char *extra)
1151 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1152 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1156 reason = cpu_to_le16(mlme->reason_code);
1157 switch (mlme->cmd) {
1158 case IW_MLME_DEAUTH:
1159 if (!r8712_set_802_11_disassociate(padapter))
1162 case IW_MLME_DISASSOC:
1163 if (!r8712_set_802_11_disassociate(padapter))
1174 * This function intends to handle the Set Scan command.
1175 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1177 * For this operation to succeed, the interface is brought Up beforehand.
1180 static int r8711_wx_set_scan(struct net_device *dev,
1181 struct iw_request_info *a,
1182 union iwreq_data *wrqu, char *extra)
1184 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1185 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1188 if (padapter->bDriverStopped == true) {
1189 printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
1190 "bDriverStopped=%d\n", padapter->bDriverStopped);
1193 if (padapter->bup == false)
1195 if (padapter->hw_init_completed == false)
1197 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1198 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1200 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1201 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1202 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1203 struct ndis_802_11_ssid ssid;
1205 u32 len = (u32) min((u8)req->essid_len,
1206 (u8)IW_ESSID_MAX_SIZE);
1207 memset((unsigned char *)&ssid, 0,
1208 sizeof(struct ndis_802_11_ssid));
1209 memcpy(ssid.Ssid, req->essid, len);
1210 ssid.SsidLength = len;
1211 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1212 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1213 _FW_UNDER_LINKING)) ||
1214 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1215 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1218 status = r8712_sitesurvey_cmd(padapter, &ssid);
1219 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1222 status = r8712_set_802_11_bssid_list_scan(padapter);
1223 if (status == false)
1228 static int r8711_wx_get_scan(struct net_device *dev,
1229 struct iw_request_info *a,
1230 union iwreq_data *wrqu, char *extra)
1232 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1233 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1234 struct __queue *queue = &pmlmepriv->scanned_queue;
1235 struct wlan_network *pnetwork = NULL;
1237 struct list_head *plist, *phead;
1239 char *stop = ev + wrqu->data.length;
1240 u32 ret = 0, cnt = 0;
1242 if (padapter->bDriverStopped)
1244 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1250 spin_lock_irqsave(&queue->lock, irqL);
1251 phead = get_list_head(queue);
1252 plist = get_next(phead);
1254 if (end_of_queue_search(phead, plist) == true)
1256 if ((stop - ev) < SCAN_ITEM_SIZE) {
1260 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1261 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1262 plist = get_next(plist);
1264 spin_unlock_irqrestore(&queue->lock, irqL);
1265 wrqu->data.length = ev - extra;
1266 wrqu->data.flags = 0;
1271 * s1. set_802_11_infrastructure_mode()
1272 * s2. set_802_11_authenticaion_mode()
1273 * s3. set_802_11_encryption_mode()
1274 * s4. set_802_11_ssid()
1276 * This function intends to handle the Set ESSID command.
1277 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1279 * For this operation to succeed, there is no need for the interface to be Up.
1282 static int r8711_wx_set_essid(struct net_device *dev,
1283 struct iw_request_info *a,
1284 union iwreq_data *wrqu, char *extra)
1286 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1287 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1288 struct __queue *queue = &pmlmepriv->scanned_queue;
1289 struct wlan_network *pnetwork = NULL;
1290 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1291 struct ndis_802_11_ssid ndis_ssid;
1292 u8 *dst_ssid, *src_ssid;
1293 struct list_head *phead;
1296 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1298 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1300 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1302 authmode = padapter->securitypriv.ndisauthtype;
1303 if (wrqu->essid.flags && wrqu->essid.length) {
1304 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1305 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1306 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1307 ndis_ssid.SsidLength = len;
1308 memcpy(ndis_ssid.Ssid, extra, len);
1309 src_ssid = ndis_ssid.Ssid;
1310 phead = get_list_head(queue);
1311 pmlmepriv->pscanned = get_next(phead);
1313 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1315 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1316 struct wlan_network, list);
1317 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1318 dst_ssid = pnetwork->network.Ssid.Ssid;
1319 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1320 && (pnetwork->network.Ssid.SsidLength ==
1321 ndis_ssid.SsidLength)) {
1322 if (check_fwstate(pmlmepriv,
1323 WIFI_ADHOC_STATE)) {
1324 if (pnetwork->network.
1328 cur_network.network.
1333 if (!r8712_set_802_11_infrastructure_mode(
1335 pnetwork->network.InfrastructureMode))
1340 r8712_set_802_11_authentication_mode(padapter, authmode);
1341 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1343 return -EINPROGRESS;
1346 static int r8711_wx_get_essid(struct net_device *dev,
1347 struct iw_request_info *a,
1348 union iwreq_data *wrqu, char *extra)
1350 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1351 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1352 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1355 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1356 len = pcur_bss->Ssid.SsidLength;
1357 wrqu->essid.length = len;
1358 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1359 wrqu->essid.flags = 1;
1365 static int r8711_wx_set_rate(struct net_device *dev,
1366 struct iw_request_info *a,
1367 union iwreq_data *wrqu, char *extra)
1369 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1370 u32 target_rate = wrqu->bitrate.value;
1371 u32 fixed = wrqu->bitrate.fixed;
1373 u8 datarates[NumRates];
1374 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1377 if (target_rate == -1) {
1381 target_rate = target_rate / 100000;
1382 switch (target_rate) {
1424 for (i = 0; i < NumRates; i++) {
1425 if (ratevalue == mpdatarate[i]) {
1426 datarates[i] = mpdatarate[i];
1430 datarates[i] = 0xff;
1432 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1437 static int r8711_wx_get_rate(struct net_device *dev,
1438 struct iw_request_info *info,
1439 union iwreq_data *wrqu, char *extra)
1441 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1442 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1443 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1444 struct ieee80211_ht_cap *pht_capie;
1445 unsigned char rf_type = padapter->registrypriv.rf_config;
1448 u16 rate, max_rate = 0, ht_cap = false;
1450 u8 bw_40MHz = 0, short_GI = 0;
1454 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1455 p = r8712_get_ie(&pcur_bss->IEs[12],
1456 _HT_CAPABILITY_IE_, &ht_ielen,
1457 pcur_bss->IELength - 12);
1458 if (p && ht_ielen > 0) {
1460 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1461 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1462 bw_40MHz = (pht_capie->cap_info &
1463 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1464 short_GI = (pht_capie->cap_info &
1465 (IEEE80211_HT_CAP_SGI_20 |
1466 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1468 while ((pcur_bss->SupportedRates[i] != 0) &&
1469 (pcur_bss->SupportedRates[i] != 0xFF)) {
1470 rate = pcur_bss->SupportedRates[i] & 0x7F;
1471 if (rate > max_rate)
1473 wrqu->bitrate.fixed = 0; /* no auto select */
1474 wrqu->bitrate.value = rate*500000;
1477 if (ht_cap == true) {
1478 if (mcs_rate & 0x8000 /* MCS15 */
1480 RTL8712_RF_2T2R == rf_type)
1481 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1482 270) : ((short_GI) ? 144 : 130);
1483 else if (mcs_rate & 0x0080) /* MCS7 */
1484 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1485 135) : ((short_GI) ? 72 : 65);
1486 else /* default MCS7 */
1487 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1488 135) : ((short_GI) ? 72 : 65);
1489 max_rate *= 2; /* Mbps/2 */
1490 wrqu->bitrate.value = max_rate * 500000;
1492 wrqu->bitrate.value = max_rate * 500000;
1499 static int r8711_wx_get_rts(struct net_device *dev,
1500 struct iw_request_info *info,
1501 union iwreq_data *wrqu, char *extra)
1503 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1505 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1506 wrqu->rts.fixed = 0; /* no auto select */
1510 static int r8711_wx_set_frag(struct net_device *dev,
1511 struct iw_request_info *info,
1512 union iwreq_data *wrqu, char *extra)
1514 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1516 if (wrqu->frag.disabled)
1517 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1519 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1520 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1522 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1527 static int r8711_wx_get_frag(struct net_device *dev,
1528 struct iw_request_info *info,
1529 union iwreq_data *wrqu, char *extra)
1531 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1533 wrqu->frag.value = padapter->xmitpriv.frag_len;
1534 wrqu->frag.fixed = 0; /* no auto select */
1538 static int r8711_wx_get_retry(struct net_device *dev,
1539 struct iw_request_info *info,
1540 union iwreq_data *wrqu, char *extra)
1542 wrqu->retry.value = 7;
1543 wrqu->retry.fixed = 0; /* no auto select */
1544 wrqu->retry.disabled = 1;
1548 static int r8711_wx_set_enc(struct net_device *dev,
1549 struct iw_request_info *info,
1550 union iwreq_data *wrqu, char *keybuf)
1553 u32 keyindex_provided;
1554 struct NDIS_802_11_WEP wep;
1555 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1556 struct iw_point *erq = &(wrqu->encoding);
1557 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1559 key = erq->flags & IW_ENCODE_INDEX;
1560 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1561 if (erq->flags & IW_ENCODE_DISABLED) {
1562 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1563 "EncryptionDisabled\n");
1564 padapter->securitypriv.ndisencryptstatus =
1565 Ndis802_11EncryptionDisabled;
1566 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1567 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1568 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1569 authmode = Ndis802_11AuthModeOpen;
1570 padapter->securitypriv.ndisauthtype = authmode;
1577 keyindex_provided = 1;
1579 keyindex_provided = 0;
1580 key = padapter->securitypriv.PrivacyKeyIndex;
1582 /* set authentication mode */
1583 if (erq->flags & IW_ENCODE_OPEN) {
1584 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1585 "IW_ENCODE_OPEN\n");
1586 padapter->securitypriv.ndisencryptstatus =
1587 Ndis802_11Encryption1Enabled;
1588 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1589 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1590 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1591 authmode = Ndis802_11AuthModeOpen;
1592 padapter->securitypriv.ndisauthtype = authmode;
1593 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1594 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1595 "IW_ENCODE_RESTRICTED\n");
1596 padapter->securitypriv.ndisencryptstatus =
1597 Ndis802_11Encryption1Enabled;
1598 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1599 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1600 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1601 authmode = Ndis802_11AuthModeShared;
1602 padapter->securitypriv.ndisauthtype = authmode;
1604 padapter->securitypriv.ndisencryptstatus =
1605 Ndis802_11Encryption1Enabled;
1606 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1607 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1608 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1609 authmode = Ndis802_11AuthModeOpen;
1610 padapter->securitypriv.ndisauthtype = authmode;
1613 if (erq->length > 0) {
1614 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1615 wep.Length = wep.KeyLength +
1616 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1619 if (keyindex_provided == 1) { /* set key_id only, no given
1620 * KeyMaterial(erq->length==0).*/
1621 padapter->securitypriv.PrivacyKeyIndex = key;
1622 switch (padapter->securitypriv.DefKeylen[key]) {
1624 padapter->securitypriv.PrivacyAlgrthm =
1628 padapter->securitypriv.PrivacyAlgrthm =
1632 padapter->securitypriv.PrivacyAlgrthm =
1639 wep.KeyIndex |= 0x80000000; /* transmit key */
1640 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1641 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1646 static int r8711_wx_get_enc(struct net_device *dev,
1647 struct iw_request_info *info,
1648 union iwreq_data *wrqu, char *keybuf)
1651 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1652 struct iw_point *erq = &(wrqu->encoding);
1653 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1655 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1656 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1658 erq->flags |= IW_ENCODE_DISABLED;
1662 key = erq->flags & IW_ENCODE_INDEX;
1668 key = padapter->securitypriv.PrivacyKeyIndex;
1670 erq->flags = key + 1;
1671 switch (padapter->securitypriv.ndisencryptstatus) {
1672 case Ndis802_11EncryptionNotSupported:
1673 case Ndis802_11EncryptionDisabled:
1675 erq->flags |= IW_ENCODE_DISABLED;
1677 case Ndis802_11Encryption1Enabled:
1678 erq->length = padapter->securitypriv.DefKeylen[key];
1680 memcpy(keybuf, padapter->securitypriv.DefKey[
1681 key].skey, padapter->securitypriv.
1683 erq->flags |= IW_ENCODE_ENABLED;
1684 if (padapter->securitypriv.ndisauthtype ==
1685 Ndis802_11AuthModeOpen)
1686 erq->flags |= IW_ENCODE_OPEN;
1687 else if (padapter->securitypriv.ndisauthtype ==
1688 Ndis802_11AuthModeShared)
1689 erq->flags |= IW_ENCODE_RESTRICTED;
1692 erq->flags |= IW_ENCODE_DISABLED;
1695 case Ndis802_11Encryption2Enabled:
1696 case Ndis802_11Encryption3Enabled:
1698 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1703 erq->flags |= IW_ENCODE_DISABLED;
1709 static int r8711_wx_get_power(struct net_device *dev,
1710 struct iw_request_info *info,
1711 union iwreq_data *wrqu, char *extra)
1713 wrqu->power.value = 0;
1714 wrqu->power.fixed = 0; /* no auto select */
1715 wrqu->power.disabled = 1;
1719 static int r871x_wx_set_gen_ie(struct net_device *dev,
1720 struct iw_request_info *info,
1721 union iwreq_data *wrqu, char *extra)
1723 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1725 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1728 static int r871x_wx_set_auth(struct net_device *dev,
1729 struct iw_request_info *info,
1730 union iwreq_data *wrqu, char *extra)
1732 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1733 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1738 paramid = param->flags & IW_AUTH_INDEX;
1739 paramval = param->value;
1741 case IW_AUTH_WPA_VERSION:
1743 case IW_AUTH_CIPHER_PAIRWISE:
1745 case IW_AUTH_CIPHER_GROUP:
1747 case IW_AUTH_KEY_MGMT:
1749 * ??? does not use these parameters
1752 case IW_AUTH_TKIP_COUNTERMEASURES:
1754 /* wpa_supplicant is enabling tkip countermeasure. */
1755 padapter->securitypriv.btkip_countermeasure = true;
1757 /* wpa_supplicant is disabling tkip countermeasure. */
1758 padapter->securitypriv.btkip_countermeasure = false;
1761 case IW_AUTH_DROP_UNENCRYPTED:
1764 * wpa_supplicant calls set_wpa_enabled when the driver
1765 * is loaded and unloaded, regardless of if WPA is being
1766 * used. No other calls are made which can be used to
1767 * determine if encryption will be used or not prior to
1768 * association being expected. If encryption is not being
1769 * used, drop_unencrypted is set to false, else true -- we
1770 * can use this to determine if the CAP_PRIVACY_ON bit should
1773 if (padapter->securitypriv.ndisencryptstatus ==
1774 Ndis802_11Encryption1Enabled) {
1775 /* it means init value, or using wep,
1776 * ndisencryptstatus =
1777 * Ndis802_11Encryption1Enabled,
1778 * then it needn't reset it;
1784 padapter->securitypriv.ndisencryptstatus =
1785 Ndis802_11EncryptionDisabled;
1786 padapter->securitypriv.PrivacyAlgrthm =
1788 padapter->securitypriv.XGrpPrivacy =
1790 padapter->securitypriv.AuthAlgrthm = 0;
1791 padapter->securitypriv.ndisauthtype =
1792 Ndis802_11AuthModeOpen;
1795 case IW_AUTH_80211_AUTH_ALG:
1796 ret = wpa_set_auth_algs(dev, (u32)paramval);
1798 case IW_AUTH_WPA_ENABLED:
1800 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1802 case IW_AUTH_PRIVACY_INVOKED:
1811 static int r871x_wx_set_enc_ext(struct net_device *dev,
1812 struct iw_request_info *info,
1813 union iwreq_data *wrqu, char *extra)
1815 struct iw_point *pencoding = &wrqu->encoding;
1816 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1817 struct ieee_param *param = NULL;
1822 param_len = sizeof(struct ieee_param) + pext->key_len;
1823 param = (struct ieee_param *)_malloc(param_len);
1826 memset(param, 0, param_len);
1827 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1828 memset(param->sta_addr, 0xff, ETH_ALEN);
1829 switch (pext->alg) {
1830 case IW_ENCODE_ALG_NONE:
1833 case IW_ENCODE_ALG_WEP:
1836 case IW_ENCODE_ALG_TKIP:
1839 case IW_ENCODE_ALG_CCMP:
1845 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1846 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1847 param->u.crypt.set_tx = 0;
1848 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1849 param->u.crypt.set_tx = 1;
1850 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1851 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1852 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1853 if (pext->key_len) {
1854 param->u.crypt.key_len = pext->key_len;
1855 memcpy(param + 1, pext + 1, pext->key_len);
1857 ret = wpa_set_encryption(dev, param, param_len);
1862 static int r871x_wx_get_nick(struct net_device *dev,
1863 struct iw_request_info *info,
1864 union iwreq_data *wrqu, char *extra)
1867 wrqu->data.length = 8;
1868 wrqu->data.flags = 1;
1869 memcpy(extra, "rtl_wifi", 8);
1874 static int r8711_wx_read32(struct net_device *dev,
1875 struct iw_request_info *info,
1876 union iwreq_data *wrqu, char *keybuf)
1878 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1882 get_user(addr, (u32 __user *)wrqu->data.pointer);
1883 data32 = r8712_read32(padapter, addr);
1884 put_user(data32, (u32 __user *)wrqu->data.pointer);
1885 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1886 wrqu->data.flags = data32 & 0xffff;
1887 get_user(addr, (u32 __user *)wrqu->data.pointer);
1891 static int r8711_wx_write32(struct net_device *dev,
1892 struct iw_request_info *info,
1893 union iwreq_data *wrqu, char *keybuf)
1895 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1899 get_user(addr, (u32 __user *)wrqu->data.pointer);
1900 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
1901 r8712_write32(padapter, addr, data32);
1905 static int dummy(struct net_device *dev,
1906 struct iw_request_info *a,
1907 union iwreq_data *wrqu, char *b)
1912 static int r8711_drvext_hdl(struct net_device *dev,
1913 struct iw_request_info *info,
1914 union iwreq_data *wrqu, char *extra)
1919 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1920 struct iw_request_info *info,
1921 union iwreq_data *wrqu, char *extra)
1923 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1924 struct iw_point *p = &wrqu->data;
1925 struct oid_par_priv oid_par;
1926 struct mp_ioctl_handler *phandler;
1927 struct mp_ioctl_param *poidparam;
1928 unsigned long BytesRead, BytesWritten, BytesNeeded;
1929 u8 *pparmbuf = NULL, bset;
1934 if ((!p->length) || (!p->pointer)) {
1936 goto _r871x_mp_ioctl_hdl_exit;
1938 bset = (u8)(p->flags & 0xFFFF);
1941 pparmbuf = (u8 *)_malloc(len);
1942 if (pparmbuf == NULL) {
1944 goto _r871x_mp_ioctl_hdl_exit;
1946 if (copy_from_user(pparmbuf, p->pointer, len)) {
1948 goto _r871x_mp_ioctl_hdl_exit;
1950 poidparam = (struct mp_ioctl_param *)pparmbuf;
1951 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1953 goto _r871x_mp_ioctl_hdl_exit;
1955 phandler = mp_ioctl_hdl + poidparam->subcode;
1956 if ((phandler->paramsize != 0) &&
1957 (poidparam->len < phandler->paramsize)) {
1959 goto _r871x_mp_ioctl_hdl_exit;
1961 if (phandler->oid == 0 && phandler->handler)
1962 status = phandler->handler(&oid_par);
1963 else if (phandler->handler) {
1964 oid_par.adapter_context = padapter;
1965 oid_par.oid = phandler->oid;
1966 oid_par.information_buf = poidparam->data;
1967 oid_par.information_buf_len = poidparam->len;
1972 oid_par.bytes_rw = &BytesRead;
1973 oid_par.bytes_needed = &BytesNeeded;
1974 oid_par.type_of_oid = SET_OID;
1976 oid_par.bytes_rw = &BytesWritten;
1977 oid_par.bytes_needed = &BytesNeeded;
1978 oid_par.type_of_oid = QUERY_OID;
1980 status = phandler->handler(&oid_par);
1981 /* todo:check status, BytesNeeded, etc. */
1983 printk(KERN_INFO "r8712u: r871x_mp_ioctl_hdl(): err!,"
1984 " subcode=%d, oid=%d, handler=%p\n",
1985 poidparam->subcode, phandler->oid, phandler->handler);
1987 goto _r871x_mp_ioctl_hdl_exit;
1989 if (bset == 0x00) { /* query info */
1990 if (copy_to_user(p->pointer, pparmbuf, len))
1995 goto _r871x_mp_ioctl_hdl_exit;
1997 _r871x_mp_ioctl_hdl_exit:
2002 static int r871x_get_ap_info(struct net_device *dev,
2003 struct iw_request_info *info,
2004 union iwreq_data *wrqu, char *extra)
2006 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2007 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2008 struct __queue *queue = &pmlmepriv->scanned_queue;
2009 struct iw_point *pdata = &wrqu->data;
2010 struct wlan_network *pnetwork = NULL;
2011 u32 cnt = 0, wpa_ielen;
2013 struct list_head *plist, *phead;
2014 unsigned char *pbuf;
2018 if (padapter->bDriverStopped || (pdata == NULL))
2020 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
2027 if (pdata->length >= 32) {
2028 if (copy_from_user(data, pdata->pointer, 32))
2032 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2033 phead = get_list_head(queue);
2034 plist = get_next(phead);
2036 if (end_of_queue_search(phead, plist) == true)
2038 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2039 if (hwaddr_aton_i(data, bssid)) {
2040 printk(KERN_INFO "r8712u: Invalid BSSID '%s'.\n",
2042 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2046 printk(KERN_INFO "r8712u: BSSID:%pM\n", bssid);
2047 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2048 /* BSSID match, then check if supporting wpa/wpa2 */
2049 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2050 &wpa_ielen, pnetwork->network.IELength-12);
2051 if (pbuf && (wpa_ielen > 0)) {
2055 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2056 &wpa_ielen, pnetwork->network.IELength-12);
2057 if (pbuf && (wpa_ielen > 0)) {
2062 plist = get_next(plist);
2064 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2065 if (pdata->length >= 34) {
2066 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2067 (u8 *)&pdata->flags, 1))
2073 static int r871x_set_pid(struct net_device *dev,
2074 struct iw_request_info *info,
2075 union iwreq_data *wrqu, char *extra)
2077 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2078 struct iw_point *pdata = &wrqu->data;
2080 if ((padapter->bDriverStopped) || (pdata == NULL))
2082 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2087 static int r871x_set_chplan(struct net_device *dev,
2088 struct iw_request_info *info,
2089 union iwreq_data *wrqu, char *extra)
2092 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2093 struct iw_point *pdata = &wrqu->data;
2096 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2100 ch_plan = (int)*extra;
2101 r8712_set_chplan_cmd(padapter, ch_plan);
2108 static int r871x_wps_start(struct net_device *dev,
2109 struct iw_request_info *info,
2110 union iwreq_data *wrqu, char *extra)
2112 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2113 struct iw_point *pdata = &wrqu->data;
2114 u32 u32wps_start = 0;
2116 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2118 if ((padapter->bDriverStopped) || (pdata == NULL))
2120 if (u32wps_start == 0)
2121 u32wps_start = *extra;
2122 if (u32wps_start == 1) /* WPS Start */
2123 padapter->ledpriv.LedControlHandler(padapter,
2125 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2126 padapter->ledpriv.LedControlHandler(padapter,
2128 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2129 padapter->ledpriv.LedControlHandler(padapter,
2130 LED_CTL_STOP_WPS_FAIL);
2134 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2136 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2139 case IEEE_PARAM_WPA_ENABLED:
2140 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2141 switch ((value)&0xff) {
2143 padapter->securitypriv.ndisauthtype =
2144 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2145 padapter->securitypriv.ndisencryptstatus =
2146 Ndis802_11Encryption2Enabled;
2149 padapter->securitypriv.ndisauthtype =
2150 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2151 padapter->securitypriv.ndisencryptstatus =
2152 Ndis802_11Encryption3Enabled;
2156 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2158 case IEEE_PARAM_DROP_UNENCRYPTED:
2161 * wpa_supplicant calls set_wpa_enabled when the driver
2162 * is loaded and unloaded, regardless of if WPA is being
2163 * used. No other calls are made which can be used to
2164 * determine if encryption will be used or not prior to
2165 * association being expected. If encryption is not being
2166 * used, drop_unencrypted is set to false, else true -- we
2167 * can use this to determine if the CAP_PRIVACY_ON bit should
2171 case IEEE_PARAM_PRIVACY_INVOKED:
2173 case IEEE_PARAM_AUTH_ALGS:
2174 return wpa_set_auth_algs(dev, value);
2176 case IEEE_PARAM_IEEE_802_1X:
2178 case IEEE_PARAM_WPAX_SELECT:
2179 /* added for WPA2 mixed mode */
2187 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2189 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2192 case IEEE_MLME_STA_DEAUTH:
2193 if (!r8712_set_802_11_disassociate(padapter))
2196 case IEEE_MLME_STA_DISASSOC:
2197 if (!r8712_set_802_11_disassociate(padapter))
2206 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2208 struct ieee_param *param;
2210 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2212 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2214 param = (struct ieee_param *)_malloc(p->length);
2217 if (copy_from_user(param, p->pointer, p->length)) {
2221 switch (param->cmd) {
2222 case IEEE_CMD_SET_WPA_PARAM:
2223 ret = wpa_set_param(dev, param->u.wpa_param.name,
2224 param->u.wpa_param.value);
2226 case IEEE_CMD_SET_WPA_IE:
2227 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2228 (u16)param->u.wpa_ie.len);
2230 case IEEE_CMD_SET_ENCRYPTION:
2231 ret = wpa_set_encryption(dev, param, p->length);
2234 ret = wpa_mlme(dev, param->u.mlme.command,
2235 param->u.mlme.reason_code);
2241 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2247 /* based on "driver_ipw" and for hostapd */
2248 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2250 struct iwreq *wrq = (struct iwreq *)rq;
2253 case RTL_IOCTL_WPA_SUPPLICANT:
2254 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2261 static iw_handler r8711_handlers[] = {
2262 NULL, /* SIOCSIWCOMMIT */
2263 r8711_wx_get_name, /* SIOCGIWNAME */
2264 dummy, /* SIOCSIWNWID */
2265 dummy, /* SIOCGIWNWID */
2266 r8711_wx_set_freq, /* SIOCSIWFREQ */
2267 r8711_wx_get_freq, /* SIOCGIWFREQ */
2268 r8711_wx_set_mode, /* SIOCSIWMODE */
2269 r8711_wx_get_mode, /* SIOCGIWMODE */
2270 dummy, /* SIOCSIWSENS */
2271 r8711_wx_get_sens, /* SIOCGIWSENS */
2272 NULL, /* SIOCSIWRANGE */
2273 r8711_wx_get_range, /* SIOCGIWRANGE */
2274 r871x_wx_set_priv, /* SIOCSIWPRIV */
2275 NULL, /* SIOCGIWPRIV */
2276 NULL, /* SIOCSIWSTATS */
2277 NULL, /* SIOCGIWSTATS */
2278 dummy, /* SIOCSIWSPY */
2279 dummy, /* SIOCGIWSPY */
2280 NULL, /* SIOCGIWTHRSPY */
2281 NULL, /* SIOCWIWTHRSPY */
2282 r8711_wx_set_wap, /* SIOCSIWAP */
2283 r8711_wx_get_wap, /* SIOCGIWAP */
2284 r871x_wx_set_mlme, /* request MLME operation;
2285 * uses struct iw_mlme */
2286 dummy, /* SIOCGIWAPLIST -- deprecated */
2287 r8711_wx_set_scan, /* SIOCSIWSCAN */
2288 r8711_wx_get_scan, /* SIOCGIWSCAN */
2289 r8711_wx_set_essid, /* SIOCSIWESSID */
2290 r8711_wx_get_essid, /* SIOCGIWESSID */
2291 dummy, /* SIOCSIWNICKN */
2292 r871x_wx_get_nick, /* SIOCGIWNICKN */
2293 NULL, /* -- hole -- */
2294 NULL, /* -- hole -- */
2295 r8711_wx_set_rate, /* SIOCSIWRATE */
2296 r8711_wx_get_rate, /* SIOCGIWRATE */
2297 dummy, /* SIOCSIWRTS */
2298 r8711_wx_get_rts, /* SIOCGIWRTS */
2299 r8711_wx_set_frag, /* SIOCSIWFRAG */
2300 r8711_wx_get_frag, /* SIOCGIWFRAG */
2301 dummy, /* SIOCSIWTXPOW */
2302 dummy, /* SIOCGIWTXPOW */
2303 dummy, /* SIOCSIWRETRY */
2304 r8711_wx_get_retry, /* SIOCGIWRETRY */
2305 r8711_wx_set_enc, /* SIOCSIWENCODE */
2306 r8711_wx_get_enc, /* SIOCGIWENCODE */
2307 dummy, /* SIOCSIWPOWER */
2308 r8711_wx_get_power, /* SIOCGIWPOWER */
2309 NULL, /*---hole---*/
2310 NULL, /*---hole---*/
2311 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2312 NULL, /* SIOCGIWGENIE */
2313 r871x_wx_set_auth, /* SIOCSIWAUTH */
2314 NULL, /* SIOCGIWAUTH */
2315 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2316 NULL, /* SIOCGIWENCODEEXT */
2317 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2318 NULL, /*---hole---*/
2321 static const struct iw_priv_args r8711_private_args[] = {
2323 SIOCIWFIRSTPRIV + 0x0,
2324 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2327 SIOCIWFIRSTPRIV + 0x1,
2328 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2331 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2334 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2337 SIOCIWFIRSTPRIV + 0x4,
2338 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2341 SIOCIWFIRSTPRIV + 0x5,
2342 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2345 SIOCIWFIRSTPRIV + 0x6,
2346 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2349 SIOCIWFIRSTPRIV + 0x7,
2350 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2354 static iw_handler r8711_private_handler[] = {
2359 r871x_get_ap_info, /*for MM DTV platform*/
2365 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2367 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2368 struct iw_statistics *piwstats = &padapter->iwstats;
2373 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2374 piwstats->qual.qual = 0;
2375 piwstats->qual.level = 0;
2376 piwstats->qual.noise = 0;
2378 /* show percentage, we need transfer dbm to orignal value. */
2379 tmp_level = padapter->recvpriv.fw_rssi;
2380 tmp_qual = padapter->recvpriv.signal;
2381 tmp_noise = padapter->recvpriv.noise;
2382 piwstats->qual.level = tmp_level;
2383 /*piwstats->qual.qual = tmp_qual;
2384 * The NetworkManager of Fedora 10, 13 will use the link
2385 * quality for its display.
2386 * So, use the fw_rssi on link quality variable because
2387 * fw_rssi will be updated per 2 seconds.
2389 piwstats->qual.qual = tmp_level;
2390 piwstats->qual.noise = tmp_noise;
2392 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2393 return &padapter->iwstats;
2396 struct iw_handler_def r871x_handlers_def = {
2397 .standard = r8711_handlers,
2398 .num_standard = sizeof(r8711_handlers) / sizeof(iw_handler),
2399 .private = r8711_private_handler,
2400 .private_args = (struct iw_priv_args *)r8711_private_args,
2401 .num_private = sizeof(r8711_private_handler) / sizeof(iw_handler),
2402 .num_private_args = sizeof(r8711_private_args) /
2403 sizeof(struct iw_priv_args),
2404 .get_wireless_stats = r871x_get_wireless_stats