1 /******************************************************************************
2 * rtl871x_ioctl_linux.c
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.h"
37 #include "rtl871x_mlme.h"
38 #include "rtl871x_ioctl.h"
39 #include "rtl871x_ioctl_set.h"
40 #include "rtl871x_mp_ioctl.h"
41 #include "mlme_osdep.h"
42 #include <linux/wireless.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/init.h>
47 #include <linux/semaphore.h>
48 #include <net/iw_handler.h>
49 #include <linux/if_arp.h>
51 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
53 #define SCAN_ITEM_SIZE 768
54 #define MAX_CUSTOM_LEN 64
58 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
59 6000000, 9000000, 12000000, 18000000,
60 24000000, 36000000, 48000000, 54000000};
62 static const long ieee80211_wlan_frequencies[] = {
63 2412, 2417, 2422, 2427,
64 2432, 2437, 2442, 2447,
65 2452, 2457, 2462, 2467,
69 static const char * const iw_operation_mode[] = {
70 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
75 * hwaddr_aton - Convert ASCII string to MAC address
76 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
77 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
78 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
80 static int hwaddr_aton_i(const char *txt, u8 *addr)
84 for (i = 0; i < 6; i++) {
87 a = hex_to_bin(*txt++);
90 b = hex_to_bin(*txt++);
93 *addr++ = (a << 4) | b;
94 if (i < 5 && *txt++ != ':')
100 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
102 union iwreq_data wrqu;
103 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
105 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
106 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
108 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
111 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
113 union iwreq_data wrqu;
115 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
116 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
117 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
120 static inline void handle_pairwise_key(struct sta_info *psta,
121 struct ieee_param *param,
122 struct _adapter *padapter)
125 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
126 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
127 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
128 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
130 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
132 padapter->securitypriv. busetkipkey = false;
133 _set_timer(&padapter->securitypriv.tkip_timer, 50);
135 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
138 static inline void handle_group_key(struct ieee_param *param,
139 struct _adapter *padapter)
141 if (0 < param->u.crypt.idx &&
142 param->u.crypt.idx < 3) {
143 /* group key idx is 1 or 2 */
144 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
145 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
146 > 16 ? 16 : param->u.crypt.key_len));
147 memcpy(padapter->securitypriv.XGrptxmickey[param->
148 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
149 memcpy(padapter->securitypriv. XGrprxmickey[param->
150 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
151 padapter->securitypriv.binstallGrpkey = true;
152 r8712_set_key(padapter, &padapter->securitypriv,
154 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
155 if (padapter->registrypriv.power_mgnt != padapter->
156 pwrctrlpriv.pwr_mode)
157 _set_timer(&(padapter->mlmepriv.dhcp_timer),
163 static inline char *translate_scan(struct _adapter *padapter,
164 struct iw_request_info *info,
165 struct wlan_network *pnetwork,
166 char *start, char *stop)
169 struct ieee80211_ht_cap *pht_capie;
172 u32 i = 0, ht_ielen = 0;
173 u16 cap, ht_cap = false, mcs_rate;
174 u8 rssi, bw_40MHz = 0, short_GI = 0;
176 if ((pnetwork->network.Configuration.DSConfig < 1) ||
177 (pnetwork->network.Configuration.DSConfig > 14)) {
178 if (pnetwork->network.Configuration.DSConfig < 1)
179 pnetwork->network.Configuration.DSConfig = 1;
181 pnetwork->network.Configuration.DSConfig = 14;
185 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
186 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
187 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
189 iwe.cmd = SIOCGIWESSID;
190 iwe.u.data.flags = 1;
191 iwe.u.data.length = (u16)min((u16)pnetwork->network.Ssid.SsidLength,
193 start = iwe_stream_add_point(info, start, stop, &iwe,
194 pnetwork->network.Ssid.Ssid);
195 /* parsing HT_CAP_IE */
196 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
197 &ht_ielen, pnetwork->network.IELength - 12);
198 if (p && ht_ielen > 0) {
200 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
201 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
202 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
204 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
205 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
207 /* Add the protocol name */
208 iwe.cmd = SIOCGIWNAME;
209 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
210 SupportedRates)) == true) {
212 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
214 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
215 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
216 SupportedRates)) == true) {
218 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
220 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
223 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
225 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
227 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
229 iwe.cmd = SIOCGIWMODE;
230 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
232 cap = le16_to_cpu(cap);
233 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
234 if (cap & WLAN_CAPABILITY_BSS)
235 iwe.u.mode = (u32)IW_MODE_MASTER;
237 iwe.u.mode = (u32)IW_MODE_ADHOC;
238 start = iwe_stream_add_event(info, start, stop, &iwe,
241 /* Add frequency/channel */
242 iwe.cmd = SIOCGIWFREQ;
244 /* check legal index */
245 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
246 if (dsconfig >= 1 && dsconfig <= sizeof(
247 ieee80211_wlan_frequencies) / sizeof(long))
248 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
249 pnetwork->network.Configuration.
250 DSConfig - 1] * 100000);
254 iwe.u.freq.e = (s16)1;
255 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
256 start = iwe_stream_add_event(info, start, stop, &iwe,
258 /* Add encryption capability */
259 iwe.cmd = SIOCGIWENCODE;
260 if (cap & WLAN_CAPABILITY_PRIVACY)
261 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
264 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
265 iwe.u.data.length = (u16)0;
266 start = iwe_stream_add_point(info, start, stop, &iwe,
267 pnetwork->network.Ssid.Ssid);
268 /*Add basic and extended rates */
269 current_val = start + iwe_stream_lcp_len(info);
270 iwe.cmd = SIOCGIWRATE;
271 iwe.u.bitrate.fixed = 0;
272 iwe.u.bitrate.disabled = 0;
273 iwe.u.bitrate.value = 0;
275 while (pnetwork->network.SupportedRates[i] != 0) {
276 /* Bit rate given in 500 kb/s units */
277 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
279 current_val = iwe_stream_add_value(info, start, current_val,
280 stop, &iwe, IW_EV_PARAM_LEN);
282 /* Check if we added any event */
283 if ((current_val - start) > iwe_stream_lcp_len(info))
285 /* parsing WPA/WPA2 IE */
287 u8 buf[MAX_WPA_IE_LEN];
288 u8 wpa_ie[255], rsn_ie[255];
289 u16 wpa_len = 0, rsn_len = 0;
292 out_len = r8712_get_sec_ie(pnetwork->network.IEs,
294 IELength, rsn_ie, &rsn_len,
297 memset(buf, 0, MAX_WPA_IE_LEN);
298 n = sprintf(buf, "wpa_ie=");
299 for (i = 0; i < wpa_len; i++) {
300 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
302 if (n >= MAX_WPA_IE_LEN)
305 memset(&iwe, 0, sizeof(iwe));
306 iwe.cmd = IWEVCUSTOM;
307 iwe.u.data.length = (u16)strlen(buf);
308 start = iwe_stream_add_point(info, start, stop,
310 memset(&iwe, 0, sizeof(iwe));
312 iwe.u.data.length = (u16)wpa_len;
313 start = iwe_stream_add_point(info, start, stop,
317 memset(buf, 0, MAX_WPA_IE_LEN);
318 n = sprintf(buf, "rsn_ie=");
319 for (i = 0; i < rsn_len; i++) {
320 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
322 if (n >= MAX_WPA_IE_LEN)
325 memset(&iwe, 0, sizeof(iwe));
326 iwe.cmd = IWEVCUSTOM;
327 iwe.u.data.length = strlen(buf);
328 start = iwe_stream_add_point(info, start, stop,
330 memset(&iwe, 0, sizeof(iwe));
332 iwe.u.data.length = rsn_len;
333 start = iwe_stream_add_point(info, start, stop, &iwe,
338 { /* parsing WPS IE */
342 if (r8712_get_wps_ie(pnetwork->network.IEs,
343 pnetwork->network.IELength,
344 wps_ie, &wps_ielen) == true) {
347 iwe.u.data.length = (u16)wps_ielen;
348 start = iwe_stream_add_point(info, start, stop,
353 /* Add quality statistics */
355 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
356 /* we only update signal_level (signal strength) that is rssi. */
357 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
358 IW_QUAL_NOISE_INVALID);
359 iwe.u.qual.level = rssi; /* signal strength */
360 iwe.u.qual.qual = 0; /* signal quality */
361 iwe.u.qual.noise = 0; /* noise level */
362 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
363 /* how to translate rssi to ?% */
367 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
369 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
372 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
373 padapter->securitypriv.ndisencryptstatus =
374 Ndis802_11Encryption1Enabled;
375 padapter->securitypriv.ndisauthtype =
376 Ndis802_11AuthModeAutoSwitch;
377 padapter->securitypriv.AuthAlgrthm = 3;
378 } else if (value & AUTH_ALG_SHARED_KEY) {
379 padapter->securitypriv.ndisencryptstatus =
380 Ndis802_11Encryption1Enabled;
381 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
382 padapter->securitypriv.AuthAlgrthm = 1;
383 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
384 if (padapter->securitypriv.ndisauthtype <
385 Ndis802_11AuthModeWPAPSK) {
386 padapter->securitypriv.ndisauthtype =
387 Ndis802_11AuthModeOpen;
388 padapter->securitypriv.AuthAlgrthm = 0;
395 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
399 u32 wep_key_idx, wep_key_len = 0;
400 struct NDIS_802_11_WEP *pwep = NULL;
401 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
402 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
403 struct security_priv *psecuritypriv = &padapter->securitypriv;
405 param->u.crypt.err = 0;
406 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
407 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
408 param->u.crypt.key_len)
410 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
411 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
412 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
413 if (param->u.crypt.idx >= WEP_KEYS) {
414 /* for large key indices, set the default (0) */
415 param->u.crypt.idx = 0;
419 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
420 printk(KERN_INFO "r8712u: wpa_set_encryption, crypt.alg ="
422 padapter->securitypriv.ndisencryptstatus =
423 Ndis802_11Encryption1Enabled;
424 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
425 padapter->securitypriv.XGrpPrivacy = _WEP40_;
426 wep_key_idx = param->u.crypt.idx;
427 wep_key_len = param->u.crypt.key_len;
428 if (wep_key_idx >= WEP_KEYS)
430 if (wep_key_len > 0) {
431 wep_key_len = wep_key_len <= 5 ? 5 : 13;
432 pwep = (struct NDIS_802_11_WEP *)_malloc((u32)
434 FIELD_OFFSET(struct NDIS_802_11_WEP,
438 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
439 pwep->KeyLength = wep_key_len;
440 pwep->Length = wep_key_len +
441 FIELD_OFFSET(struct NDIS_802_11_WEP,
443 if (wep_key_len == 13) {
444 padapter->securitypriv.PrivacyAlgrthm =
446 padapter->securitypriv.XGrpPrivacy =
451 pwep->KeyIndex = wep_key_idx;
452 pwep->KeyIndex |= 0x80000000;
453 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
454 if (param->u.crypt.set_tx) {
455 if (r8712_set_802_11_add_wep(padapter, pwep) ==
459 /* don't update "psecuritypriv->PrivacyAlgrthm" and
460 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
461 * r8712_set_key to fw/cam
463 if (wep_key_idx >= WEP_KEYS) {
467 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
468 skey[0]), pwep->KeyMaterial,
470 psecuritypriv->DefKeylen[wep_key_idx] =
472 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
476 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
477 struct sta_info *psta, *pbcmc_sta;
478 struct sta_priv *pstapriv = &padapter->stapriv;
480 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
481 WIFI_MP_STATE) == true) { /* sta mode */
482 psta = r8712_get_stainfo(pstapriv,
483 get_bssid(pmlmepriv));
485 psta->ieee8021x_blocked = false;
486 if ((padapter->securitypriv.ndisencryptstatus ==
487 Ndis802_11Encryption2Enabled) ||
488 (padapter->securitypriv.ndisencryptstatus ==
489 Ndis802_11Encryption3Enabled))
490 psta->XPrivacy = padapter->
491 securitypriv.PrivacyAlgrthm;
492 if (param->u.crypt.set_tx == 1)
493 handle_pairwise_key(psta, param,
496 handle_group_key(param, padapter);
498 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
500 pbcmc_sta->ieee8021x_blocked = false;
501 if ((padapter->securitypriv.ndisencryptstatus ==
502 Ndis802_11Encryption2Enabled) ||
503 (padapter->securitypriv.ndisencryptstatus ==
504 Ndis802_11Encryption3Enabled))
505 pbcmc_sta->XPrivacy =
506 padapter->securitypriv.
516 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
517 unsigned short ielen)
519 u8 *buf = NULL, *pos = NULL;
520 int group_cipher = 0, pairwise_cipher = 0;
523 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
526 buf = _malloc(ielen);
529 memcpy(buf, pie , ielen);
531 if (ielen < RSN_HEADER_LEN) {
535 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
536 &pairwise_cipher) == _SUCCESS) {
537 padapter->securitypriv.AuthAlgrthm = 2;
538 padapter->securitypriv.ndisauthtype =
539 Ndis802_11AuthModeWPAPSK;
541 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
542 &pairwise_cipher) == _SUCCESS) {
543 padapter->securitypriv.AuthAlgrthm = 2;
544 padapter->securitypriv.ndisauthtype =
545 Ndis802_11AuthModeWPA2PSK;
547 switch (group_cipher) {
548 case WPA_CIPHER_NONE:
549 padapter->securitypriv.XGrpPrivacy =
551 padapter->securitypriv.ndisencryptstatus =
552 Ndis802_11EncryptionDisabled;
554 case WPA_CIPHER_WEP40:
555 padapter->securitypriv.XGrpPrivacy = _WEP40_;
556 padapter->securitypriv.ndisencryptstatus =
557 Ndis802_11Encryption1Enabled;
559 case WPA_CIPHER_TKIP:
560 padapter->securitypriv.XGrpPrivacy = _TKIP_;
561 padapter->securitypriv.ndisencryptstatus =
562 Ndis802_11Encryption2Enabled;
564 case WPA_CIPHER_CCMP:
565 padapter->securitypriv.XGrpPrivacy = _AES_;
566 padapter->securitypriv.ndisencryptstatus =
567 Ndis802_11Encryption3Enabled;
569 case WPA_CIPHER_WEP104:
570 padapter->securitypriv.XGrpPrivacy = _WEP104_;
571 padapter->securitypriv.ndisencryptstatus =
572 Ndis802_11Encryption1Enabled;
575 switch (pairwise_cipher) {
576 case WPA_CIPHER_NONE:
577 padapter->securitypriv.PrivacyAlgrthm =
579 padapter->securitypriv.ndisencryptstatus =
580 Ndis802_11EncryptionDisabled;
582 case WPA_CIPHER_WEP40:
583 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
584 padapter->securitypriv.ndisencryptstatus =
585 Ndis802_11Encryption1Enabled;
587 case WPA_CIPHER_TKIP:
588 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
589 padapter->securitypriv.ndisencryptstatus =
590 Ndis802_11Encryption2Enabled;
592 case WPA_CIPHER_CCMP:
593 padapter->securitypriv.PrivacyAlgrthm = _AES_;
594 padapter->securitypriv.ndisencryptstatus =
595 Ndis802_11Encryption3Enabled;
597 case WPA_CIPHER_WEP104:
598 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
599 padapter->securitypriv.ndisencryptstatus =
600 Ndis802_11Encryption1Enabled;
603 padapter->securitypriv.wps_phase = false;
606 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
608 while (cnt < ielen) {
611 if ((eid == _VENDOR_SPECIFIC_IE_) &&
612 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
613 printk(KERN_INFO "r8712u: "
615 padapter->securitypriv.wps_ie_len =
617 (MAX_WPA_IE_LEN << 2)) ?
619 (MAX_WPA_IE_LEN << 2);
620 memcpy(padapter->securitypriv.wps_ie,
622 padapter->securitypriv.wps_ie_len);
623 padapter->securitypriv.wps_phase =
625 printk(KERN_INFO "r8712u: SET WPS_IE,"
626 " wps_phase==true\n");
630 cnt += buf[cnt + 1] + 2;
639 static int r8711_wx_get_name(struct net_device *dev,
640 struct iw_request_info *info,
641 union iwreq_data *wrqu, char *extra)
643 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
647 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
648 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
649 NDIS_802_11_RATES_EX *prates = NULL;
651 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
653 /* parsing HT_CAP_IE */
654 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
655 &ht_ielen, pcur_bss->IELength - 12);
656 if (p && ht_ielen > 0)
658 prates = &pcur_bss->SupportedRates;
659 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
661 snprintf(wrqu->name, IFNAMSIZ,
664 snprintf(wrqu->name, IFNAMSIZ,
666 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
668 snprintf(wrqu->name, IFNAMSIZ,
671 snprintf(wrqu->name, IFNAMSIZ,
675 snprintf(wrqu->name, IFNAMSIZ,
678 snprintf(wrqu->name, IFNAMSIZ,
682 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
686 static const long frequency_list[] = {
687 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
688 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
689 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
690 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
691 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
695 static int r8711_wx_set_freq(struct net_device *dev,
696 struct iw_request_info *info,
697 union iwreq_data *wrqu, char *extra)
699 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
700 struct iw_freq *fwrq = &wrqu->freq;
703 /* If setting by frequency, convert to a channel */
704 if ((fwrq->e == 1) &&
705 (fwrq->m >= (int) 2.412e8) &&
706 (fwrq->m <= (int) 2.487e8)) {
707 int f = fwrq->m / 100000;
709 while ((c < 14) && (f != frequency_list[c]))
714 /* Setting by channel number */
715 if ((fwrq->m > 14) || (fwrq->e > 0))
718 int channel = fwrq->m;
719 if ((channel < 1) || (channel > 14))
722 /* Yes ! We can set it !!! */
723 padapter->registrypriv.channel = channel;
729 static int r8711_wx_get_freq(struct net_device *dev,
730 struct iw_request_info *info,
731 union iwreq_data *wrqu, char *extra)
733 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
734 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
735 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
737 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
738 wrqu->freq.m = ieee80211_wlan_frequencies[
739 pcur_bss->Configuration.DSConfig-1] * 100000;
741 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);
776 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_supplicant 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' threshold 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 r8712_set_802_11_infrastructure_mode(padapter,
1111 pnetwork->network.InfrastructureMode);
1115 spin_unlock_irqrestore(&queue->lock, irqL);
1117 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1120 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1127 static int r8711_wx_get_wap(struct net_device *dev,
1128 struct iw_request_info *info,
1129 union iwreq_data *wrqu, char *extra)
1131 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1132 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1133 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1135 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1136 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1137 if (check_fwstate(pmlmepriv, _FW_LINKED |
1138 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
1139 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1144 static int r871x_wx_set_mlme(struct net_device *dev,
1145 struct iw_request_info *info,
1146 union iwreq_data *wrqu, char *extra)
1150 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1151 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1155 reason = cpu_to_le16(mlme->reason_code);
1156 switch (mlme->cmd) {
1157 case IW_MLME_DEAUTH:
1158 if (!r8712_set_802_11_disassociate(padapter))
1161 case IW_MLME_DISASSOC:
1162 if (!r8712_set_802_11_disassociate(padapter))
1173 * This function intends to handle the Set Scan command.
1174 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1176 * For this operation to succeed, the interface is brought Up beforehand.
1179 static int r8711_wx_set_scan(struct net_device *dev,
1180 struct iw_request_info *a,
1181 union iwreq_data *wrqu, char *extra)
1183 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1184 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1187 if (padapter->bDriverStopped == true) {
1188 printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
1189 "bDriverStopped=%d\n", padapter->bDriverStopped);
1192 if (padapter->bup == false)
1194 if (padapter->hw_init_completed == false)
1196 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1197 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1199 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1200 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1201 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1202 struct ndis_802_11_ssid ssid;
1204 u32 len = (u32) min((u8)req->essid_len,
1205 (u8)IW_ESSID_MAX_SIZE);
1206 memset((unsigned char *)&ssid, 0,
1207 sizeof(struct ndis_802_11_ssid));
1208 memcpy(ssid.Ssid, req->essid, len);
1209 ssid.SsidLength = len;
1210 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1211 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1212 _FW_UNDER_LINKING)) ||
1213 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1214 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1217 status = r8712_sitesurvey_cmd(padapter, &ssid);
1218 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1221 status = r8712_set_802_11_bssid_list_scan(padapter);
1222 if (status == false)
1227 static int r8711_wx_get_scan(struct net_device *dev,
1228 struct iw_request_info *a,
1229 union iwreq_data *wrqu, char *extra)
1231 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1232 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1233 struct __queue *queue = &pmlmepriv->scanned_queue;
1234 struct wlan_network *pnetwork = NULL;
1236 struct list_head *plist, *phead;
1238 char *stop = ev + wrqu->data.length;
1239 u32 ret = 0, cnt = 0;
1241 if (padapter->bDriverStopped)
1243 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1249 spin_lock_irqsave(&queue->lock, irqL);
1250 phead = get_list_head(queue);
1251 plist = get_next(phead);
1253 if (end_of_queue_search(phead, plist) == true)
1255 if ((stop - ev) < SCAN_ITEM_SIZE) {
1259 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1260 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1261 plist = get_next(plist);
1263 spin_unlock_irqrestore(&queue->lock, irqL);
1264 wrqu->data.length = ev - extra;
1265 wrqu->data.flags = 0;
1270 * s1. set_802_11_infrastructure_mode()
1271 * s2. set_802_11_authenticaion_mode()
1272 * s3. set_802_11_encryption_mode()
1273 * s4. set_802_11_ssid()
1275 * This function intends to handle the Set ESSID command.
1276 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1278 * For this operation to succeed, there is no need for the interface to be Up.
1281 static int r8711_wx_set_essid(struct net_device *dev,
1282 struct iw_request_info *a,
1283 union iwreq_data *wrqu, char *extra)
1285 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1286 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1287 struct __queue *queue = &pmlmepriv->scanned_queue;
1288 struct wlan_network *pnetwork = NULL;
1289 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1290 struct ndis_802_11_ssid ndis_ssid;
1291 u8 *dst_ssid, *src_ssid;
1292 struct list_head *phead;
1295 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1297 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1299 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1301 authmode = padapter->securitypriv.ndisauthtype;
1302 if (wrqu->essid.flags && wrqu->essid.length) {
1303 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1304 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1305 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1306 ndis_ssid.SsidLength = len;
1307 memcpy(ndis_ssid.Ssid, extra, len);
1308 src_ssid = ndis_ssid.Ssid;
1309 phead = get_list_head(queue);
1310 pmlmepriv->pscanned = get_next(phead);
1312 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1314 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1315 struct wlan_network, list);
1316 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1317 dst_ssid = pnetwork->network.Ssid.Ssid;
1318 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1319 && (pnetwork->network.Ssid.SsidLength ==
1320 ndis_ssid.SsidLength)) {
1321 if (check_fwstate(pmlmepriv,
1322 WIFI_ADHOC_STATE)) {
1323 if (pnetwork->network.
1327 cur_network.network.
1332 r8712_set_802_11_infrastructure_mode(
1334 pnetwork->network.InfrastructureMode);
1338 r8712_set_802_11_authentication_mode(padapter, authmode);
1339 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1341 return -EINPROGRESS;
1344 static int r8711_wx_get_essid(struct net_device *dev,
1345 struct iw_request_info *a,
1346 union iwreq_data *wrqu, char *extra)
1348 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1349 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1350 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1353 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1354 len = pcur_bss->Ssid.SsidLength;
1355 wrqu->essid.length = len;
1356 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1357 wrqu->essid.flags = 1;
1364 static int r8711_wx_set_rate(struct net_device *dev,
1365 struct iw_request_info *a,
1366 union iwreq_data *wrqu, char *extra)
1368 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1369 u32 target_rate = wrqu->bitrate.value;
1370 u32 fixed = wrqu->bitrate.fixed;
1372 u8 datarates[NumRates];
1373 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1376 if (target_rate == -1) {
1380 target_rate = target_rate / 100000;
1381 switch (target_rate) {
1423 for (i = 0; i < NumRates; i++) {
1424 if (ratevalue == mpdatarate[i]) {
1425 datarates[i] = mpdatarate[i];
1429 datarates[i] = 0xff;
1431 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1436 static int r8711_wx_get_rate(struct net_device *dev,
1437 struct iw_request_info *info,
1438 union iwreq_data *wrqu, char *extra)
1440 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1441 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1442 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1443 struct ieee80211_ht_cap *pht_capie;
1444 unsigned char rf_type = padapter->registrypriv.rf_config;
1447 u16 rate, max_rate = 0, ht_cap = false;
1449 u8 bw_40MHz = 0, short_GI = 0;
1453 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1454 p = r8712_get_ie(&pcur_bss->IEs[12],
1455 _HT_CAPABILITY_IE_, &ht_ielen,
1456 pcur_bss->IELength - 12);
1457 if (p && ht_ielen > 0) {
1459 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1460 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1461 bw_40MHz = (pht_capie->cap_info &
1462 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1463 short_GI = (pht_capie->cap_info &
1464 (IEEE80211_HT_CAP_SGI_20 |
1465 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1467 while ((pcur_bss->SupportedRates[i] != 0) &&
1468 (pcur_bss->SupportedRates[i] != 0xFF)) {
1469 rate = pcur_bss->SupportedRates[i] & 0x7F;
1470 if (rate > max_rate)
1472 wrqu->bitrate.fixed = 0; /* no auto select */
1473 wrqu->bitrate.value = rate*500000;
1476 if (ht_cap == true) {
1477 if (mcs_rate & 0x8000 /* MCS15 */
1479 RTL8712_RF_2T2R == rf_type)
1480 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1481 270) : ((short_GI) ? 144 : 130);
1482 else if (mcs_rate & 0x0080) /* MCS7 */
1483 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1484 135) : ((short_GI) ? 72 : 65);
1485 else /* default MCS7 */
1486 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1487 135) : ((short_GI) ? 72 : 65);
1488 max_rate *= 2; /* Mbps/2 */
1489 wrqu->bitrate.value = max_rate * 500000;
1491 wrqu->bitrate.value = max_rate * 500000;
1498 static int r8711_wx_get_rts(struct net_device *dev,
1499 struct iw_request_info *info,
1500 union iwreq_data *wrqu, char *extra)
1502 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1504 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1505 wrqu->rts.fixed = 0; /* no auto select */
1509 static int r8711_wx_set_frag(struct net_device *dev,
1510 struct iw_request_info *info,
1511 union iwreq_data *wrqu, char *extra)
1513 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1515 if (wrqu->frag.disabled)
1516 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1518 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1519 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1521 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1526 static int r8711_wx_get_frag(struct net_device *dev,
1527 struct iw_request_info *info,
1528 union iwreq_data *wrqu, char *extra)
1530 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1532 wrqu->frag.value = padapter->xmitpriv.frag_len;
1533 wrqu->frag.fixed = 0; /* no auto select */
1537 static int r8711_wx_get_retry(struct net_device *dev,
1538 struct iw_request_info *info,
1539 union iwreq_data *wrqu, char *extra)
1541 wrqu->retry.value = 7;
1542 wrqu->retry.fixed = 0; /* no auto select */
1543 wrqu->retry.disabled = 1;
1547 static int r8711_wx_set_enc(struct net_device *dev,
1548 struct iw_request_info *info,
1549 union iwreq_data *wrqu, char *keybuf)
1552 u32 keyindex_provided;
1553 struct NDIS_802_11_WEP wep;
1554 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1555 struct iw_point *erq = &(wrqu->encoding);
1556 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1558 key = erq->flags & IW_ENCODE_INDEX;
1559 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1560 if (erq->flags & IW_ENCODE_DISABLED) {
1561 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1562 "EncryptionDisabled\n");
1563 padapter->securitypriv.ndisencryptstatus =
1564 Ndis802_11EncryptionDisabled;
1565 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1566 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1567 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1568 authmode = Ndis802_11AuthModeOpen;
1569 padapter->securitypriv.ndisauthtype = authmode;
1576 keyindex_provided = 1;
1578 keyindex_provided = 0;
1579 key = padapter->securitypriv.PrivacyKeyIndex;
1581 /* set authentication mode */
1582 if (erq->flags & IW_ENCODE_OPEN) {
1583 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1584 "IW_ENCODE_OPEN\n");
1585 padapter->securitypriv.ndisencryptstatus =
1586 Ndis802_11Encryption1Enabled;
1587 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1588 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1589 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1590 authmode = Ndis802_11AuthModeOpen;
1591 padapter->securitypriv.ndisauthtype = authmode;
1592 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1593 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1594 "IW_ENCODE_RESTRICTED\n");
1595 padapter->securitypriv.ndisencryptstatus =
1596 Ndis802_11Encryption1Enabled;
1597 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1598 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1599 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1600 authmode = Ndis802_11AuthModeShared;
1601 padapter->securitypriv.ndisauthtype = authmode;
1603 padapter->securitypriv.ndisencryptstatus =
1604 Ndis802_11Encryption1Enabled;
1605 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1606 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1607 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1608 authmode = Ndis802_11AuthModeOpen;
1609 padapter->securitypriv.ndisauthtype = authmode;
1612 if (erq->length > 0) {
1613 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1614 wep.Length = wep.KeyLength +
1615 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1618 if (keyindex_provided == 1) { /* set key_id only, no given
1619 * KeyMaterial(erq->length==0).*/
1620 padapter->securitypriv.PrivacyKeyIndex = key;
1621 switch (padapter->securitypriv.DefKeylen[key]) {
1623 padapter->securitypriv.PrivacyAlgrthm =
1627 padapter->securitypriv.PrivacyAlgrthm =
1631 padapter->securitypriv.PrivacyAlgrthm =
1638 wep.KeyIndex |= 0x80000000; /* transmit key */
1639 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1640 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1645 static int r8711_wx_get_enc(struct net_device *dev,
1646 struct iw_request_info *info,
1647 union iwreq_data *wrqu, char *keybuf)
1650 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1651 struct iw_point *erq = &(wrqu->encoding);
1652 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1654 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1655 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1657 erq->flags |= IW_ENCODE_DISABLED;
1661 key = erq->flags & IW_ENCODE_INDEX;
1667 key = padapter->securitypriv.PrivacyKeyIndex;
1669 erq->flags = key + 1;
1670 switch (padapter->securitypriv.ndisencryptstatus) {
1671 case Ndis802_11EncryptionNotSupported:
1672 case Ndis802_11EncryptionDisabled:
1674 erq->flags |= IW_ENCODE_DISABLED;
1676 case Ndis802_11Encryption1Enabled:
1677 erq->length = padapter->securitypriv.DefKeylen[key];
1679 memcpy(keybuf, padapter->securitypriv.DefKey[
1680 key].skey, padapter->securitypriv.
1682 erq->flags |= IW_ENCODE_ENABLED;
1683 if (padapter->securitypriv.ndisauthtype ==
1684 Ndis802_11AuthModeOpen)
1685 erq->flags |= IW_ENCODE_OPEN;
1686 else if (padapter->securitypriv.ndisauthtype ==
1687 Ndis802_11AuthModeShared)
1688 erq->flags |= IW_ENCODE_RESTRICTED;
1691 erq->flags |= IW_ENCODE_DISABLED;
1694 case Ndis802_11Encryption2Enabled:
1695 case Ndis802_11Encryption3Enabled:
1697 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1702 erq->flags |= IW_ENCODE_DISABLED;
1708 static int r8711_wx_get_power(struct net_device *dev,
1709 struct iw_request_info *info,
1710 union iwreq_data *wrqu, char *extra)
1712 wrqu->power.value = 0;
1713 wrqu->power.fixed = 0; /* no auto select */
1714 wrqu->power.disabled = 1;
1718 static int r871x_wx_set_gen_ie(struct net_device *dev,
1719 struct iw_request_info *info,
1720 union iwreq_data *wrqu, char *extra)
1722 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1724 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1727 static int r871x_wx_set_auth(struct net_device *dev,
1728 struct iw_request_info *info,
1729 union iwreq_data *wrqu, char *extra)
1731 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1732 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1737 paramid = param->flags & IW_AUTH_INDEX;
1738 paramval = param->value;
1740 case IW_AUTH_WPA_VERSION:
1742 case IW_AUTH_CIPHER_PAIRWISE:
1744 case IW_AUTH_CIPHER_GROUP:
1746 case IW_AUTH_KEY_MGMT:
1748 * ??? does not use these parameters
1751 case IW_AUTH_TKIP_COUNTERMEASURES:
1753 /* wpa_supplicant is enabling tkip countermeasure. */
1754 padapter->securitypriv.btkip_countermeasure = true;
1756 /* wpa_supplicant is disabling tkip countermeasure. */
1757 padapter->securitypriv.btkip_countermeasure = false;
1760 case IW_AUTH_DROP_UNENCRYPTED:
1763 * wpa_supplicant calls set_wpa_enabled when the driver
1764 * is loaded and unloaded, regardless of if WPA is being
1765 * used. No other calls are made which can be used to
1766 * determine if encryption will be used or not prior to
1767 * association being expected. If encryption is not being
1768 * used, drop_unencrypted is set to false, else true -- we
1769 * can use this to determine if the CAP_PRIVACY_ON bit should
1772 if (padapter->securitypriv.ndisencryptstatus ==
1773 Ndis802_11Encryption1Enabled) {
1774 /* it means init value, or using wep,
1775 * ndisencryptstatus =
1776 * Ndis802_11Encryption1Enabled,
1777 * then it needn't reset it;
1783 padapter->securitypriv.ndisencryptstatus =
1784 Ndis802_11EncryptionDisabled;
1785 padapter->securitypriv.PrivacyAlgrthm =
1787 padapter->securitypriv.XGrpPrivacy =
1789 padapter->securitypriv.AuthAlgrthm = 0;
1790 padapter->securitypriv.ndisauthtype =
1791 Ndis802_11AuthModeOpen;
1794 case IW_AUTH_80211_AUTH_ALG:
1795 ret = wpa_set_auth_algs(dev, (u32)paramval);
1797 case IW_AUTH_WPA_ENABLED:
1799 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1801 case IW_AUTH_PRIVACY_INVOKED:
1810 static int r871x_wx_set_enc_ext(struct net_device *dev,
1811 struct iw_request_info *info,
1812 union iwreq_data *wrqu, char *extra)
1814 struct iw_point *pencoding = &wrqu->encoding;
1815 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1816 struct ieee_param *param = NULL;
1821 param_len = sizeof(struct ieee_param) + pext->key_len;
1822 param = (struct ieee_param *)_malloc(param_len);
1825 memset(param, 0, param_len);
1826 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1827 memset(param->sta_addr, 0xff, ETH_ALEN);
1828 switch (pext->alg) {
1829 case IW_ENCODE_ALG_NONE:
1832 case IW_ENCODE_ALG_WEP:
1835 case IW_ENCODE_ALG_TKIP:
1838 case IW_ENCODE_ALG_CCMP:
1844 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1845 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1846 param->u.crypt.set_tx = 0;
1847 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1848 param->u.crypt.set_tx = 1;
1849 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1850 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1851 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1852 if (pext->key_len) {
1853 param->u.crypt.key_len = pext->key_len;
1854 memcpy(param + 1, pext + 1, pext->key_len);
1856 ret = wpa_set_encryption(dev, param, param_len);
1861 static int r871x_wx_get_nick(struct net_device *dev,
1862 struct iw_request_info *info,
1863 union iwreq_data *wrqu, char *extra)
1866 wrqu->data.length = 8;
1867 wrqu->data.flags = 1;
1868 memcpy(extra, "rtl_wifi", 8);
1873 static int r8711_wx_read32(struct net_device *dev,
1874 struct iw_request_info *info,
1875 union iwreq_data *wrqu, char *keybuf)
1877 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1881 get_user(addr, (u32 __user *)wrqu->data.pointer);
1882 data32 = r8712_read32(padapter, addr);
1883 put_user(data32, (u32 __user *)wrqu->data.pointer);
1884 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1885 wrqu->data.flags = data32 & 0xffff;
1886 get_user(addr, (u32 __user *)wrqu->data.pointer);
1890 static int r8711_wx_write32(struct net_device *dev,
1891 struct iw_request_info *info,
1892 union iwreq_data *wrqu, char *keybuf)
1894 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1898 get_user(addr, (u32 __user *)wrqu->data.pointer);
1899 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
1900 r8712_write32(padapter, addr, data32);
1904 static int dummy(struct net_device *dev,
1905 struct iw_request_info *a,
1906 union iwreq_data *wrqu, char *b)
1911 static int r8711_drvext_hdl(struct net_device *dev,
1912 struct iw_request_info *info,
1913 union iwreq_data *wrqu, char *extra)
1918 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1919 struct iw_request_info *info,
1920 union iwreq_data *wrqu, char *extra)
1922 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1923 struct iw_point *p = &wrqu->data;
1924 struct oid_par_priv oid_par;
1925 struct mp_ioctl_handler *phandler;
1926 struct mp_ioctl_param *poidparam;
1927 unsigned long BytesRead, BytesWritten, BytesNeeded;
1928 u8 *pparmbuf = NULL, bset;
1933 if ((!p->length) || (!p->pointer)) {
1935 goto _r871x_mp_ioctl_hdl_exit;
1937 bset = (u8)(p->flags & 0xFFFF);
1940 pparmbuf = (u8 *)_malloc(len);
1941 if (pparmbuf == NULL) {
1943 goto _r871x_mp_ioctl_hdl_exit;
1945 if (copy_from_user(pparmbuf, p->pointer, len)) {
1947 goto _r871x_mp_ioctl_hdl_exit;
1949 poidparam = (struct mp_ioctl_param *)pparmbuf;
1950 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1952 goto _r871x_mp_ioctl_hdl_exit;
1954 phandler = mp_ioctl_hdl + poidparam->subcode;
1955 if ((phandler->paramsize != 0) &&
1956 (poidparam->len < phandler->paramsize)) {
1958 goto _r871x_mp_ioctl_hdl_exit;
1960 if (phandler->oid == 0 && phandler->handler)
1961 status = phandler->handler(&oid_par);
1962 else if (phandler->handler) {
1963 oid_par.adapter_context = padapter;
1964 oid_par.oid = phandler->oid;
1965 oid_par.information_buf = poidparam->data;
1966 oid_par.information_buf_len = poidparam->len;
1971 oid_par.bytes_rw = &BytesRead;
1972 oid_par.bytes_needed = &BytesNeeded;
1973 oid_par.type_of_oid = SET_OID;
1975 oid_par.bytes_rw = &BytesWritten;
1976 oid_par.bytes_needed = &BytesNeeded;
1977 oid_par.type_of_oid = QUERY_OID;
1979 status = phandler->handler(&oid_par);
1980 /* todo:check status, BytesNeeded, etc. */
1982 printk(KERN_INFO "r8712u: r871x_mp_ioctl_hdl(): err!,"
1983 " subcode=%d, oid=%d, handler=%p\n",
1984 poidparam->subcode, phandler->oid, phandler->handler);
1986 goto _r871x_mp_ioctl_hdl_exit;
1988 if (bset == 0x00) { /* query info */
1989 if (copy_to_user(p->pointer, pparmbuf, len))
1994 goto _r871x_mp_ioctl_hdl_exit;
1996 _r871x_mp_ioctl_hdl_exit:
2001 static int r871x_get_ap_info(struct net_device *dev,
2002 struct iw_request_info *info,
2003 union iwreq_data *wrqu, char *extra)
2005 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2006 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2007 struct __queue *queue = &pmlmepriv->scanned_queue;
2008 struct iw_point *pdata = &wrqu->data;
2009 struct wlan_network *pnetwork = NULL;
2010 u32 cnt = 0, wpa_ielen;
2012 struct list_head *plist, *phead;
2013 unsigned char *pbuf;
2017 if (padapter->bDriverStopped || (pdata == NULL))
2019 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
2026 if (pdata->length >= 32) {
2027 if (copy_from_user(data, pdata->pointer, 32))
2031 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2032 phead = get_list_head(queue);
2033 plist = get_next(phead);
2035 if (end_of_queue_search(phead, plist) == true)
2037 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2038 if (hwaddr_aton_i(data, bssid)) {
2039 printk(KERN_INFO "r8712u: Invalid BSSID '%s'.\n",
2041 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2045 printk(KERN_INFO "r8712u: BSSID:%pM\n", bssid);
2046 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2047 /* BSSID match, then check if supporting wpa/wpa2 */
2048 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2049 &wpa_ielen, pnetwork->network.IELength-12);
2050 if (pbuf && (wpa_ielen > 0)) {
2054 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2055 &wpa_ielen, pnetwork->network.IELength-12);
2056 if (pbuf && (wpa_ielen > 0)) {
2061 plist = get_next(plist);
2063 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2064 if (pdata->length >= 34) {
2065 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2066 (u8 *)&pdata->flags, 1))
2072 static int r871x_set_pid(struct net_device *dev,
2073 struct iw_request_info *info,
2074 union iwreq_data *wrqu, char *extra)
2076 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2077 struct iw_point *pdata = &wrqu->data;
2079 if ((padapter->bDriverStopped) || (pdata == NULL))
2081 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2086 static int r871x_set_chplan(struct net_device *dev,
2087 struct iw_request_info *info,
2088 union iwreq_data *wrqu, char *extra)
2091 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2092 struct iw_point *pdata = &wrqu->data;
2095 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2099 ch_plan = (int)*extra;
2100 r8712_set_chplan_cmd(padapter, ch_plan);
2107 static int r871x_wps_start(struct net_device *dev,
2108 struct iw_request_info *info,
2109 union iwreq_data *wrqu, char *extra)
2111 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2112 struct iw_point *pdata = &wrqu->data;
2113 u32 u32wps_start = 0;
2115 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2117 if ((padapter->bDriverStopped) || (pdata == NULL))
2119 if (u32wps_start == 0)
2120 u32wps_start = *extra;
2121 if (u32wps_start == 1) /* WPS Start */
2122 padapter->ledpriv.LedControlHandler(padapter,
2124 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2125 padapter->ledpriv.LedControlHandler(padapter,
2127 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2128 padapter->ledpriv.LedControlHandler(padapter,
2129 LED_CTL_STOP_WPS_FAIL);
2133 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2135 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2138 case IEEE_PARAM_WPA_ENABLED:
2139 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2140 switch ((value)&0xff) {
2142 padapter->securitypriv.ndisauthtype =
2143 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2144 padapter->securitypriv.ndisencryptstatus =
2145 Ndis802_11Encryption2Enabled;
2148 padapter->securitypriv.ndisauthtype =
2149 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2150 padapter->securitypriv.ndisencryptstatus =
2151 Ndis802_11Encryption3Enabled;
2155 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2157 case IEEE_PARAM_DROP_UNENCRYPTED:
2160 * wpa_supplicant calls set_wpa_enabled when the driver
2161 * is loaded and unloaded, regardless of if WPA is being
2162 * used. No other calls are made which can be used to
2163 * determine if encryption will be used or not prior to
2164 * association being expected. If encryption is not being
2165 * used, drop_unencrypted is set to false, else true -- we
2166 * can use this to determine if the CAP_PRIVACY_ON bit should
2170 case IEEE_PARAM_PRIVACY_INVOKED:
2172 case IEEE_PARAM_AUTH_ALGS:
2173 return wpa_set_auth_algs(dev, value);
2175 case IEEE_PARAM_IEEE_802_1X:
2177 case IEEE_PARAM_WPAX_SELECT:
2178 /* added for WPA2 mixed mode */
2186 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2188 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2191 case IEEE_MLME_STA_DEAUTH:
2192 if (!r8712_set_802_11_disassociate(padapter))
2195 case IEEE_MLME_STA_DISASSOC:
2196 if (!r8712_set_802_11_disassociate(padapter))
2205 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2207 struct ieee_param *param;
2209 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2211 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2213 param = (struct ieee_param *)_malloc(p->length);
2216 if (copy_from_user(param, p->pointer, p->length)) {
2220 switch (param->cmd) {
2221 case IEEE_CMD_SET_WPA_PARAM:
2222 ret = wpa_set_param(dev, param->u.wpa_param.name,
2223 param->u.wpa_param.value);
2225 case IEEE_CMD_SET_WPA_IE:
2226 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2227 (u16)param->u.wpa_ie.len);
2229 case IEEE_CMD_SET_ENCRYPTION:
2230 ret = wpa_set_encryption(dev, param, p->length);
2233 ret = wpa_mlme(dev, param->u.mlme.command,
2234 param->u.mlme.reason_code);
2240 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2246 /* based on "driver_ipw" and for hostapd */
2247 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2249 struct iwreq *wrq = (struct iwreq *)rq;
2252 case RTL_IOCTL_WPA_SUPPLICANT:
2253 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2260 static iw_handler r8711_handlers[] = {
2261 NULL, /* SIOCSIWCOMMIT */
2262 r8711_wx_get_name, /* SIOCGIWNAME */
2263 dummy, /* SIOCSIWNWID */
2264 dummy, /* SIOCGIWNWID */
2265 r8711_wx_set_freq, /* SIOCSIWFREQ */
2266 r8711_wx_get_freq, /* SIOCGIWFREQ */
2267 r8711_wx_set_mode, /* SIOCSIWMODE */
2268 r8711_wx_get_mode, /* SIOCGIWMODE */
2269 dummy, /* SIOCSIWSENS */
2270 r8711_wx_get_sens, /* SIOCGIWSENS */
2271 NULL, /* SIOCSIWRANGE */
2272 r8711_wx_get_range, /* SIOCGIWRANGE */
2273 r871x_wx_set_priv, /* SIOCSIWPRIV */
2274 NULL, /* SIOCGIWPRIV */
2275 NULL, /* SIOCSIWSTATS */
2276 NULL, /* SIOCGIWSTATS */
2277 dummy, /* SIOCSIWSPY */
2278 dummy, /* SIOCGIWSPY */
2279 NULL, /* SIOCGIWTHRSPY */
2280 NULL, /* SIOCWIWTHRSPY */
2281 r8711_wx_set_wap, /* SIOCSIWAP */
2282 r8711_wx_get_wap, /* SIOCGIWAP */
2283 r871x_wx_set_mlme, /* request MLME operation;
2284 * uses struct iw_mlme */
2285 dummy, /* SIOCGIWAPLIST -- deprecated */
2286 r8711_wx_set_scan, /* SIOCSIWSCAN */
2287 r8711_wx_get_scan, /* SIOCGIWSCAN */
2288 r8711_wx_set_essid, /* SIOCSIWESSID */
2289 r8711_wx_get_essid, /* SIOCGIWESSID */
2290 dummy, /* SIOCSIWNICKN */
2291 r871x_wx_get_nick, /* SIOCGIWNICKN */
2292 NULL, /* -- hole -- */
2293 NULL, /* -- hole -- */
2294 r8711_wx_set_rate, /* SIOCSIWRATE */
2295 r8711_wx_get_rate, /* SIOCGIWRATE */
2296 dummy, /* SIOCSIWRTS */
2297 r8711_wx_get_rts, /* SIOCGIWRTS */
2298 r8711_wx_set_frag, /* SIOCSIWFRAG */
2299 r8711_wx_get_frag, /* SIOCGIWFRAG */
2300 dummy, /* SIOCSIWTXPOW */
2301 dummy, /* SIOCGIWTXPOW */
2302 dummy, /* SIOCSIWRETRY */
2303 r8711_wx_get_retry, /* SIOCGIWRETRY */
2304 r8711_wx_set_enc, /* SIOCSIWENCODE */
2305 r8711_wx_get_enc, /* SIOCGIWENCODE */
2306 dummy, /* SIOCSIWPOWER */
2307 r8711_wx_get_power, /* SIOCGIWPOWER */
2308 NULL, /*---hole---*/
2309 NULL, /*---hole---*/
2310 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2311 NULL, /* SIOCGIWGENIE */
2312 r871x_wx_set_auth, /* SIOCSIWAUTH */
2313 NULL, /* SIOCGIWAUTH */
2314 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2315 NULL, /* SIOCGIWENCODEEXT */
2316 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2317 NULL, /*---hole---*/
2320 static const struct iw_priv_args r8711_private_args[] = {
2322 SIOCIWFIRSTPRIV + 0x0,
2323 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2326 SIOCIWFIRSTPRIV + 0x1,
2327 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2330 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2333 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2336 SIOCIWFIRSTPRIV + 0x4,
2337 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2340 SIOCIWFIRSTPRIV + 0x5,
2341 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2344 SIOCIWFIRSTPRIV + 0x6,
2345 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2348 SIOCIWFIRSTPRIV + 0x7,
2349 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2353 static iw_handler r8711_private_handler[] = {
2358 r871x_get_ap_info, /*for MM DTV platform*/
2364 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2366 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2367 struct iw_statistics *piwstats = &padapter->iwstats;
2372 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2373 piwstats->qual.qual = 0;
2374 piwstats->qual.level = 0;
2375 piwstats->qual.noise = 0;
2377 /* show percentage, we need transfer dbm to orignal value. */
2378 tmp_level = padapter->recvpriv.fw_rssi;
2379 tmp_qual = padapter->recvpriv.signal;
2380 tmp_noise = padapter->recvpriv.noise;
2381 piwstats->qual.level = tmp_level;
2382 piwstats->qual.qual = tmp_qual;
2383 piwstats->qual.noise = tmp_noise;
2385 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2386 return &padapter->iwstats;
2389 struct iw_handler_def r871x_handlers_def = {
2390 .standard = r8711_handlers,
2391 .num_standard = ARRAY_SIZE(r8711_handlers),
2392 .private = r8711_private_handler,
2393 .private_args = (struct iw_priv_args *)r8711_private_args,
2394 .num_private = ARRAY_SIZE(r8711_private_handler),
2395 .num_private_args = sizeof(r8711_private_args) /
2396 sizeof(struct iw_priv_args),
2397 .get_wireless_stats = r871x_get_wireless_stats