1 /******************************************************************************
2 * rtl871x_ioctl_linux.c
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.h"
37 #include "rtl871x_mlme.h"
38 #include "rtl871x_ioctl.h"
39 #include "rtl871x_ioctl_set.h"
40 #include "rtl871x_mp_ioctl.h"
41 #include "mlme_osdep.h"
42 #include <linux/wireless.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
46 #include <linux/semaphore.h>
47 #include <net/iw_handler.h>
48 #include <linux/if_arp.h>
50 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
52 #define SCAN_ITEM_SIZE 768
53 #define MAX_CUSTOM_LEN 64
57 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
58 6000000, 9000000, 12000000, 18000000,
59 24000000, 36000000, 48000000, 54000000};
61 static const long ieee80211_wlan_frequencies[] = {
62 2412, 2417, 2422, 2427,
63 2432, 2437, 2442, 2447,
64 2452, 2457, 2462, 2467,
68 static const char * const iw_operation_mode[] = {
69 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
74 * hwaddr_aton - Convert ASCII string to MAC address
75 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
76 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
77 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
79 static int hwaddr_aton_i(const char *txt, u8 *addr)
83 for (i = 0; i < 6; i++) {
86 a = hex_to_bin(*txt++);
89 b = hex_to_bin(*txt++);
92 *addr++ = (a << 4) | b;
93 if (i < 5 && *txt++ != ':')
99 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
101 union iwreq_data wrqu;
102 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
104 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
105 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
107 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
110 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
112 union iwreq_data wrqu;
114 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
115 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
116 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
119 static inline void handle_pairwise_key(struct sta_info *psta,
120 struct ieee_param *param,
121 struct _adapter *padapter)
124 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
125 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
126 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
127 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
129 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
131 padapter->securitypriv. busetkipkey = false;
132 _set_timer(&padapter->securitypriv.tkip_timer, 50);
134 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
137 static inline void handle_group_key(struct ieee_param *param,
138 struct _adapter *padapter)
140 if (0 < param->u.crypt.idx &&
141 param->u.crypt.idx < 3) {
142 /* group key idx is 1 or 2 */
143 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
144 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
145 > 16 ? 16 : param->u.crypt.key_len));
146 memcpy(padapter->securitypriv.XGrptxmickey[param->
147 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
148 memcpy(padapter->securitypriv. XGrprxmickey[param->
149 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
150 padapter->securitypriv.binstallGrpkey = true;
151 r8712_set_key(padapter, &padapter->securitypriv,
153 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
154 if (padapter->registrypriv.power_mgnt != padapter->
155 pwrctrlpriv.pwr_mode)
156 _set_timer(&(padapter->mlmepriv.dhcp_timer),
162 static inline char *translate_scan(struct _adapter *padapter,
163 struct iw_request_info *info,
164 struct wlan_network *pnetwork,
165 char *start, char *stop)
168 struct ieee80211_ht_cap *pht_capie;
171 u32 i = 0, ht_ielen = 0;
172 u16 cap, ht_cap = false, mcs_rate;
173 u8 rssi, bw_40MHz = 0, short_GI = 0;
175 if ((pnetwork->network.Configuration.DSConfig < 1) ||
176 (pnetwork->network.Configuration.DSConfig > 14)) {
177 if (pnetwork->network.Configuration.DSConfig < 1)
178 pnetwork->network.Configuration.DSConfig = 1;
180 pnetwork->network.Configuration.DSConfig = 14;
184 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
185 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
186 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
188 iwe.cmd = SIOCGIWESSID;
189 iwe.u.data.flags = 1;
190 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
191 start = iwe_stream_add_point(info, start, stop, &iwe,
192 pnetwork->network.Ssid.Ssid);
193 /* parsing HT_CAP_IE */
194 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
195 &ht_ielen, pnetwork->network.IELength - 12);
196 if (p && ht_ielen > 0) {
198 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
199 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
200 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
202 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
203 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
205 /* Add the protocol name */
206 iwe.cmd = SIOCGIWNAME;
207 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
208 SupportedRates)) == true) {
210 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
212 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
213 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
214 SupportedRates)) == true) {
216 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
218 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
221 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
223 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
225 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
227 iwe.cmd = SIOCGIWMODE;
228 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
230 cap = le16_to_cpu(cap);
231 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
232 if (cap & WLAN_CAPABILITY_BSS)
233 iwe.u.mode = (u32)IW_MODE_MASTER;
235 iwe.u.mode = (u32)IW_MODE_ADHOC;
236 start = iwe_stream_add_event(info, start, stop, &iwe,
239 /* Add frequency/channel */
240 iwe.cmd = SIOCGIWFREQ;
242 /* check legal index */
243 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
244 if (dsconfig >= 1 && dsconfig <= sizeof(
245 ieee80211_wlan_frequencies) / sizeof(long))
246 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
247 pnetwork->network.Configuration.
248 DSConfig - 1] * 100000);
252 iwe.u.freq.e = (s16)1;
253 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
254 start = iwe_stream_add_event(info, start, stop, &iwe,
256 /* Add encryption capability */
257 iwe.cmd = SIOCGIWENCODE;
258 if (cap & WLAN_CAPABILITY_PRIVACY)
259 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
262 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
263 iwe.u.data.length = (u16)0;
264 start = iwe_stream_add_point(info, start, stop, &iwe,
265 pnetwork->network.Ssid.Ssid);
266 /*Add basic and extended rates */
267 current_val = start + iwe_stream_lcp_len(info);
268 iwe.cmd = SIOCGIWRATE;
269 iwe.u.bitrate.fixed = 0;
270 iwe.u.bitrate.disabled = 0;
271 iwe.u.bitrate.value = 0;
273 while (pnetwork->network.SupportedRates[i] != 0) {
274 /* Bit rate given in 500 kb/s units */
275 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
277 current_val = iwe_stream_add_value(info, start, current_val,
278 stop, &iwe, IW_EV_PARAM_LEN);
280 /* Check if we added any event */
281 if ((current_val - start) > iwe_stream_lcp_len(info))
283 /* parsing WPA/WPA2 IE */
285 u8 buf[MAX_WPA_IE_LEN];
286 u8 wpa_ie[255], rsn_ie[255];
287 u16 wpa_len = 0, rsn_len = 0;
290 out_len = r8712_get_sec_ie(pnetwork->network.IEs,
292 IELength, rsn_ie, &rsn_len,
295 memset(buf, 0, MAX_WPA_IE_LEN);
296 n = sprintf(buf, "wpa_ie=");
297 for (i = 0; i < wpa_len; i++) {
298 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
300 if (n >= MAX_WPA_IE_LEN)
303 memset(&iwe, 0, sizeof(iwe));
304 iwe.cmd = IWEVCUSTOM;
305 iwe.u.data.length = (u16)strlen(buf);
306 start = iwe_stream_add_point(info, start, stop,
308 memset(&iwe, 0, sizeof(iwe));
310 iwe.u.data.length = (u16)wpa_len;
311 start = iwe_stream_add_point(info, start, stop,
315 memset(buf, 0, MAX_WPA_IE_LEN);
316 n = sprintf(buf, "rsn_ie=");
317 for (i = 0; i < rsn_len; i++) {
318 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
320 if (n >= MAX_WPA_IE_LEN)
323 memset(&iwe, 0, sizeof(iwe));
324 iwe.cmd = IWEVCUSTOM;
325 iwe.u.data.length = strlen(buf);
326 start = iwe_stream_add_point(info, start, stop,
328 memset(&iwe, 0, sizeof(iwe));
330 iwe.u.data.length = rsn_len;
331 start = iwe_stream_add_point(info, start, stop, &iwe,
336 { /* parsing WPS IE */
340 if (r8712_get_wps_ie(pnetwork->network.IEs,
341 pnetwork->network.IELength,
342 wps_ie, &wps_ielen) == true) {
345 iwe.u.data.length = (u16)wps_ielen;
346 start = iwe_stream_add_point(info, start, stop,
351 /* Add quality statistics */
353 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
354 /* we only update signal_level (signal strength) that is rssi. */
355 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
356 IW_QUAL_NOISE_INVALID);
357 iwe.u.qual.level = rssi; /* signal strength */
358 iwe.u.qual.qual = 0; /* signal quality */
359 iwe.u.qual.noise = 0; /* noise level */
360 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
361 /* how to translate rssi to ?% */
365 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
367 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
370 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
371 padapter->securitypriv.ndisencryptstatus =
372 Ndis802_11Encryption1Enabled;
373 padapter->securitypriv.ndisauthtype =
374 Ndis802_11AuthModeAutoSwitch;
375 padapter->securitypriv.AuthAlgrthm = 3;
376 } else if (value & AUTH_ALG_SHARED_KEY) {
377 padapter->securitypriv.ndisencryptstatus =
378 Ndis802_11Encryption1Enabled;
379 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
380 padapter->securitypriv.AuthAlgrthm = 1;
381 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
382 if (padapter->securitypriv.ndisauthtype <
383 Ndis802_11AuthModeWPAPSK) {
384 padapter->securitypriv.ndisauthtype =
385 Ndis802_11AuthModeOpen;
386 padapter->securitypriv.AuthAlgrthm = 0;
393 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
397 u32 wep_key_idx, wep_key_len = 0;
398 struct NDIS_802_11_WEP *pwep = NULL;
399 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
400 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
401 struct security_priv *psecuritypriv = &padapter->securitypriv;
403 param->u.crypt.err = 0;
404 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
405 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
406 param->u.crypt.key_len)
408 if (is_broadcast_ether_addr(param->sta_addr)) {
409 if (param->u.crypt.idx >= WEP_KEYS) {
410 /* for large key indices, set the default (0) */
411 param->u.crypt.idx = 0;
415 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
416 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
417 padapter->securitypriv.ndisencryptstatus =
418 Ndis802_11Encryption1Enabled;
419 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
420 padapter->securitypriv.XGrpPrivacy = _WEP40_;
421 wep_key_idx = param->u.crypt.idx;
422 wep_key_len = param->u.crypt.key_len;
423 if (wep_key_idx >= WEP_KEYS)
425 if (wep_key_len > 0) {
426 wep_key_len = wep_key_len <= 5 ? 5 : 13;
427 pwep = kmalloc((u32)(wep_key_len +
428 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial)),
432 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
433 pwep->KeyLength = wep_key_len;
434 pwep->Length = wep_key_len +
435 FIELD_OFFSET(struct NDIS_802_11_WEP,
437 if (wep_key_len == 13) {
438 padapter->securitypriv.PrivacyAlgrthm =
440 padapter->securitypriv.XGrpPrivacy =
445 pwep->KeyIndex = wep_key_idx;
446 pwep->KeyIndex |= 0x80000000;
447 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
448 if (param->u.crypt.set_tx) {
449 if (r8712_set_802_11_add_wep(padapter, pwep) ==
453 /* don't update "psecuritypriv->PrivacyAlgrthm" and
454 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
455 * r8712_set_key to fw/cam
457 if (wep_key_idx >= WEP_KEYS) {
461 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
462 skey[0]), pwep->KeyMaterial,
464 psecuritypriv->DefKeylen[wep_key_idx] =
466 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
470 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
471 struct sta_info *psta, *pbcmc_sta;
472 struct sta_priv *pstapriv = &padapter->stapriv;
474 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
475 WIFI_MP_STATE) == true) { /* sta mode */
476 psta = r8712_get_stainfo(pstapriv,
477 get_bssid(pmlmepriv));
479 psta->ieee8021x_blocked = false;
480 if ((padapter->securitypriv.ndisencryptstatus ==
481 Ndis802_11Encryption2Enabled) ||
482 (padapter->securitypriv.ndisencryptstatus ==
483 Ndis802_11Encryption3Enabled))
484 psta->XPrivacy = padapter->
485 securitypriv.PrivacyAlgrthm;
486 if (param->u.crypt.set_tx == 1)
487 handle_pairwise_key(psta, param,
490 handle_group_key(param, padapter);
492 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
494 pbcmc_sta->ieee8021x_blocked = false;
495 if ((padapter->securitypriv.ndisencryptstatus ==
496 Ndis802_11Encryption2Enabled) ||
497 (padapter->securitypriv.ndisencryptstatus ==
498 Ndis802_11Encryption3Enabled))
499 pbcmc_sta->XPrivacy =
500 padapter->securitypriv.
510 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
511 unsigned short ielen)
513 u8 *buf = NULL, *pos = NULL;
514 int group_cipher = 0, pairwise_cipher = 0;
517 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
520 buf = kmemdup(pie, ielen, GFP_ATOMIC);
524 if (ielen < RSN_HEADER_LEN) {
528 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
529 &pairwise_cipher) == _SUCCESS) {
530 padapter->securitypriv.AuthAlgrthm = 2;
531 padapter->securitypriv.ndisauthtype =
532 Ndis802_11AuthModeWPAPSK;
534 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
535 &pairwise_cipher) == _SUCCESS) {
536 padapter->securitypriv.AuthAlgrthm = 2;
537 padapter->securitypriv.ndisauthtype =
538 Ndis802_11AuthModeWPA2PSK;
540 switch (group_cipher) {
541 case WPA_CIPHER_NONE:
542 padapter->securitypriv.XGrpPrivacy =
544 padapter->securitypriv.ndisencryptstatus =
545 Ndis802_11EncryptionDisabled;
547 case WPA_CIPHER_WEP40:
548 padapter->securitypriv.XGrpPrivacy = _WEP40_;
549 padapter->securitypriv.ndisencryptstatus =
550 Ndis802_11Encryption1Enabled;
552 case WPA_CIPHER_TKIP:
553 padapter->securitypriv.XGrpPrivacy = _TKIP_;
554 padapter->securitypriv.ndisencryptstatus =
555 Ndis802_11Encryption2Enabled;
557 case WPA_CIPHER_CCMP:
558 padapter->securitypriv.XGrpPrivacy = _AES_;
559 padapter->securitypriv.ndisencryptstatus =
560 Ndis802_11Encryption3Enabled;
562 case WPA_CIPHER_WEP104:
563 padapter->securitypriv.XGrpPrivacy = _WEP104_;
564 padapter->securitypriv.ndisencryptstatus =
565 Ndis802_11Encryption1Enabled;
568 switch (pairwise_cipher) {
569 case WPA_CIPHER_NONE:
570 padapter->securitypriv.PrivacyAlgrthm =
572 padapter->securitypriv.ndisencryptstatus =
573 Ndis802_11EncryptionDisabled;
575 case WPA_CIPHER_WEP40:
576 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
577 padapter->securitypriv.ndisencryptstatus =
578 Ndis802_11Encryption1Enabled;
580 case WPA_CIPHER_TKIP:
581 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
582 padapter->securitypriv.ndisencryptstatus =
583 Ndis802_11Encryption2Enabled;
585 case WPA_CIPHER_CCMP:
586 padapter->securitypriv.PrivacyAlgrthm = _AES_;
587 padapter->securitypriv.ndisencryptstatus =
588 Ndis802_11Encryption3Enabled;
590 case WPA_CIPHER_WEP104:
591 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
592 padapter->securitypriv.ndisencryptstatus =
593 Ndis802_11Encryption1Enabled;
596 padapter->securitypriv.wps_phase = false;
599 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
601 while (cnt < ielen) {
604 if ((eid == _VENDOR_SPECIFIC_IE_) &&
605 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
606 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
607 padapter->securitypriv.wps_ie_len =
609 (MAX_WPA_IE_LEN << 2)) ?
611 (MAX_WPA_IE_LEN << 2);
612 memcpy(padapter->securitypriv.wps_ie,
614 padapter->securitypriv.wps_ie_len);
615 padapter->securitypriv.wps_phase =
617 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
621 cnt += buf[cnt + 1] + 2;
630 static int r8711_wx_get_name(struct net_device *dev,
631 struct iw_request_info *info,
632 union iwreq_data *wrqu, char *extra)
634 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
638 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
639 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
640 NDIS_802_11_RATES_EX *prates = NULL;
642 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
644 /* parsing HT_CAP_IE */
645 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
646 &ht_ielen, pcur_bss->IELength - 12);
647 if (p && ht_ielen > 0)
649 prates = &pcur_bss->SupportedRates;
650 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
652 snprintf(wrqu->name, IFNAMSIZ,
655 snprintf(wrqu->name, IFNAMSIZ,
657 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
659 snprintf(wrqu->name, IFNAMSIZ,
662 snprintf(wrqu->name, IFNAMSIZ,
666 snprintf(wrqu->name, IFNAMSIZ,
669 snprintf(wrqu->name, IFNAMSIZ,
673 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
677 static const long frequency_list[] = {
678 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
679 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
680 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
681 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
682 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
686 static int r8711_wx_set_freq(struct net_device *dev,
687 struct iw_request_info *info,
688 union iwreq_data *wrqu, char *extra)
690 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
691 struct iw_freq *fwrq = &wrqu->freq;
694 /* If setting by frequency, convert to a channel */
695 if ((fwrq->e == 1) &&
696 (fwrq->m >= (int) 2.412e8) &&
697 (fwrq->m <= (int) 2.487e8)) {
698 int f = fwrq->m / 100000;
700 while ((c < 14) && (f != frequency_list[c]))
705 /* Setting by channel number */
706 if ((fwrq->m > 14) || (fwrq->e > 0))
709 int channel = fwrq->m;
710 if ((channel < 1) || (channel > 14))
713 /* Yes ! We can set it !!! */
714 padapter->registrypriv.channel = channel;
720 static int r8711_wx_get_freq(struct net_device *dev,
721 struct iw_request_info *info,
722 union iwreq_data *wrqu, char *extra)
724 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
725 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
726 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
728 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
729 wrqu->freq.m = ieee80211_wlan_frequencies[
730 pcur_bss->Configuration.DSConfig-1] * 100000;
732 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
739 static int r8711_wx_set_mode(struct net_device *dev,
740 struct iw_request_info *a,
741 union iwreq_data *wrqu, char *b)
743 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
744 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
746 switch (wrqu->mode) {
748 networkType = Ndis802_11AutoUnknown;
751 networkType = Ndis802_11IBSS;
754 networkType = Ndis802_11APMode;
757 networkType = Ndis802_11Infrastructure;
762 if (Ndis802_11APMode == networkType)
763 r8712_setopmode_cmd(padapter, networkType);
765 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
767 r8712_set_802_11_infrastructure_mode(padapter, networkType);
771 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
772 union iwreq_data *wrqu, char *b)
774 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
775 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
777 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
778 wrqu->mode = IW_MODE_INFRA;
779 else if (check_fwstate(pmlmepriv,
780 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
781 wrqu->mode = IW_MODE_ADHOC;
782 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
783 wrqu->mode = IW_MODE_MASTER;
785 wrqu->mode = IW_MODE_AUTO;
789 static int r871x_wx_set_pmkid(struct net_device *dev,
790 struct iw_request_info *a,
791 union iwreq_data *wrqu, char *extra)
793 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
794 struct security_priv *psecuritypriv = &padapter->securitypriv;
795 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
796 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
797 u8 strIssueBssid[ETH_ALEN] = {0x00};
798 u8 j, blInserted = false;
799 int intReturn = false;
802 There are the BSSID information in the bssid.sa_data array.
803 If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
804 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
805 wpa_supplicant wants to add a PMKID/BSSID to driver.
806 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
807 remove a PMKID/BSSID from driver.
811 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
814 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
819 /* overwrite PMKID */
820 for (j = 0; j < NUM_PMKID_CACHE; j++) {
821 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
822 strIssueBssid, ETH_ALEN)) {
823 /* BSSID is matched, the same AP => rewrite
825 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
827 memcpy(psecuritypriv->PMKIDList[j].PMKID,
828 pPMK->pmkid, IW_PMKID_LEN);
829 psecuritypriv->PMKIDList[j].bUsed = true;
830 psecuritypriv->PMKIDIndex = j + 1;
836 /* Find a new entry */
837 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
838 __func__, psecuritypriv->PMKIDIndex);
839 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
840 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
841 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
842 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
843 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
845 psecuritypriv->PMKIDIndex++;
846 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
847 psecuritypriv->PMKIDIndex = 0;
850 case IW_PMKSA_REMOVE:
852 for (j = 0; j < NUM_PMKID_CACHE; j++) {
853 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
854 strIssueBssid, ETH_ALEN)) {
855 /* BSSID is matched, the same AP => Remove
856 * this PMKID information and reset it. */
857 memset(psecuritypriv->PMKIDList[j].Bssid,
859 psecuritypriv->PMKIDList[j].bUsed = false;
865 memset(psecuritypriv->PMKIDList, 0,
866 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
867 psecuritypriv->PMKIDIndex = 0;
871 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
878 static int r8711_wx_get_sens(struct net_device *dev,
879 struct iw_request_info *info,
880 union iwreq_data *wrqu, char *extra)
882 wrqu->sens.value = 0;
883 wrqu->sens.fixed = 0; /* no auto select */
884 wrqu->sens.disabled = 1;
888 static int r8711_wx_get_range(struct net_device *dev,
889 struct iw_request_info *info,
890 union iwreq_data *wrqu, char *extra)
892 struct iw_range *range = (struct iw_range *)extra;
896 wrqu->data.length = sizeof(*range);
897 memset(range, 0, sizeof(*range));
898 /* Let's try to keep this struct in the same order as in
899 * linux/include/wireless.h
902 /* TODO: See what values we can set, and remove the ones we can't
903 * set, or fill them with some default data.
905 /* ~5 Mb/s real (802.11b) */
906 range->throughput = 5 * 1000 * 1000;
907 /* TODO: 8711 sensitivity ? */
908 /* signal level threshold range */
909 /* percent values between 0 and 100. */
910 range->max_qual.qual = 100;
911 range->max_qual.level = 100;
912 range->max_qual.noise = 100;
913 range->max_qual.updated = 7; /* Updated all three */
914 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
915 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
916 range->avg_qual.level = 20 + -98;
917 range->avg_qual.noise = 0;
918 range->avg_qual.updated = 7; /* Updated all three */
919 range->num_bitrates = RATE_COUNT;
920 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
921 range->bitrate[i] = rtl8180_rates[i];
922 range->min_frag = MIN_FRAG_THRESHOLD;
923 range->max_frag = MAX_FRAG_THRESHOLD;
925 range->we_version_compiled = WIRELESS_EXT;
926 range->we_version_source = 16;
927 range->num_channels = 14;
928 for (i = 0, val = 0; i < 14; i++) {
929 /* Include only legal frequencies for some countries */
930 range->freq[val].i = i + 1;
931 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
932 range->freq[val].e = 1;
934 if (val == IW_MAX_FREQUENCIES)
937 range->num_frequency = val;
938 range->enc_capa = IW_ENC_CAPA_WPA |
940 IW_ENC_CAPA_CIPHER_TKIP |
941 IW_ENC_CAPA_CIPHER_CCMP;
945 static int r8711_wx_get_rate(struct net_device *dev,
946 struct iw_request_info *info,
947 union iwreq_data *wrqu, char *extra);
949 static int r871x_wx_set_priv(struct net_device *dev,
950 struct iw_request_info *info,
951 union iwreq_data *awrq,
954 int ret = 0, len = 0;
956 struct _adapter *padapter = netdev_priv(dev);
957 struct iw_point *dwrq = (struct iw_point *)awrq;
960 ext = memdup_user(dwrq->pointer, len);
964 if (0 == strcasecmp(ext, "RSSI")) {
965 /*Return received signal strength indicator in -db for */
968 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
969 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
971 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
972 sprintf(ext, "%s rssi %d",
973 pcur_network->network.Ssid.Ssid,
975 ((padapter->recvpriv.fw_rssi)>>1)-95
976 /*pcur_network->network.Rssi */
981 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
982 /*Return link speed in MBPS */
984 union iwreq_data wrqd;
988 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
992 mbps = wrqd.bitrate.value / 1000000;
993 sprintf(ext, "LINKSPEED %d", mbps);
994 } else if (0 == strcasecmp(ext, "MACADDR")) {
995 /*Return mac address of the station */
996 /* Macaddr = xx:xx:xx:xx:xx:xx */
997 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
998 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
999 /*Set scan type to active */
1000 /*OK if successful */
1001 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1002 pmlmepriv->passive_mode = 1;
1004 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1005 /*Set scan type to passive */
1006 /*OK if successful */
1007 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1008 pmlmepriv->passive_mode = 0;
1010 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1011 /*Set scan type to passive */
1012 /*OK if successful */
1013 r8712_disconnectCtrlEx_cmd(padapter
1014 , 1 /*u32 enableDrvCtrl */
1015 , 5 /*u32 tryPktCnt */
1016 , 100 /*u32 tryPktInterval */
1017 , 5000 /*u32 firstStageTO */
1020 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1021 /*Set scan type to passive */
1022 /*OK if successfu */
1023 r8712_disconnectCtrlEx_cmd(padapter
1024 , 0 /*u32 enableDrvCtrl */
1025 , 5 /*u32 tryPktCnt */
1026 , 100 /*u32 tryPktInterval */
1027 , 5000 /*u32 firstStageTO */
1031 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1035 if (copy_to_user(dwrq->pointer, ext,
1036 min(dwrq->length, (__u16)(strlen(ext)+1))))
1045 * s1. set_802_11_infrastructure_mode()
1046 * s2. set_802_11_authentication_mode()
1047 * s3. set_802_11_encryption_mode()
1048 * s4. set_802_11_bssid()
1050 * This function intends to handle the Set AP command, which specifies the
1051 * MAC# of a preferred Access Point.
1052 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1054 * For this operation to succeed, there is no need for the interface to be up.
1057 static int r8711_wx_set_wap(struct net_device *dev,
1058 struct iw_request_info *info,
1059 union iwreq_data *awrq,
1062 int ret = -EINPROGRESS;
1063 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1064 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1065 struct __queue *queue = &pmlmepriv->scanned_queue;
1066 struct sockaddr *temp = (struct sockaddr *)awrq;
1068 struct list_head *phead;
1070 struct wlan_network *pnetwork = NULL;
1071 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1073 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1075 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1077 if (temp->sa_family != ARPHRD_ETHER)
1079 authmode = padapter->securitypriv.ndisauthtype;
1080 spin_lock_irqsave(&queue->lock, irqL);
1081 phead = &queue->queue;
1082 pmlmepriv->pscanned = phead->next;
1084 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1086 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1087 struct wlan_network, list);
1088 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1089 dst_bssid = pnetwork->network.MacAddress;
1090 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1091 r8712_set_802_11_infrastructure_mode(padapter,
1092 pnetwork->network.InfrastructureMode);
1096 spin_unlock_irqrestore(&queue->lock, irqL);
1098 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1101 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1108 static int r8711_wx_get_wap(struct net_device *dev,
1109 struct iw_request_info *info,
1110 union iwreq_data *wrqu, char *extra)
1112 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1113 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1114 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1116 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1117 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1119 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1121 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1125 static int r871x_wx_set_mlme(struct net_device *dev,
1126 struct iw_request_info *info,
1127 union iwreq_data *wrqu, char *extra)
1131 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1132 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1136 reason = cpu_to_le16(mlme->reason_code);
1137 switch (mlme->cmd) {
1138 case IW_MLME_DEAUTH:
1139 if (!r8712_set_802_11_disassociate(padapter))
1142 case IW_MLME_DISASSOC:
1143 if (!r8712_set_802_11_disassociate(padapter))
1154 * This function intends to handle the Set Scan command.
1155 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1157 * For this operation to succeed, the interface is brought Up beforehand.
1160 static int r8711_wx_set_scan(struct net_device *dev,
1161 struct iw_request_info *a,
1162 union iwreq_data *wrqu, char *extra)
1164 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1165 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1168 if (padapter->bDriverStopped == true) {
1169 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1170 __func__, padapter->bDriverStopped);
1173 if (padapter->bup == false)
1175 if (padapter->hw_init_completed == false)
1177 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1178 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1180 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1181 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1182 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1183 struct ndis_802_11_ssid ssid;
1185 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1186 memset((unsigned char *)&ssid, 0,
1187 sizeof(struct ndis_802_11_ssid));
1188 memcpy(ssid.Ssid, req->essid, len);
1189 ssid.SsidLength = len;
1190 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1191 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1192 _FW_UNDER_LINKING)) ||
1193 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1194 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1197 status = r8712_sitesurvey_cmd(padapter, &ssid);
1198 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1201 status = r8712_set_802_11_bssid_list_scan(padapter);
1202 if (status == false)
1207 static int r8711_wx_get_scan(struct net_device *dev,
1208 struct iw_request_info *a,
1209 union iwreq_data *wrqu, char *extra)
1211 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1212 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1213 struct __queue *queue = &pmlmepriv->scanned_queue;
1214 struct wlan_network *pnetwork = NULL;
1216 struct list_head *plist, *phead;
1218 char *stop = ev + wrqu->data.length;
1219 u32 ret = 0, cnt = 0;
1221 if (padapter->bDriverStopped)
1223 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1229 spin_lock_irqsave(&queue->lock, irqL);
1230 phead = &queue->queue;
1231 plist = phead->next;
1233 if (end_of_queue_search(phead, plist) == true)
1235 if ((stop - ev) < SCAN_ITEM_SIZE) {
1239 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1240 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1241 plist = plist->next;
1243 spin_unlock_irqrestore(&queue->lock, irqL);
1244 wrqu->data.length = ev - extra;
1245 wrqu->data.flags = 0;
1250 * s1. set_802_11_infrastructure_mode()
1251 * s2. set_802_11_authenticaion_mode()
1252 * s3. set_802_11_encryption_mode()
1253 * s4. set_802_11_ssid()
1255 * This function intends to handle the Set ESSID command.
1256 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1258 * For this operation to succeed, there is no need for the interface to be Up.
1261 static int r8711_wx_set_essid(struct net_device *dev,
1262 struct iw_request_info *a,
1263 union iwreq_data *wrqu, char *extra)
1265 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1266 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1267 struct __queue *queue = &pmlmepriv->scanned_queue;
1268 struct wlan_network *pnetwork = NULL;
1269 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1270 struct ndis_802_11_ssid ndis_ssid;
1271 u8 *dst_ssid, *src_ssid;
1272 struct list_head *phead;
1275 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1277 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1279 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1281 authmode = padapter->securitypriv.ndisauthtype;
1282 if (wrqu->essid.flags && wrqu->essid.length) {
1283 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1284 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1285 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1286 ndis_ssid.SsidLength = len;
1287 memcpy(ndis_ssid.Ssid, extra, len);
1288 src_ssid = ndis_ssid.Ssid;
1289 phead = &queue->queue;
1290 pmlmepriv->pscanned = phead->next;
1292 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1294 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1295 struct wlan_network, list);
1296 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1297 dst_ssid = pnetwork->network.Ssid.Ssid;
1298 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1299 && (pnetwork->network.Ssid.SsidLength ==
1300 ndis_ssid.SsidLength)) {
1301 if (check_fwstate(pmlmepriv,
1302 WIFI_ADHOC_STATE)) {
1303 if (pnetwork->network.
1307 cur_network.network.
1312 r8712_set_802_11_infrastructure_mode(
1314 pnetwork->network.InfrastructureMode);
1318 r8712_set_802_11_authentication_mode(padapter, authmode);
1319 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1321 return -EINPROGRESS;
1324 static int r8711_wx_get_essid(struct net_device *dev,
1325 struct iw_request_info *a,
1326 union iwreq_data *wrqu, char *extra)
1328 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1329 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1330 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1333 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1334 len = pcur_bss->Ssid.SsidLength;
1335 wrqu->essid.length = len;
1336 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1337 wrqu->essid.flags = 1;
1344 static int r8711_wx_set_rate(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 u32 target_rate = wrqu->bitrate.value;
1350 u32 fixed = wrqu->bitrate.fixed;
1352 u8 datarates[NumRates];
1353 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1356 if (target_rate == -1) {
1360 target_rate = target_rate / 100000;
1361 switch (target_rate) {
1403 for (i = 0; i < NumRates; i++) {
1404 if (ratevalue == mpdatarate[i]) {
1405 datarates[i] = mpdatarate[i];
1409 datarates[i] = 0xff;
1411 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1416 static int r8711_wx_get_rate(struct net_device *dev,
1417 struct iw_request_info *info,
1418 union iwreq_data *wrqu, char *extra)
1420 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1421 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1422 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1423 struct ieee80211_ht_cap *pht_capie;
1424 unsigned char rf_type = padapter->registrypriv.rf_config;
1427 u16 rate, max_rate = 0, ht_cap = false;
1429 u8 bw_40MHz = 0, short_GI = 0;
1433 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1434 p = r8712_get_ie(&pcur_bss->IEs[12],
1435 _HT_CAPABILITY_IE_, &ht_ielen,
1436 pcur_bss->IELength - 12);
1437 if (p && ht_ielen > 0) {
1439 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1440 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1441 bw_40MHz = (pht_capie->cap_info &
1442 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1443 short_GI = (pht_capie->cap_info &
1444 (IEEE80211_HT_CAP_SGI_20 |
1445 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1447 while ((pcur_bss->SupportedRates[i] != 0) &&
1448 (pcur_bss->SupportedRates[i] != 0xFF)) {
1449 rate = pcur_bss->SupportedRates[i] & 0x7F;
1450 if (rate > max_rate)
1452 wrqu->bitrate.fixed = 0; /* no auto select */
1453 wrqu->bitrate.value = rate*500000;
1456 if (ht_cap == true) {
1457 if (mcs_rate & 0x8000 /* MCS15 */
1459 RTL8712_RF_2T2R == rf_type)
1460 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1461 270) : ((short_GI) ? 144 : 130);
1462 else /* default MCS7 */
1463 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1464 135) : ((short_GI) ? 72 : 65);
1465 max_rate *= 2; /* Mbps/2 */
1467 wrqu->bitrate.value = max_rate * 500000;
1473 static int r8711_wx_get_rts(struct net_device *dev,
1474 struct iw_request_info *info,
1475 union iwreq_data *wrqu, char *extra)
1477 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1479 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1480 wrqu->rts.fixed = 0; /* no auto select */
1484 static int r8711_wx_set_frag(struct net_device *dev,
1485 struct iw_request_info *info,
1486 union iwreq_data *wrqu, char *extra)
1488 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1490 if (wrqu->frag.disabled)
1491 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1493 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1494 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1496 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1501 static int r8711_wx_get_frag(struct net_device *dev,
1502 struct iw_request_info *info,
1503 union iwreq_data *wrqu, char *extra)
1505 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1507 wrqu->frag.value = padapter->xmitpriv.frag_len;
1508 wrqu->frag.fixed = 0; /* no auto select */
1512 static int r8711_wx_get_retry(struct net_device *dev,
1513 struct iw_request_info *info,
1514 union iwreq_data *wrqu, char *extra)
1516 wrqu->retry.value = 7;
1517 wrqu->retry.fixed = 0; /* no auto select */
1518 wrqu->retry.disabled = 1;
1522 static int r8711_wx_set_enc(struct net_device *dev,
1523 struct iw_request_info *info,
1524 union iwreq_data *wrqu, char *keybuf)
1527 u32 keyindex_provided;
1528 struct NDIS_802_11_WEP wep;
1529 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1530 struct iw_point *erq = &(wrqu->encoding);
1531 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1533 key = erq->flags & IW_ENCODE_INDEX;
1534 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1535 if (erq->flags & IW_ENCODE_DISABLED) {
1536 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1537 padapter->securitypriv.ndisencryptstatus =
1538 Ndis802_11EncryptionDisabled;
1539 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1540 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1541 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1542 authmode = Ndis802_11AuthModeOpen;
1543 padapter->securitypriv.ndisauthtype = authmode;
1550 keyindex_provided = 1;
1552 keyindex_provided = 0;
1553 key = padapter->securitypriv.PrivacyKeyIndex;
1555 /* set authentication mode */
1556 if (erq->flags & IW_ENCODE_OPEN) {
1557 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1558 padapter->securitypriv.ndisencryptstatus =
1559 Ndis802_11Encryption1Enabled;
1560 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1561 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1562 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1563 authmode = Ndis802_11AuthModeOpen;
1564 padapter->securitypriv.ndisauthtype = authmode;
1565 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1566 netdev_info(dev, "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1567 padapter->securitypriv.ndisencryptstatus =
1568 Ndis802_11Encryption1Enabled;
1569 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1570 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1571 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1572 authmode = Ndis802_11AuthModeShared;
1573 padapter->securitypriv.ndisauthtype = authmode;
1575 padapter->securitypriv.ndisencryptstatus =
1576 Ndis802_11Encryption1Enabled;
1577 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1578 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1579 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1580 authmode = Ndis802_11AuthModeOpen;
1581 padapter->securitypriv.ndisauthtype = authmode;
1584 if (erq->length > 0) {
1585 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1586 wep.Length = wep.KeyLength +
1587 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1590 if (keyindex_provided == 1) { /* set key_id only, no given
1591 * KeyMaterial(erq->length==0).*/
1592 padapter->securitypriv.PrivacyKeyIndex = key;
1593 switch (padapter->securitypriv.DefKeylen[key]) {
1595 padapter->securitypriv.PrivacyAlgrthm =
1599 padapter->securitypriv.PrivacyAlgrthm =
1603 padapter->securitypriv.PrivacyAlgrthm =
1610 wep.KeyIndex |= 0x80000000; /* transmit key */
1611 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1612 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1617 static int r8711_wx_get_enc(struct net_device *dev,
1618 struct iw_request_info *info,
1619 union iwreq_data *wrqu, char *keybuf)
1622 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1623 struct iw_point *erq = &(wrqu->encoding);
1624 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1626 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1627 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1629 erq->flags |= IW_ENCODE_DISABLED;
1633 key = erq->flags & IW_ENCODE_INDEX;
1639 key = padapter->securitypriv.PrivacyKeyIndex;
1641 erq->flags = key + 1;
1642 switch (padapter->securitypriv.ndisencryptstatus) {
1643 case Ndis802_11EncryptionNotSupported:
1644 case Ndis802_11EncryptionDisabled:
1646 erq->flags |= IW_ENCODE_DISABLED;
1648 case Ndis802_11Encryption1Enabled:
1649 erq->length = padapter->securitypriv.DefKeylen[key];
1651 memcpy(keybuf, padapter->securitypriv.DefKey[
1652 key].skey, padapter->securitypriv.
1654 erq->flags |= IW_ENCODE_ENABLED;
1655 if (padapter->securitypriv.ndisauthtype ==
1656 Ndis802_11AuthModeOpen)
1657 erq->flags |= IW_ENCODE_OPEN;
1658 else if (padapter->securitypriv.ndisauthtype ==
1659 Ndis802_11AuthModeShared)
1660 erq->flags |= IW_ENCODE_RESTRICTED;
1663 erq->flags |= IW_ENCODE_DISABLED;
1666 case Ndis802_11Encryption2Enabled:
1667 case Ndis802_11Encryption3Enabled:
1669 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1674 erq->flags |= IW_ENCODE_DISABLED;
1680 static int r8711_wx_get_power(struct net_device *dev,
1681 struct iw_request_info *info,
1682 union iwreq_data *wrqu, char *extra)
1684 wrqu->power.value = 0;
1685 wrqu->power.fixed = 0; /* no auto select */
1686 wrqu->power.disabled = 1;
1690 static int r871x_wx_set_gen_ie(struct net_device *dev,
1691 struct iw_request_info *info,
1692 union iwreq_data *wrqu, char *extra)
1694 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1696 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1699 static int r871x_wx_set_auth(struct net_device *dev,
1700 struct iw_request_info *info,
1701 union iwreq_data *wrqu, char *extra)
1703 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1704 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1709 paramid = param->flags & IW_AUTH_INDEX;
1710 paramval = param->value;
1712 case IW_AUTH_WPA_VERSION:
1714 case IW_AUTH_CIPHER_PAIRWISE:
1716 case IW_AUTH_CIPHER_GROUP:
1718 case IW_AUTH_KEY_MGMT:
1720 * ??? does not use these parameters
1723 case IW_AUTH_TKIP_COUNTERMEASURES:
1725 /* wpa_supplicant is enabling tkip countermeasure. */
1726 padapter->securitypriv.btkip_countermeasure = true;
1728 /* wpa_supplicant is disabling tkip countermeasure. */
1729 padapter->securitypriv.btkip_countermeasure = false;
1732 case IW_AUTH_DROP_UNENCRYPTED:
1735 * wpa_supplicant calls set_wpa_enabled when the driver
1736 * is loaded and unloaded, regardless of if WPA is being
1737 * used. No other calls are made which can be used to
1738 * determine if encryption will be used or not prior to
1739 * association being expected. If encryption is not being
1740 * used, drop_unencrypted is set to false, else true -- we
1741 * can use this to determine if the CAP_PRIVACY_ON bit should
1744 if (padapter->securitypriv.ndisencryptstatus ==
1745 Ndis802_11Encryption1Enabled) {
1746 /* it means init value, or using wep,
1747 * ndisencryptstatus =
1748 * Ndis802_11Encryption1Enabled,
1749 * then it needn't reset it;
1755 padapter->securitypriv.ndisencryptstatus =
1756 Ndis802_11EncryptionDisabled;
1757 padapter->securitypriv.PrivacyAlgrthm =
1759 padapter->securitypriv.XGrpPrivacy =
1761 padapter->securitypriv.AuthAlgrthm = 0;
1762 padapter->securitypriv.ndisauthtype =
1763 Ndis802_11AuthModeOpen;
1766 case IW_AUTH_80211_AUTH_ALG:
1767 ret = wpa_set_auth_algs(dev, (u32)paramval);
1769 case IW_AUTH_WPA_ENABLED:
1771 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1773 case IW_AUTH_PRIVACY_INVOKED:
1782 static int r871x_wx_set_enc_ext(struct net_device *dev,
1783 struct iw_request_info *info,
1784 union iwreq_data *wrqu, char *extra)
1786 struct iw_point *pencoding = &wrqu->encoding;
1787 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1788 struct ieee_param *param = NULL;
1793 switch (pext->alg) {
1794 case IW_ENCODE_ALG_NONE:
1797 case IW_ENCODE_ALG_WEP:
1800 case IW_ENCODE_ALG_TKIP:
1803 case IW_ENCODE_ALG_CCMP:
1810 param_len = sizeof(struct ieee_param) + pext->key_len;
1811 param = kzalloc(param_len, GFP_ATOMIC);
1814 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1815 memset(param->sta_addr, 0xff, ETH_ALEN);
1817 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1818 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1819 param->u.crypt.set_tx = 0;
1820 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1821 param->u.crypt.set_tx = 1;
1822 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1823 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1824 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1825 if (pext->key_len) {
1826 param->u.crypt.key_len = pext->key_len;
1827 memcpy(param + 1, pext + 1, pext->key_len);
1829 ret = wpa_set_encryption(dev, param, param_len);
1834 static int r871x_wx_get_nick(struct net_device *dev,
1835 struct iw_request_info *info,
1836 union iwreq_data *wrqu, char *extra)
1839 wrqu->data.length = 8;
1840 wrqu->data.flags = 1;
1841 memcpy(extra, "rtl_wifi", 8);
1846 static int r8711_wx_read32(struct net_device *dev,
1847 struct iw_request_info *info,
1848 union iwreq_data *wrqu, char *keybuf)
1850 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1854 get_user(addr, (u32 __user *)wrqu->data.pointer);
1855 data32 = r8712_read32(padapter, addr);
1856 put_user(data32, (u32 __user *)wrqu->data.pointer);
1857 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1858 wrqu->data.flags = data32 & 0xffff;
1859 get_user(addr, (u32 __user *)wrqu->data.pointer);
1863 static int r8711_wx_write32(struct net_device *dev,
1864 struct iw_request_info *info,
1865 union iwreq_data *wrqu, char *keybuf)
1867 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1871 get_user(addr, (u32 __user *)wrqu->data.pointer);
1872 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
1873 r8712_write32(padapter, addr, data32);
1877 static int dummy(struct net_device *dev,
1878 struct iw_request_info *a,
1879 union iwreq_data *wrqu, char *b)
1884 static int r8711_drvext_hdl(struct net_device *dev,
1885 struct iw_request_info *info,
1886 union iwreq_data *wrqu, char *extra)
1891 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1892 struct iw_request_info *info,
1893 union iwreq_data *wrqu, char *extra)
1895 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1896 struct iw_point *p = &wrqu->data;
1897 struct oid_par_priv oid_par;
1898 struct mp_ioctl_handler *phandler;
1899 struct mp_ioctl_param *poidparam;
1900 unsigned long BytesRead, BytesWritten, BytesNeeded;
1901 u8 *pparmbuf = NULL, bset;
1906 if ((!p->length) || (!p->pointer)) {
1908 goto _r871x_mp_ioctl_hdl_exit;
1910 bset = (u8)(p->flags & 0xFFFF);
1913 pparmbuf = kmalloc(len, GFP_ATOMIC);
1914 if (pparmbuf == NULL) {
1916 goto _r871x_mp_ioctl_hdl_exit;
1918 if (copy_from_user(pparmbuf, p->pointer, len)) {
1920 goto _r871x_mp_ioctl_hdl_exit;
1922 poidparam = (struct mp_ioctl_param *)pparmbuf;
1923 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1925 goto _r871x_mp_ioctl_hdl_exit;
1927 phandler = mp_ioctl_hdl + poidparam->subcode;
1928 if ((phandler->paramsize != 0) &&
1929 (poidparam->len < phandler->paramsize)) {
1931 goto _r871x_mp_ioctl_hdl_exit;
1933 if (phandler->oid == 0 && phandler->handler)
1934 status = phandler->handler(&oid_par);
1935 else if (phandler->handler) {
1936 oid_par.adapter_context = padapter;
1937 oid_par.oid = phandler->oid;
1938 oid_par.information_buf = poidparam->data;
1939 oid_par.information_buf_len = poidparam->len;
1944 oid_par.bytes_rw = &BytesRead;
1945 oid_par.bytes_needed = &BytesNeeded;
1946 oid_par.type_of_oid = SET_OID;
1948 oid_par.bytes_rw = &BytesWritten;
1949 oid_par.bytes_needed = &BytesNeeded;
1950 oid_par.type_of_oid = QUERY_OID;
1952 status = phandler->handler(&oid_par);
1953 /* todo:check status, BytesNeeded, etc. */
1955 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1956 __func__, poidparam->subcode, phandler->oid,
1959 goto _r871x_mp_ioctl_hdl_exit;
1961 if (bset == 0x00) { /* query info */
1962 if (copy_to_user(p->pointer, pparmbuf, len))
1967 goto _r871x_mp_ioctl_hdl_exit;
1969 _r871x_mp_ioctl_hdl_exit:
1974 static int r871x_get_ap_info(struct net_device *dev,
1975 struct iw_request_info *info,
1976 union iwreq_data *wrqu, char *extra)
1978 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1979 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1980 struct __queue *queue = &pmlmepriv->scanned_queue;
1981 struct iw_point *pdata = &wrqu->data;
1982 struct wlan_network *pnetwork = NULL;
1983 u32 cnt = 0, wpa_ielen;
1985 struct list_head *plist, *phead;
1986 unsigned char *pbuf;
1990 if (padapter->bDriverStopped || (pdata == NULL))
1992 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1999 if (pdata->length >= 32) {
2000 if (copy_from_user(data, pdata->pointer, 32))
2004 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2005 phead = &queue->queue;
2006 plist = phead->next;
2008 if (end_of_queue_search(phead, plist) == true)
2010 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2011 if (hwaddr_aton_i(data, bssid)) {
2012 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
2014 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2018 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
2019 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2020 /* BSSID match, then check if supporting wpa/wpa2 */
2021 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2022 &wpa_ielen, pnetwork->network.IELength-12);
2023 if (pbuf && (wpa_ielen > 0)) {
2027 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2028 &wpa_ielen, pnetwork->network.IELength-12);
2029 if (pbuf && (wpa_ielen > 0)) {
2034 plist = plist->next;
2036 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2037 if (pdata->length >= 34) {
2038 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2039 (u8 *)&pdata->flags, 1))
2045 static int r871x_set_pid(struct net_device *dev,
2046 struct iw_request_info *info,
2047 union iwreq_data *wrqu, char *extra)
2049 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2050 struct iw_point *pdata = &wrqu->data;
2052 if ((padapter->bDriverStopped) || (pdata == NULL))
2054 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2059 static int r871x_set_chplan(struct net_device *dev,
2060 struct iw_request_info *info,
2061 union iwreq_data *wrqu, char *extra)
2064 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2065 struct iw_point *pdata = &wrqu->data;
2068 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2072 ch_plan = (int)*extra;
2073 r8712_set_chplan_cmd(padapter, ch_plan);
2080 static int r871x_wps_start(struct net_device *dev,
2081 struct iw_request_info *info,
2082 union iwreq_data *wrqu, char *extra)
2084 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2085 struct iw_point *pdata = &wrqu->data;
2086 u32 u32wps_start = 0;
2088 if ((padapter->bDriverStopped) || (pdata == NULL))
2090 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2092 if (u32wps_start == 0)
2093 u32wps_start = *extra;
2094 if (u32wps_start == 1) /* WPS Start */
2095 padapter->ledpriv.LedControlHandler(padapter,
2097 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2098 padapter->ledpriv.LedControlHandler(padapter,
2100 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2101 padapter->ledpriv.LedControlHandler(padapter,
2102 LED_CTL_STOP_WPS_FAIL);
2106 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2108 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2111 case IEEE_PARAM_WPA_ENABLED:
2112 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2113 switch ((value)&0xff) {
2115 padapter->securitypriv.ndisauthtype =
2116 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2117 padapter->securitypriv.ndisencryptstatus =
2118 Ndis802_11Encryption2Enabled;
2121 padapter->securitypriv.ndisauthtype =
2122 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2123 padapter->securitypriv.ndisencryptstatus =
2124 Ndis802_11Encryption3Enabled;
2128 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2130 case IEEE_PARAM_DROP_UNENCRYPTED:
2133 * wpa_supplicant calls set_wpa_enabled when the driver
2134 * is loaded and unloaded, regardless of if WPA is being
2135 * used. No other calls are made which can be used to
2136 * determine if encryption will be used or not prior to
2137 * association being expected. If encryption is not being
2138 * used, drop_unencrypted is set to false, else true -- we
2139 * can use this to determine if the CAP_PRIVACY_ON bit should
2143 case IEEE_PARAM_PRIVACY_INVOKED:
2145 case IEEE_PARAM_AUTH_ALGS:
2146 return wpa_set_auth_algs(dev, value);
2148 case IEEE_PARAM_IEEE_802_1X:
2150 case IEEE_PARAM_WPAX_SELECT:
2151 /* added for WPA2 mixed mode */
2159 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2161 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2164 case IEEE_MLME_STA_DEAUTH:
2165 if (!r8712_set_802_11_disassociate(padapter))
2168 case IEEE_MLME_STA_DISASSOC:
2169 if (!r8712_set_802_11_disassociate(padapter))
2178 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2180 struct ieee_param *param;
2182 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2184 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2186 param = memdup_user(p->pointer, p->length);
2188 return PTR_ERR(param);
2189 switch (param->cmd) {
2190 case IEEE_CMD_SET_WPA_PARAM:
2191 ret = wpa_set_param(dev, param->u.wpa_param.name,
2192 param->u.wpa_param.value);
2194 case IEEE_CMD_SET_WPA_IE:
2195 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2196 (u16)param->u.wpa_ie.len);
2198 case IEEE_CMD_SET_ENCRYPTION:
2199 ret = wpa_set_encryption(dev, param, p->length);
2202 ret = wpa_mlme(dev, param->u.mlme.command,
2203 param->u.mlme.reason_code);
2209 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2215 /* based on "driver_ipw" and for hostapd */
2216 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2218 struct iwreq *wrq = (struct iwreq *)rq;
2221 case RTL_IOCTL_WPA_SUPPLICANT:
2222 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2229 static iw_handler r8711_handlers[] = {
2230 NULL, /* SIOCSIWCOMMIT */
2231 r8711_wx_get_name, /* SIOCGIWNAME */
2232 dummy, /* SIOCSIWNWID */
2233 dummy, /* SIOCGIWNWID */
2234 r8711_wx_set_freq, /* SIOCSIWFREQ */
2235 r8711_wx_get_freq, /* SIOCGIWFREQ */
2236 r8711_wx_set_mode, /* SIOCSIWMODE */
2237 r8711_wx_get_mode, /* SIOCGIWMODE */
2238 dummy, /* SIOCSIWSENS */
2239 r8711_wx_get_sens, /* SIOCGIWSENS */
2240 NULL, /* SIOCSIWRANGE */
2241 r8711_wx_get_range, /* SIOCGIWRANGE */
2242 r871x_wx_set_priv, /* SIOCSIWPRIV */
2243 NULL, /* SIOCGIWPRIV */
2244 NULL, /* SIOCSIWSTATS */
2245 NULL, /* SIOCGIWSTATS */
2246 dummy, /* SIOCSIWSPY */
2247 dummy, /* SIOCGIWSPY */
2248 NULL, /* SIOCGIWTHRSPY */
2249 NULL, /* SIOCWIWTHRSPY */
2250 r8711_wx_set_wap, /* SIOCSIWAP */
2251 r8711_wx_get_wap, /* SIOCGIWAP */
2252 r871x_wx_set_mlme, /* request MLME operation;
2253 * uses struct iw_mlme */
2254 dummy, /* SIOCGIWAPLIST -- deprecated */
2255 r8711_wx_set_scan, /* SIOCSIWSCAN */
2256 r8711_wx_get_scan, /* SIOCGIWSCAN */
2257 r8711_wx_set_essid, /* SIOCSIWESSID */
2258 r8711_wx_get_essid, /* SIOCGIWESSID */
2259 dummy, /* SIOCSIWNICKN */
2260 r871x_wx_get_nick, /* SIOCGIWNICKN */
2261 NULL, /* -- hole -- */
2262 NULL, /* -- hole -- */
2263 r8711_wx_set_rate, /* SIOCSIWRATE */
2264 r8711_wx_get_rate, /* SIOCGIWRATE */
2265 dummy, /* SIOCSIWRTS */
2266 r8711_wx_get_rts, /* SIOCGIWRTS */
2267 r8711_wx_set_frag, /* SIOCSIWFRAG */
2268 r8711_wx_get_frag, /* SIOCGIWFRAG */
2269 dummy, /* SIOCSIWTXPOW */
2270 dummy, /* SIOCGIWTXPOW */
2271 dummy, /* SIOCSIWRETRY */
2272 r8711_wx_get_retry, /* SIOCGIWRETRY */
2273 r8711_wx_set_enc, /* SIOCSIWENCODE */
2274 r8711_wx_get_enc, /* SIOCGIWENCODE */
2275 dummy, /* SIOCSIWPOWER */
2276 r8711_wx_get_power, /* SIOCGIWPOWER */
2277 NULL, /*---hole---*/
2278 NULL, /*---hole---*/
2279 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2280 NULL, /* SIOCGIWGENIE */
2281 r871x_wx_set_auth, /* SIOCSIWAUTH */
2282 NULL, /* SIOCGIWAUTH */
2283 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2284 NULL, /* SIOCGIWENCODEEXT */
2285 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2286 NULL, /*---hole---*/
2289 static const struct iw_priv_args r8711_private_args[] = {
2291 SIOCIWFIRSTPRIV + 0x0,
2292 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2295 SIOCIWFIRSTPRIV + 0x1,
2296 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2299 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2302 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2305 SIOCIWFIRSTPRIV + 0x4,
2306 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2309 SIOCIWFIRSTPRIV + 0x5,
2310 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2313 SIOCIWFIRSTPRIV + 0x6,
2314 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2317 SIOCIWFIRSTPRIV + 0x7,
2318 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2322 static iw_handler r8711_private_handler[] = {
2327 r871x_get_ap_info, /*for MM DTV platform*/
2333 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2335 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2336 struct iw_statistics *piwstats = &padapter->iwstats;
2341 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2342 piwstats->qual.qual = 0;
2343 piwstats->qual.level = 0;
2344 piwstats->qual.noise = 0;
2346 /* show percentage, we need transfer dbm to orignal value. */
2347 tmp_level = padapter->recvpriv.fw_rssi;
2348 tmp_qual = padapter->recvpriv.signal;
2349 tmp_noise = padapter->recvpriv.noise;
2350 piwstats->qual.level = tmp_level;
2351 piwstats->qual.qual = tmp_qual;
2352 piwstats->qual.noise = tmp_noise;
2354 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2355 return &padapter->iwstats;
2358 struct iw_handler_def r871x_handlers_def = {
2359 .standard = r8711_handlers,
2360 .num_standard = ARRAY_SIZE(r8711_handlers),
2361 .private = r8711_private_handler,
2362 .private_args = (struct iw_priv_args *)r8711_private_args,
2363 .num_private = ARRAY_SIZE(r8711_private_handler),
2364 .num_private_args = sizeof(r8711_private_args) /
2365 sizeof(struct iw_priv_args),
2366 .get_wireless_stats = r871x_get_wireless_stats