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>
49 #include <linux/etherdevice.h>
52 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
54 #define SCAN_ITEM_SIZE 768
55 #define MAX_CUSTOM_LEN 64
59 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
60 6000000, 9000000, 12000000, 18000000,
61 24000000, 36000000, 48000000, 54000000};
63 static const long ieee80211_wlan_frequencies[] = {
64 2412, 2417, 2422, 2427,
65 2432, 2437, 2442, 2447,
66 2452, 2457, 2462, 2467,
70 static const char * const iw_operation_mode[] = {
71 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
75 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
77 union iwreq_data wrqu;
78 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
80 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
81 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
83 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
86 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
88 union iwreq_data wrqu;
90 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
91 eth_zero_addr(wrqu.ap_addr.sa_data);
92 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
95 static inline void handle_pairwise_key(struct sta_info *psta,
96 struct ieee_param *param,
97 struct _adapter *padapter)
100 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
101 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
102 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
103 memcpy(psta->tkiptxmickey. skey,
104 &(param->u.crypt.key[16]), 8);
105 memcpy(psta->tkiprxmickey. skey,
106 &(param->u.crypt.key[24]), 8);
107 padapter->securitypriv. busetkipkey = false;
108 mod_timer(&padapter->securitypriv.tkip_timer,
109 jiffies + msecs_to_jiffies(50));
111 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
114 static inline void handle_group_key(struct ieee_param *param,
115 struct _adapter *padapter)
117 if (param->u.crypt.idx > 0 &&
118 param->u.crypt.idx < 3) {
119 /* group key idx is 1 or 2 */
120 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
121 idx - 1].skey, param->u.crypt.key,
122 (param->u.crypt.key_len > 16 ? 16 :
123 param->u.crypt.key_len));
124 memcpy(padapter->securitypriv.XGrptxmickey[param->
125 u.crypt.idx - 1].skey, &(param->u.crypt.key[16]), 8);
126 memcpy(padapter->securitypriv. XGrprxmickey[param->
127 u.crypt.idx - 1].skey, &(param->u.crypt.key[24]), 8);
128 padapter->securitypriv.binstallGrpkey = true;
129 r8712_set_key(padapter, &padapter->securitypriv,
131 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
132 if (padapter->registrypriv.power_mgnt != padapter->
133 pwrctrlpriv.pwr_mode)
134 mod_timer(&padapter->mlmepriv.dhcp_timer,
135 jiffies + msecs_to_jiffies(60000));
140 static noinline_for_stack char *translate_scan(struct _adapter *padapter,
141 struct iw_request_info *info,
142 struct wlan_network *pnetwork,
143 char *start, char *stop)
146 struct ieee80211_ht_cap *pht_capie;
149 u32 i = 0, ht_ielen = 0;
150 u16 cap, ht_cap = false, mcs_rate;
153 if ((pnetwork->network.Configuration.DSConfig < 1) ||
154 (pnetwork->network.Configuration.DSConfig > 14)) {
155 if (pnetwork->network.Configuration.DSConfig < 1)
156 pnetwork->network.Configuration.DSConfig = 1;
158 pnetwork->network.Configuration.DSConfig = 14;
162 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
163 ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
164 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
166 iwe.cmd = SIOCGIWESSID;
167 iwe.u.data.flags = 1;
168 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
169 start = iwe_stream_add_point(info, start, stop, &iwe,
170 pnetwork->network.Ssid.Ssid);
171 /* parsing HT_CAP_IE */
172 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
173 &ht_ielen, pnetwork->network.IELength - 12);
174 if (p && ht_ielen > 0) {
176 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
177 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
179 /* Add the protocol name */
180 iwe.cmd = SIOCGIWNAME;
181 if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
183 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
185 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
186 } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
188 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
190 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
193 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
195 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
197 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
199 iwe.cmd = SIOCGIWMODE;
200 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
203 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
204 if (cap & WLAN_CAPABILITY_BSS)
205 iwe.u.mode = (u32)IW_MODE_MASTER;
207 iwe.u.mode = (u32)IW_MODE_ADHOC;
208 start = iwe_stream_add_event(info, start, stop, &iwe,
211 /* Add frequency/channel */
212 iwe.cmd = SIOCGIWFREQ;
214 /* check legal index */
215 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
217 if (dsconfig >= 1 && dsconfig <= sizeof(
218 ieee80211_wlan_frequencies) / sizeof(long))
219 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
220 pnetwork->network.Configuration.
221 DSConfig - 1] * 100000);
225 iwe.u.freq.e = (s16)1;
226 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
227 start = iwe_stream_add_event(info, start, stop, &iwe,
229 /* Add encryption capability */
230 iwe.cmd = SIOCGIWENCODE;
231 if (cap & WLAN_CAPABILITY_PRIVACY)
232 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
235 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
236 iwe.u.data.length = (u16)0;
237 start = iwe_stream_add_point(info, start, stop, &iwe,
238 pnetwork->network.Ssid.Ssid);
239 /*Add basic and extended rates */
240 current_val = start + iwe_stream_lcp_len(info);
241 iwe.cmd = SIOCGIWRATE;
242 iwe.u.bitrate.fixed = 0;
243 iwe.u.bitrate.disabled = 0;
244 iwe.u.bitrate.value = 0;
246 while (pnetwork->network.rates[i] != 0) {
247 /* Bit rate given in 500 kb/s units */
248 iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
250 current_val = iwe_stream_add_value(info, start, current_val,
251 stop, &iwe, IW_EV_PARAM_LEN);
253 /* Check if we added any event */
254 if ((current_val - start) > iwe_stream_lcp_len(info))
256 /* parsing WPA/WPA2 IE */
258 u8 buf[MAX_WPA_IE_LEN];
259 u8 wpa_ie[255], rsn_ie[255];
260 u16 wpa_len = 0, rsn_len = 0;
263 r8712_get_sec_ie(pnetwork->network.IEs,
264 pnetwork->network.IELength, rsn_ie, &rsn_len,
267 memset(buf, 0, MAX_WPA_IE_LEN);
268 n = sprintf(buf, "wpa_ie=");
269 for (i = 0; i < wpa_len; i++) {
270 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
272 if (n >= MAX_WPA_IE_LEN)
275 memset(&iwe, 0, sizeof(iwe));
276 iwe.cmd = IWEVCUSTOM;
277 iwe.u.data.length = (u16)strlen(buf);
278 start = iwe_stream_add_point(info, start, stop,
280 memset(&iwe, 0, sizeof(iwe));
282 iwe.u.data.length = (u16)wpa_len;
283 start = iwe_stream_add_point(info, start, stop,
287 memset(buf, 0, MAX_WPA_IE_LEN);
288 n = sprintf(buf, "rsn_ie=");
289 for (i = 0; i < rsn_len; i++) {
290 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
292 if (n >= MAX_WPA_IE_LEN)
295 memset(&iwe, 0, sizeof(iwe));
296 iwe.cmd = IWEVCUSTOM;
297 iwe.u.data.length = strlen(buf);
298 start = iwe_stream_add_point(info, start, stop,
300 memset(&iwe, 0, sizeof(iwe));
302 iwe.u.data.length = rsn_len;
303 start = iwe_stream_add_point(info, start, stop, &iwe,
308 { /* parsing WPS IE */
312 if (r8712_get_wps_ie(pnetwork->network.IEs,
313 pnetwork->network.IELength,
314 wps_ie, &wps_ielen)) {
317 iwe.u.data.length = (u16)wps_ielen;
318 start = iwe_stream_add_point(info, start, stop,
323 /* Add quality statistics */
325 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
326 /* we only update signal_level (signal strength) that is rssi. */
327 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
328 IW_QUAL_NOISE_INVALID);
329 iwe.u.qual.level = rssi; /* signal strength */
330 iwe.u.qual.qual = 0; /* signal quality */
331 iwe.u.qual.noise = 0; /* noise level */
332 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
333 /* how to translate rssi to ?% */
337 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
339 struct _adapter *padapter = netdev_priv(dev);
342 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
343 padapter->securitypriv.ndisencryptstatus =
344 Ndis802_11Encryption1Enabled;
345 padapter->securitypriv.ndisauthtype =
346 Ndis802_11AuthModeAutoSwitch;
347 padapter->securitypriv.AuthAlgrthm = 3;
348 } else if (value & AUTH_ALG_SHARED_KEY) {
349 padapter->securitypriv.ndisencryptstatus =
350 Ndis802_11Encryption1Enabled;
351 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
352 padapter->securitypriv.AuthAlgrthm = 1;
353 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
354 if (padapter->securitypriv.ndisauthtype <
355 Ndis802_11AuthModeWPAPSK) {
356 padapter->securitypriv.ndisauthtype =
357 Ndis802_11AuthModeOpen;
358 padapter->securitypriv.AuthAlgrthm = 0;
366 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
370 u32 wep_key_idx, wep_key_len = 0;
371 struct NDIS_802_11_WEP *pwep = NULL;
372 struct _adapter *padapter = netdev_priv(dev);
373 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
374 struct security_priv *psecuritypriv = &padapter->securitypriv;
376 param->u.crypt.err = 0;
377 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
378 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
379 param->u.crypt.key_len)
381 if (!is_broadcast_ether_addr(param->sta_addr))
384 if (param->u.crypt.idx >= WEP_KEYS) {
385 /* for large key indices, set the default (0) */
386 param->u.crypt.idx = 0;
388 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
389 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
390 padapter->securitypriv.ndisencryptstatus =
391 Ndis802_11Encryption1Enabled;
392 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
393 padapter->securitypriv.XGrpPrivacy = _WEP40_;
394 wep_key_idx = param->u.crypt.idx;
395 wep_key_len = param->u.crypt.key_len;
396 if (wep_key_idx >= WEP_KEYS)
398 if (wep_key_len <= 0)
401 wep_key_len = wep_key_len <= 5 ? 5 : 13;
402 pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
405 pwep->KeyLength = wep_key_len;
406 pwep->Length = wep_key_len +
407 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
408 if (wep_key_len == 13) {
409 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
410 padapter->securitypriv.XGrpPrivacy = _WEP104_;
412 pwep->KeyIndex = wep_key_idx;
413 pwep->KeyIndex |= 0x80000000;
414 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
415 if (param->u.crypt.set_tx) {
416 if (r8712_set_802_11_add_wep(padapter, pwep) ==
420 /* don't update "psecuritypriv->PrivacyAlgrthm" and
421 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
422 * r8712_set_key to fw/cam
424 if (wep_key_idx >= WEP_KEYS) {
428 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
429 skey[0]), pwep->KeyMaterial,
431 psecuritypriv->DefKeylen[wep_key_idx] =
433 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
437 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
438 struct sta_info *psta, *pbcmc_sta;
439 struct sta_priv *pstapriv = &padapter->stapriv;
441 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
442 WIFI_MP_STATE)) { /* sta mode */
443 psta = r8712_get_stainfo(pstapriv,
444 get_bssid(pmlmepriv));
446 psta->ieee8021x_blocked = false;
447 if ((padapter->securitypriv.ndisencryptstatus ==
448 Ndis802_11Encryption2Enabled) ||
449 (padapter->securitypriv.ndisencryptstatus ==
450 Ndis802_11Encryption3Enabled))
451 psta->XPrivacy = padapter->
452 securitypriv.PrivacyAlgrthm;
453 if (param->u.crypt.set_tx == 1)
454 handle_pairwise_key(psta, param,
457 handle_group_key(param, padapter);
459 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
461 pbcmc_sta->ieee8021x_blocked = false;
462 if ((padapter->securitypriv.ndisencryptstatus ==
463 Ndis802_11Encryption2Enabled) ||
464 (padapter->securitypriv.ndisencryptstatus ==
465 Ndis802_11Encryption3Enabled))
466 pbcmc_sta->XPrivacy =
467 padapter->securitypriv.
477 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
478 unsigned short ielen)
481 int group_cipher = 0, pairwise_cipher = 0;
484 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
487 buf = kmemdup(pie, ielen, GFP_ATOMIC);
490 if (ielen < RSN_HEADER_LEN) {
494 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
495 &pairwise_cipher) == _SUCCESS) {
496 padapter->securitypriv.AuthAlgrthm = 2;
497 padapter->securitypriv.ndisauthtype =
498 Ndis802_11AuthModeWPAPSK;
500 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
501 &pairwise_cipher) == _SUCCESS) {
502 padapter->securitypriv.AuthAlgrthm = 2;
503 padapter->securitypriv.ndisauthtype =
504 Ndis802_11AuthModeWPA2PSK;
506 switch (group_cipher) {
507 case WPA_CIPHER_NONE:
508 padapter->securitypriv.XGrpPrivacy =
510 padapter->securitypriv.ndisencryptstatus =
511 Ndis802_11EncryptionDisabled;
513 case WPA_CIPHER_WEP40:
514 padapter->securitypriv.XGrpPrivacy = _WEP40_;
515 padapter->securitypriv.ndisencryptstatus =
516 Ndis802_11Encryption1Enabled;
518 case WPA_CIPHER_TKIP:
519 padapter->securitypriv.XGrpPrivacy = _TKIP_;
520 padapter->securitypriv.ndisencryptstatus =
521 Ndis802_11Encryption2Enabled;
523 case WPA_CIPHER_CCMP:
524 padapter->securitypriv.XGrpPrivacy = _AES_;
525 padapter->securitypriv.ndisencryptstatus =
526 Ndis802_11Encryption3Enabled;
528 case WPA_CIPHER_WEP104:
529 padapter->securitypriv.XGrpPrivacy = _WEP104_;
530 padapter->securitypriv.ndisencryptstatus =
531 Ndis802_11Encryption1Enabled;
534 switch (pairwise_cipher) {
535 case WPA_CIPHER_NONE:
536 padapter->securitypriv.PrivacyAlgrthm =
538 padapter->securitypriv.ndisencryptstatus =
539 Ndis802_11EncryptionDisabled;
541 case WPA_CIPHER_WEP40:
542 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
543 padapter->securitypriv.ndisencryptstatus =
544 Ndis802_11Encryption1Enabled;
546 case WPA_CIPHER_TKIP:
547 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
548 padapter->securitypriv.ndisencryptstatus =
549 Ndis802_11Encryption2Enabled;
551 case WPA_CIPHER_CCMP:
552 padapter->securitypriv.PrivacyAlgrthm = _AES_;
553 padapter->securitypriv.ndisencryptstatus =
554 Ndis802_11Encryption3Enabled;
556 case WPA_CIPHER_WEP104:
557 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
558 padapter->securitypriv.ndisencryptstatus =
559 Ndis802_11Encryption1Enabled;
562 padapter->securitypriv.wps_phase = false;
565 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
567 while (cnt < ielen) {
570 if ((eid == _VENDOR_SPECIFIC_IE_) &&
571 (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
572 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
573 padapter->securitypriv.wps_ie_len =
574 ((buf[cnt + 1] + 2) <
575 (MAX_WPA_IE_LEN << 2)) ?
577 (MAX_WPA_IE_LEN << 2);
578 memcpy(padapter->securitypriv.wps_ie,
580 padapter->securitypriv.wps_ie_len);
581 padapter->securitypriv.wps_phase =
583 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
584 cnt += buf[cnt + 1] + 2;
588 cnt += buf[cnt + 1] + 2;
597 static int r8711_wx_get_name(struct net_device *dev,
598 struct iw_request_info *info,
599 union iwreq_data *wrqu, char *extra)
601 struct _adapter *padapter = netdev_priv(dev);
605 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
606 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
609 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
611 /* parsing HT_CAP_IE */
612 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
613 &ht_ielen, pcur_bss->IELength - 12);
614 if (p && ht_ielen > 0)
616 prates = pcur_bss->rates;
617 if (r8712_is_cckratesonly_included(prates)) {
619 snprintf(wrqu->name, IFNAMSIZ,
622 snprintf(wrqu->name, IFNAMSIZ,
624 } else if (r8712_is_cckrates_included(prates)) {
626 snprintf(wrqu->name, IFNAMSIZ,
629 snprintf(wrqu->name, IFNAMSIZ,
633 snprintf(wrqu->name, IFNAMSIZ,
636 snprintf(wrqu->name, IFNAMSIZ,
640 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
645 static const long frequency_list[] = {
646 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
647 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
648 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
649 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
650 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
654 static int r8711_wx_set_freq(struct net_device *dev,
655 struct iw_request_info *info,
656 union iwreq_data *wrqu, char *extra)
658 struct _adapter *padapter = netdev_priv(dev);
659 struct iw_freq *fwrq = &wrqu->freq;
662 /* If setting by frequency, convert to a channel */
663 if ((fwrq->e == 1) &&
664 (fwrq->m >= (int) 2.412e8) &&
665 (fwrq->m <= (int) 2.487e8)) {
666 int f = fwrq->m / 100000;
669 while ((c < 14) && (f != frequency_list[c]))
674 /* Setting by channel number */
675 if ((fwrq->m > 14) || (fwrq->e > 0)) {
678 int channel = fwrq->m;
680 if ((channel < 1) || (channel > 14)) {
683 /* Yes ! We can set it !!! */
684 padapter->registrypriv.channel = channel;
690 static int r8711_wx_get_freq(struct net_device *dev,
691 struct iw_request_info *info,
692 union iwreq_data *wrqu, char *extra)
694 struct _adapter *padapter = netdev_priv(dev);
695 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
696 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
698 if (!check_fwstate(pmlmepriv, _FW_LINKED))
701 wrqu->freq.m = ieee80211_wlan_frequencies[
702 pcur_bss->Configuration.DSConfig - 1] * 100000;
704 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
709 static int r8711_wx_set_mode(struct net_device *dev,
710 struct iw_request_info *a,
711 union iwreq_data *wrqu, char *b)
713 struct _adapter *padapter = netdev_priv(dev);
714 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
716 switch (wrqu->mode) {
718 networkType = Ndis802_11AutoUnknown;
721 networkType = Ndis802_11IBSS;
724 networkType = Ndis802_11APMode;
727 networkType = Ndis802_11Infrastructure;
732 if (Ndis802_11APMode == networkType)
733 r8712_setopmode_cmd(padapter, networkType);
735 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
737 r8712_set_802_11_infrastructure_mode(padapter, networkType);
741 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
742 union iwreq_data *wrqu, char *b)
744 struct _adapter *padapter = netdev_priv(dev);
745 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
747 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
748 wrqu->mode = IW_MODE_INFRA;
749 else if (check_fwstate(pmlmepriv,
750 WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
751 wrqu->mode = IW_MODE_ADHOC;
752 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
753 wrqu->mode = IW_MODE_MASTER;
755 wrqu->mode = IW_MODE_AUTO;
759 static int r871x_wx_set_pmkid(struct net_device *dev,
760 struct iw_request_info *a,
761 union iwreq_data *wrqu, char *extra)
763 struct _adapter *padapter = netdev_priv(dev);
764 struct security_priv *psecuritypriv = &padapter->securitypriv;
765 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
766 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
767 u8 strIssueBssid[ETH_ALEN] = {0x00};
768 u8 j, blInserted = false;
769 int intReturn = false;
772 * There are the BSSID information in the bssid.sa_data array.
773 * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
774 * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
775 * wpa_supplicant wants to add a PMKID/BSSID to driver.
776 * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
777 * remove a PMKID/BSSID from driver.
781 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
784 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
788 /* overwrite PMKID */
789 for (j = 0; j < NUM_PMKID_CACHE; j++) {
790 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
791 strIssueBssid, ETH_ALEN)) {
792 /* BSSID is matched, the same AP => rewrite
795 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
797 memcpy(psecuritypriv->PMKIDList[j].PMKID,
798 pPMK->pmkid, IW_PMKID_LEN);
799 psecuritypriv->PMKIDList[j].bUsed = true;
800 psecuritypriv->PMKIDIndex = j + 1;
806 /* Find a new entry */
807 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
808 __func__, psecuritypriv->PMKIDIndex);
809 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
810 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
811 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
812 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
813 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
815 psecuritypriv->PMKIDIndex++;
816 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
817 psecuritypriv->PMKIDIndex = 0;
820 case IW_PMKSA_REMOVE:
822 for (j = 0; j < NUM_PMKID_CACHE; j++) {
823 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
824 strIssueBssid, ETH_ALEN)) {
825 /* BSSID is matched, the same AP => Remove
826 * this PMKID information and reset it.
828 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
829 psecuritypriv->PMKIDList[j].bUsed = false;
835 memset(psecuritypriv->PMKIDList, 0,
836 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
837 psecuritypriv->PMKIDIndex = 0;
841 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
848 static int r8711_wx_get_sens(struct net_device *dev,
849 struct iw_request_info *info,
850 union iwreq_data *wrqu, char *extra)
852 wrqu->sens.value = 0;
853 wrqu->sens.fixed = 0; /* no auto select */
854 wrqu->sens.disabled = 1;
858 static int r8711_wx_get_range(struct net_device *dev,
859 struct iw_request_info *info,
860 union iwreq_data *wrqu, char *extra)
862 struct iw_range *range = (struct iw_range *)extra;
866 wrqu->data.length = sizeof(*range);
867 memset(range, 0, sizeof(*range));
868 /* Let's try to keep this struct in the same order as in
869 * linux/include/wireless.h
872 /* TODO: See what values we can set, and remove the ones we can't
873 * set, or fill them with some default data.
875 /* ~5 Mb/s real (802.11b) */
876 range->throughput = 5 * 1000 * 1000;
877 /* TODO: 8711 sensitivity ? */
878 /* signal level threshold range */
879 /* percent values between 0 and 100. */
880 range->max_qual.qual = 100;
881 range->max_qual.level = 100;
882 range->max_qual.noise = 100;
883 range->max_qual.updated = 7; /* Updated all three */
884 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
885 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
886 range->avg_qual.level = 0x100 - 78;
887 range->avg_qual.noise = 0;
888 range->avg_qual.updated = 7; /* Updated all three */
889 range->num_bitrates = RATE_COUNT;
890 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
891 range->bitrate[i] = rtl8180_rates[i];
892 range->min_frag = MIN_FRAG_THRESHOLD;
893 range->max_frag = MAX_FRAG_THRESHOLD;
895 range->we_version_compiled = WIRELESS_EXT;
896 range->we_version_source = 16;
897 range->num_channels = 14;
898 for (i = 0, val = 0; i < 14; i++) {
899 /* Include only legal frequencies for some countries */
900 range->freq[val].i = i + 1;
901 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
902 range->freq[val].e = 1;
904 if (val == IW_MAX_FREQUENCIES)
907 range->num_frequency = val;
908 range->enc_capa = IW_ENC_CAPA_WPA |
910 IW_ENC_CAPA_CIPHER_TKIP |
911 IW_ENC_CAPA_CIPHER_CCMP;
915 static int r8711_wx_get_rate(struct net_device *dev,
916 struct iw_request_info *info,
917 union iwreq_data *wrqu, char *extra);
919 static int r871x_wx_set_priv(struct net_device *dev,
920 struct iw_request_info *info,
921 union iwreq_data *awrq,
924 int ret = 0, len = 0;
926 struct _adapter *padapter = netdev_priv(dev);
927 struct iw_point *dwrq = (struct iw_point *)awrq;
930 ext = memdup_user(dwrq->pointer, len);
934 if (!strcasecmp(ext, "RSSI")) {
935 /*Return received signal strength indicator in -db for */
938 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
939 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
941 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
942 sprintf(ext, "%s rssi %d",
943 pcur_network->network.Ssid.Ssid,
945 ((padapter->recvpriv.fw_rssi) >> 1) - 95
946 /*pcur_network->network.Rssi */
951 } else if (!strcasecmp(ext, "LINKSPEED")) {
952 /*Return link speed in MBPS */
954 union iwreq_data wrqd;
958 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
962 mbps = wrqd.bitrate.value / 1000000;
963 sprintf(ext, "LINKSPEED %d", mbps);
964 } else if (!strcasecmp(ext, "MACADDR")) {
965 /*Return mac address of the station */
966 /* Macaddr = xx:xx:xx:xx:xx:xx */
967 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
968 } else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
969 /*Set scan type to active */
970 /*OK if successful */
971 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
973 pmlmepriv->passive_mode = 1;
975 } else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
976 /*Set scan type to passive */
977 /*OK if successful */
978 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
980 pmlmepriv->passive_mode = 0;
982 } else if (!strncmp(ext, "DCE-E", 5)) {
983 /*Set scan type to passive */
984 /*OK if successful */
985 r8712_disconnectCtrlEx_cmd(padapter
986 , 1 /*u32 enableDrvCtrl */
987 , 5 /*u32 tryPktCnt */
988 , 100 /*u32 tryPktInterval */
989 , 5000 /*u32 firstStageTO */
992 } else if (!strncmp(ext, "DCE-D", 5)) {
993 /*Set scan type to passive */
995 r8712_disconnectCtrlEx_cmd(padapter
996 , 0 /*u32 enableDrvCtrl */
997 , 5 /*u32 tryPktCnt */
998 , 100 /*u32 tryPktInterval */
999 , 5000 /*u32 firstStageTO */
1003 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1007 if (copy_to_user(dwrq->pointer, ext,
1008 min(dwrq->length, (__u16)(strlen(ext) + 1))))
1017 * s1. set_802_11_infrastructure_mode()
1018 * s2. set_802_11_authentication_mode()
1019 * s3. set_802_11_encryption_mode()
1020 * s4. set_802_11_bssid()
1022 * This function intends to handle the Set AP command, which specifies the
1023 * MAC# of a preferred Access Point.
1024 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1026 * For this operation to succeed, there is no need for the interface to be up.
1029 static int r8711_wx_set_wap(struct net_device *dev,
1030 struct iw_request_info *info,
1031 union iwreq_data *awrq,
1034 int ret = -EINPROGRESS;
1035 struct _adapter *padapter = netdev_priv(dev);
1036 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1037 struct __queue *queue = &pmlmepriv->scanned_queue;
1038 struct sockaddr *temp = (struct sockaddr *)awrq;
1040 struct list_head *phead;
1042 struct wlan_network *pnetwork = NULL;
1043 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1045 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1047 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1049 if (temp->sa_family != ARPHRD_ETHER)
1051 authmode = padapter->securitypriv.ndisauthtype;
1052 spin_lock_irqsave(&queue->lock, irqL);
1053 phead = &queue->queue;
1054 pmlmepriv->pscanned = phead->next;
1056 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1058 pnetwork = container_of(pmlmepriv->pscanned,
1059 struct wlan_network, list);
1060 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1061 dst_bssid = pnetwork->network.MacAddress;
1062 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1063 r8712_set_802_11_infrastructure_mode(padapter,
1064 pnetwork->network.InfrastructureMode);
1068 spin_unlock_irqrestore(&queue->lock, irqL);
1070 if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
1073 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1080 static int r8711_wx_get_wap(struct net_device *dev,
1081 struct iw_request_info *info,
1082 union iwreq_data *wrqu, char *extra)
1084 struct _adapter *padapter = netdev_priv(dev);
1085 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1086 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1088 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1089 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1091 ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
1093 eth_zero_addr(wrqu->ap_addr.sa_data);
1097 static int r871x_wx_set_mlme(struct net_device *dev,
1098 struct iw_request_info *info,
1099 union iwreq_data *wrqu, char *extra)
1102 struct _adapter *padapter = netdev_priv(dev);
1103 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1107 switch (mlme->cmd) {
1108 case IW_MLME_DEAUTH:
1109 if (!r8712_set_802_11_disassociate(padapter))
1112 case IW_MLME_DISASSOC:
1113 if (!r8712_set_802_11_disassociate(padapter))
1124 * This function intends to handle the Set Scan command.
1125 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1127 * For this operation to succeed, the interface is brought Up beforehand.
1130 static int r8711_wx_set_scan(struct net_device *dev,
1131 struct iw_request_info *a,
1132 union iwreq_data *wrqu, char *extra)
1134 struct _adapter *padapter = netdev_priv(dev);
1135 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1138 if (padapter->bDriverStopped) {
1139 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1140 __func__, padapter->bDriverStopped);
1145 if (!padapter->hw_init_completed)
1147 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
1148 (pmlmepriv->sitesurveyctrl.traffic_busy))
1150 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1151 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1153 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1154 struct ndis_802_11_ssid ssid;
1156 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1158 memset((unsigned char *)&ssid, 0,
1159 sizeof(struct ndis_802_11_ssid));
1160 memcpy(ssid.Ssid, req->essid, len);
1161 ssid.SsidLength = len;
1162 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1163 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1164 _FW_UNDER_LINKING)) ||
1165 (pmlmepriv->sitesurveyctrl.traffic_busy)) {
1166 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1169 status = r8712_sitesurvey_cmd(padapter, &ssid);
1171 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1174 status = r8712_set_802_11_bssid_list_scan(padapter);
1181 static int r8711_wx_get_scan(struct net_device *dev,
1182 struct iw_request_info *a,
1183 union iwreq_data *wrqu, char *extra)
1185 struct _adapter *padapter = netdev_priv(dev);
1186 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1187 struct __queue *queue = &pmlmepriv->scanned_queue;
1188 struct wlan_network *pnetwork = NULL;
1190 struct list_head *plist, *phead;
1192 char *stop = ev + wrqu->data.length;
1193 u32 ret = 0, cnt = 0;
1195 if (padapter->bDriverStopped)
1197 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1198 _FW_UNDER_LINKING)) {
1204 spin_lock_irqsave(&queue->lock, irqL);
1205 phead = &queue->queue;
1206 plist = phead->next;
1208 if (end_of_queue_search(phead, plist))
1210 if ((stop - ev) < SCAN_ITEM_SIZE) {
1214 pnetwork = container_of(plist, struct wlan_network, list);
1215 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1216 plist = plist->next;
1218 spin_unlock_irqrestore(&queue->lock, irqL);
1219 wrqu->data.length = ev - extra;
1220 wrqu->data.flags = 0;
1225 * s1. set_802_11_infrastructure_mode()
1226 * s2. set_802_11_authenticaion_mode()
1227 * s3. set_802_11_encryption_mode()
1228 * s4. set_802_11_ssid()
1230 * This function intends to handle the Set ESSID command.
1231 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1233 * For this operation to succeed, there is no need for the interface to be Up.
1236 static int r8711_wx_set_essid(struct net_device *dev,
1237 struct iw_request_info *a,
1238 union iwreq_data *wrqu, char *extra)
1240 struct _adapter *padapter = netdev_priv(dev);
1241 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1242 struct __queue *queue = &pmlmepriv->scanned_queue;
1243 struct wlan_network *pnetwork = NULL;
1244 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1245 struct ndis_802_11_ssid ndis_ssid;
1246 u8 *dst_ssid, *src_ssid;
1247 struct list_head *phead;
1250 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1252 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1254 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1256 authmode = padapter->securitypriv.ndisauthtype;
1257 if (wrqu->essid.flags && wrqu->essid.length) {
1258 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1259 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1260 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1261 ndis_ssid.SsidLength = len;
1262 memcpy(ndis_ssid.Ssid, extra, len);
1263 src_ssid = ndis_ssid.Ssid;
1264 phead = &queue->queue;
1265 pmlmepriv->pscanned = phead->next;
1267 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1269 pnetwork = container_of(pmlmepriv->pscanned,
1270 struct wlan_network, list);
1271 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1272 dst_ssid = pnetwork->network.Ssid.Ssid;
1273 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1274 && (pnetwork->network.Ssid.SsidLength ==
1275 ndis_ssid.SsidLength)) {
1276 if (check_fwstate(pmlmepriv,
1277 WIFI_ADHOC_STATE)) {
1278 if (pnetwork->network.
1282 cur_network.network.
1287 r8712_set_802_11_infrastructure_mode(
1289 pnetwork->network.InfrastructureMode);
1293 r8712_set_802_11_authentication_mode(padapter, authmode);
1294 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1296 return -EINPROGRESS;
1299 static int r8711_wx_get_essid(struct net_device *dev,
1300 struct iw_request_info *a,
1301 union iwreq_data *wrqu, char *extra)
1303 struct _adapter *padapter = netdev_priv(dev);
1304 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1305 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1308 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
1309 len = pcur_bss->Ssid.SsidLength;
1310 wrqu->essid.length = len;
1311 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1312 wrqu->essid.flags = 1;
1319 static int r8711_wx_set_rate(struct net_device *dev,
1320 struct iw_request_info *a,
1321 union iwreq_data *wrqu, char *extra)
1323 struct _adapter *padapter = netdev_priv(dev);
1324 u32 target_rate = wrqu->bitrate.value;
1325 u32 fixed = wrqu->bitrate.fixed;
1327 u8 datarates[NumRates];
1328 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1331 if (target_rate == -1) {
1335 target_rate = target_rate / 100000;
1336 switch (target_rate) {
1378 for (i = 0; i < NumRates; i++) {
1379 if (ratevalue == mpdatarate[i]) {
1380 datarates[i] = mpdatarate[i];
1384 datarates[i] = 0xff;
1387 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1392 static int r8711_wx_get_rate(struct net_device *dev,
1393 struct iw_request_info *info,
1394 union iwreq_data *wrqu, char *extra)
1396 struct _adapter *padapter = netdev_priv(dev);
1397 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1398 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1399 struct ieee80211_ht_cap *pht_capie;
1400 unsigned char rf_type = padapter->registrypriv.rf_config;
1403 u16 rate, max_rate = 0, ht_cap = false;
1405 u8 bw_40MHz = 0, short_GI = 0;
1409 if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
1411 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen,
1412 pcur_bss->IELength - 12);
1413 if (p && ht_ielen > 0) {
1415 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1416 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
1417 bw_40MHz = (le16_to_cpu(pht_capie->cap_info) &
1418 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1419 short_GI = (le16_to_cpu(pht_capie->cap_info) &
1420 (IEEE80211_HT_CAP_SGI_20 |
1421 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1423 while ((pcur_bss->rates[i] != 0) &&
1424 (pcur_bss->rates[i] != 0xFF)) {
1425 rate = pcur_bss->rates[i] & 0x7F;
1426 if (rate > max_rate)
1428 wrqu->bitrate.fixed = 0; /* no auto select */
1429 wrqu->bitrate.value = rate * 500000;
1433 if (mcs_rate & 0x8000 /* MCS15 */
1435 rf_type == RTL8712_RF_2T2R)
1436 max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) :
1437 ((short_GI) ? 144 : 130);
1438 else /* default MCS7 */
1439 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) :
1440 ((short_GI) ? 72 : 65);
1441 max_rate *= 2; /* Mbps/2 */
1443 wrqu->bitrate.value = max_rate * 500000;
1447 static int r8711_wx_get_rts(struct net_device *dev,
1448 struct iw_request_info *info,
1449 union iwreq_data *wrqu, char *extra)
1451 struct _adapter *padapter = netdev_priv(dev);
1453 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1454 wrqu->rts.fixed = 0; /* no auto select */
1458 static int r8711_wx_set_frag(struct net_device *dev,
1459 struct iw_request_info *info,
1460 union iwreq_data *wrqu, char *extra)
1462 struct _adapter *padapter = netdev_priv(dev);
1464 if (wrqu->frag.disabled) {
1465 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1467 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1468 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1470 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1475 static int r8711_wx_get_frag(struct net_device *dev,
1476 struct iw_request_info *info,
1477 union iwreq_data *wrqu, char *extra)
1479 struct _adapter *padapter = netdev_priv(dev);
1481 wrqu->frag.value = padapter->xmitpriv.frag_len;
1482 wrqu->frag.fixed = 0; /* no auto select */
1486 static int r8711_wx_get_retry(struct net_device *dev,
1487 struct iw_request_info *info,
1488 union iwreq_data *wrqu, char *extra)
1490 wrqu->retry.value = 7;
1491 wrqu->retry.fixed = 0; /* no auto select */
1492 wrqu->retry.disabled = 1;
1496 static int r8711_wx_set_enc(struct net_device *dev,
1497 struct iw_request_info *info,
1498 union iwreq_data *wrqu, char *keybuf)
1501 u32 keyindex_provided;
1502 struct NDIS_802_11_WEP wep;
1503 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1504 struct iw_point *erq = &(wrqu->encoding);
1505 struct _adapter *padapter = netdev_priv(dev);
1507 key = erq->flags & IW_ENCODE_INDEX;
1508 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1509 if (erq->flags & IW_ENCODE_DISABLED) {
1510 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1511 padapter->securitypriv.ndisencryptstatus =
1512 Ndis802_11EncryptionDisabled;
1513 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1514 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1515 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1516 authmode = Ndis802_11AuthModeOpen;
1517 padapter->securitypriv.ndisauthtype = authmode;
1524 keyindex_provided = 1;
1526 keyindex_provided = 0;
1527 key = padapter->securitypriv.PrivacyKeyIndex;
1529 /* set authentication mode */
1530 if (erq->flags & IW_ENCODE_OPEN) {
1531 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1532 padapter->securitypriv.ndisencryptstatus =
1533 Ndis802_11Encryption1Enabled;
1534 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1535 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1536 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1537 authmode = Ndis802_11AuthModeOpen;
1538 padapter->securitypriv.ndisauthtype = authmode;
1539 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1541 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1542 padapter->securitypriv.ndisencryptstatus =
1543 Ndis802_11Encryption1Enabled;
1544 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1545 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1546 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1547 authmode = Ndis802_11AuthModeShared;
1548 padapter->securitypriv.ndisauthtype = authmode;
1550 padapter->securitypriv.ndisencryptstatus =
1551 Ndis802_11Encryption1Enabled;
1552 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1553 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1554 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1555 authmode = Ndis802_11AuthModeOpen;
1556 padapter->securitypriv.ndisauthtype = authmode;
1559 if (erq->length > 0) {
1560 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1561 wep.Length = wep.KeyLength +
1562 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1565 if (keyindex_provided == 1) { /* set key_id only, no given
1566 * KeyMaterial(erq->length==0).
1568 padapter->securitypriv.PrivacyKeyIndex = key;
1569 switch (padapter->securitypriv.DefKeylen[key]) {
1571 padapter->securitypriv.PrivacyAlgrthm =
1575 padapter->securitypriv.PrivacyAlgrthm =
1579 padapter->securitypriv.PrivacyAlgrthm =
1586 wep.KeyIndex |= 0x80000000; /* transmit key */
1587 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1588 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1593 static int r8711_wx_get_enc(struct net_device *dev,
1594 struct iw_request_info *info,
1595 union iwreq_data *wrqu, char *keybuf)
1598 struct _adapter *padapter = netdev_priv(dev);
1599 struct iw_point *erq = &(wrqu->encoding);
1600 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1602 if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
1603 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1605 erq->flags |= IW_ENCODE_DISABLED;
1609 key = erq->flags & IW_ENCODE_INDEX;
1615 key = padapter->securitypriv.PrivacyKeyIndex;
1617 erq->flags = key + 1;
1618 switch (padapter->securitypriv.ndisencryptstatus) {
1619 case Ndis802_11EncryptionNotSupported:
1620 case Ndis802_11EncryptionDisabled:
1622 erq->flags |= IW_ENCODE_DISABLED;
1624 case Ndis802_11Encryption1Enabled:
1625 erq->length = padapter->securitypriv.DefKeylen[key];
1627 memcpy(keybuf, padapter->securitypriv.DefKey[
1628 key].skey, padapter->securitypriv.
1630 erq->flags |= IW_ENCODE_ENABLED;
1631 if (padapter->securitypriv.ndisauthtype ==
1632 Ndis802_11AuthModeOpen)
1633 erq->flags |= IW_ENCODE_OPEN;
1634 else if (padapter->securitypriv.ndisauthtype ==
1635 Ndis802_11AuthModeShared)
1636 erq->flags |= IW_ENCODE_RESTRICTED;
1639 erq->flags |= IW_ENCODE_DISABLED;
1642 case Ndis802_11Encryption2Enabled:
1643 case Ndis802_11Encryption3Enabled:
1645 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1650 erq->flags |= IW_ENCODE_DISABLED;
1656 static int r8711_wx_get_power(struct net_device *dev,
1657 struct iw_request_info *info,
1658 union iwreq_data *wrqu, char *extra)
1660 wrqu->power.value = 0;
1661 wrqu->power.fixed = 0; /* no auto select */
1662 wrqu->power.disabled = 1;
1666 static int r871x_wx_set_gen_ie(struct net_device *dev,
1667 struct iw_request_info *info,
1668 union iwreq_data *wrqu, char *extra)
1670 struct _adapter *padapter = netdev_priv(dev);
1672 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1675 static int r871x_wx_set_auth(struct net_device *dev,
1676 struct iw_request_info *info,
1677 union iwreq_data *wrqu, char *extra)
1679 struct _adapter *padapter = netdev_priv(dev);
1680 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1685 paramid = param->flags & IW_AUTH_INDEX;
1686 paramval = param->value;
1688 case IW_AUTH_WPA_VERSION:
1690 case IW_AUTH_CIPHER_PAIRWISE:
1692 case IW_AUTH_CIPHER_GROUP:
1694 case IW_AUTH_KEY_MGMT:
1696 * ??? does not use these parameters
1699 case IW_AUTH_TKIP_COUNTERMEASURES:
1701 /* wpa_supplicant is enabling tkip countermeasure. */
1702 padapter->securitypriv.btkip_countermeasure = true;
1704 /* wpa_supplicant is disabling tkip countermeasure. */
1705 padapter->securitypriv.btkip_countermeasure = false;
1708 case IW_AUTH_DROP_UNENCRYPTED:
1711 * wpa_supplicant calls set_wpa_enabled when the driver
1712 * is loaded and unloaded, regardless of if WPA is being
1713 * used. No other calls are made which can be used to
1714 * determine if encryption will be used or not prior to
1715 * association being expected. If encryption is not being
1716 * used, drop_unencrypted is set to false, else true -- we
1717 * can use this to determine if the CAP_PRIVACY_ON bit should
1720 if (padapter->securitypriv.ndisencryptstatus ==
1721 Ndis802_11Encryption1Enabled) {
1722 /* it means init value, or using wep,
1723 * ndisencryptstatus =
1724 * Ndis802_11Encryption1Enabled,
1725 * then it needn't reset it;
1731 padapter->securitypriv.ndisencryptstatus =
1732 Ndis802_11EncryptionDisabled;
1733 padapter->securitypriv.PrivacyAlgrthm =
1735 padapter->securitypriv.XGrpPrivacy =
1737 padapter->securitypriv.AuthAlgrthm = 0;
1738 padapter->securitypriv.ndisauthtype =
1739 Ndis802_11AuthModeOpen;
1742 case IW_AUTH_80211_AUTH_ALG:
1743 ret = wpa_set_auth_algs(dev, (u32)paramval);
1745 case IW_AUTH_WPA_ENABLED:
1747 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1749 case IW_AUTH_PRIVACY_INVOKED:
1758 static int r871x_wx_set_enc_ext(struct net_device *dev,
1759 struct iw_request_info *info,
1760 union iwreq_data *wrqu, char *extra)
1762 struct iw_point *pencoding = &wrqu->encoding;
1763 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1764 struct ieee_param *param = NULL;
1769 switch (pext->alg) {
1770 case IW_ENCODE_ALG_NONE:
1773 case IW_ENCODE_ALG_WEP:
1776 case IW_ENCODE_ALG_TKIP:
1779 case IW_ENCODE_ALG_CCMP:
1786 param_len = sizeof(struct ieee_param) + pext->key_len;
1787 param = kzalloc(param_len, GFP_ATOMIC);
1790 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1791 eth_broadcast_addr(param->sta_addr);
1792 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1793 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1794 param->u.crypt.set_tx = 0;
1795 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1796 param->u.crypt.set_tx = 1;
1797 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1798 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1799 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1800 if (pext->key_len) {
1801 param->u.crypt.key_len = pext->key_len;
1802 memcpy(param + 1, pext + 1, pext->key_len);
1804 ret = wpa_set_encryption(dev, param, param_len);
1809 static int r871x_wx_get_nick(struct net_device *dev,
1810 struct iw_request_info *info,
1811 union iwreq_data *wrqu, char *extra)
1814 wrqu->data.length = 8;
1815 wrqu->data.flags = 1;
1816 memcpy(extra, "rtl_wifi", 8);
1821 static int r8711_wx_read32(struct net_device *dev,
1822 struct iw_request_info *info,
1823 union iwreq_data *wrqu, char *keybuf)
1825 struct _adapter *padapter = netdev_priv(dev);
1829 get_user(addr, (u32 __user *)wrqu->data.pointer);
1830 data32 = r8712_read32(padapter, addr);
1831 put_user(data32, (u32 __user *)wrqu->data.pointer);
1832 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1833 wrqu->data.flags = data32 & 0xffff;
1834 get_user(addr, (u32 __user *)wrqu->data.pointer);
1838 static int r8711_wx_write32(struct net_device *dev,
1839 struct iw_request_info *info,
1840 union iwreq_data *wrqu, char *keybuf)
1842 struct _adapter *padapter = netdev_priv(dev);
1846 get_user(addr, (u32 __user *)wrqu->data.pointer);
1847 data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
1848 r8712_write32(padapter, addr, data32);
1852 static int dummy(struct net_device *dev,
1853 struct iw_request_info *a,
1854 union iwreq_data *wrqu, char *b)
1859 static int r8711_drvext_hdl(struct net_device *dev,
1860 struct iw_request_info *info,
1861 union iwreq_data *wrqu, char *extra)
1866 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1867 struct iw_request_info *info,
1868 union iwreq_data *wrqu, char *extra)
1870 struct _adapter *padapter = netdev_priv(dev);
1871 struct iw_point *p = &wrqu->data;
1872 struct oid_par_priv oid_par;
1873 struct mp_ioctl_handler *phandler;
1874 struct mp_ioctl_param *poidparam;
1875 unsigned long BytesRead, BytesWritten, BytesNeeded;
1881 if ((!p->length) || (!p->pointer))
1884 bset = (u8)(p->flags & 0xFFFF);
1886 pparmbuf = memdup_user(p->pointer, len);
1887 if (IS_ERR(pparmbuf))
1888 return PTR_ERR(pparmbuf);
1890 poidparam = (struct mp_ioctl_param *)pparmbuf;
1891 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1893 goto _r871x_mp_ioctl_hdl_exit;
1895 phandler = mp_ioctl_hdl + poidparam->subcode;
1896 if ((phandler->paramsize != 0) &&
1897 (poidparam->len < phandler->paramsize)) {
1899 goto _r871x_mp_ioctl_hdl_exit;
1901 if (phandler->oid == 0 && phandler->handler) {
1902 status = phandler->handler(&oid_par);
1903 } else if (phandler->handler) {
1904 oid_par.adapter_context = padapter;
1905 oid_par.oid = phandler->oid;
1906 oid_par.information_buf = poidparam->data;
1907 oid_par.information_buf_len = poidparam->len;
1912 oid_par.bytes_rw = &BytesRead;
1913 oid_par.bytes_needed = &BytesNeeded;
1914 oid_par.type_of_oid = SET_OID;
1916 oid_par.bytes_rw = &BytesWritten;
1917 oid_par.bytes_needed = &BytesNeeded;
1918 oid_par.type_of_oid = QUERY_OID;
1920 status = phandler->handler(&oid_par);
1921 /* todo:check status, BytesNeeded, etc. */
1923 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1924 __func__, poidparam->subcode, phandler->oid,
1927 goto _r871x_mp_ioctl_hdl_exit;
1929 if (bset == 0x00) { /* query info */
1930 if (copy_to_user(p->pointer, pparmbuf, len))
1935 goto _r871x_mp_ioctl_hdl_exit;
1937 _r871x_mp_ioctl_hdl_exit:
1942 static int r871x_get_ap_info(struct net_device *dev,
1943 struct iw_request_info *info,
1944 union iwreq_data *wrqu, char *extra)
1946 struct _adapter *padapter = netdev_priv(dev);
1947 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1948 struct __queue *queue = &pmlmepriv->scanned_queue;
1949 struct iw_point *pdata = &wrqu->data;
1950 struct wlan_network *pnetwork = NULL;
1951 u32 cnt = 0, wpa_ielen;
1953 struct list_head *plist, *phead;
1954 unsigned char *pbuf;
1958 if (padapter->bDriverStopped || (pdata == NULL))
1960 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1961 _FW_UNDER_LINKING)) {
1968 if (pdata->length < 32)
1970 if (copy_from_user(data, pdata->pointer, 32))
1974 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
1975 phead = &queue->queue;
1976 plist = phead->next;
1978 if (end_of_queue_search(phead, plist))
1980 pnetwork = container_of(plist, struct wlan_network, list);
1981 if (!mac_pton(data, bssid)) {
1982 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
1984 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
1988 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
1989 if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
1990 /* BSSID match, then check if supporting wpa/wpa2 */
1991 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
1992 &wpa_ielen, pnetwork->network.IELength - 12);
1993 if (pbuf && (wpa_ielen > 0)) {
1997 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
1998 &wpa_ielen, pnetwork->network.IELength - 12);
1999 if (pbuf && (wpa_ielen > 0)) {
2004 plist = plist->next;
2006 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2007 if (pdata->length >= 34) {
2008 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2009 (u8 *)&pdata->flags, 1))
2015 static int r871x_set_pid(struct net_device *dev,
2016 struct iw_request_info *info,
2017 union iwreq_data *wrqu, char *extra)
2019 struct _adapter *padapter = netdev_priv(dev);
2020 struct iw_point *pdata = &wrqu->data;
2022 if ((padapter->bDriverStopped) || (pdata == NULL))
2024 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2029 static int r871x_set_chplan(struct net_device *dev,
2030 struct iw_request_info *info,
2031 union iwreq_data *wrqu, char *extra)
2034 struct _adapter *padapter = netdev_priv(dev);
2035 struct iw_point *pdata = &wrqu->data;
2038 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2042 ch_plan = (int)*extra;
2043 r8712_set_chplan_cmd(padapter, ch_plan);
2050 static int r871x_wps_start(struct net_device *dev,
2051 struct iw_request_info *info,
2052 union iwreq_data *wrqu, char *extra)
2054 struct _adapter *padapter = netdev_priv(dev);
2055 struct iw_point *pdata = &wrqu->data;
2056 u32 u32wps_start = 0;
2058 if ((padapter->bDriverStopped) || (pdata == NULL))
2060 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2062 if (u32wps_start == 0)
2063 u32wps_start = *extra;
2064 if (u32wps_start == 1) /* WPS Start */
2065 padapter->ledpriv.LedControlHandler(padapter,
2067 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2068 padapter->ledpriv.LedControlHandler(padapter,
2070 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2071 padapter->ledpriv.LedControlHandler(padapter,
2072 LED_CTL_STOP_WPS_FAIL);
2076 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2078 struct _adapter *padapter = netdev_priv(dev);
2081 case IEEE_PARAM_WPA_ENABLED:
2082 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2083 switch ((value) & 0xff) {
2085 padapter->securitypriv.ndisauthtype =
2086 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2087 padapter->securitypriv.ndisencryptstatus =
2088 Ndis802_11Encryption2Enabled;
2091 padapter->securitypriv.ndisauthtype =
2092 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2093 padapter->securitypriv.ndisencryptstatus =
2094 Ndis802_11Encryption3Enabled;
2098 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2100 case IEEE_PARAM_DROP_UNENCRYPTED:
2103 * wpa_supplicant calls set_wpa_enabled when the driver
2104 * is loaded and unloaded, regardless of if WPA is being
2105 * used. No other calls are made which can be used to
2106 * determine if encryption will be used or not prior to
2107 * association being expected. If encryption is not being
2108 * used, drop_unencrypted is set to false, else true -- we
2109 * can use this to determine if the CAP_PRIVACY_ON bit should
2113 case IEEE_PARAM_PRIVACY_INVOKED:
2115 case IEEE_PARAM_AUTH_ALGS:
2116 return wpa_set_auth_algs(dev, value);
2117 case IEEE_PARAM_IEEE_802_1X:
2119 case IEEE_PARAM_WPAX_SELECT:
2120 /* added for WPA2 mixed mode */
2128 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2130 struct _adapter *padapter = netdev_priv(dev);
2133 case IEEE_MLME_STA_DEAUTH:
2134 if (!r8712_set_802_11_disassociate(padapter))
2137 case IEEE_MLME_STA_DISASSOC:
2138 if (!r8712_set_802_11_disassociate(padapter))
2147 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2149 struct ieee_param *param;
2151 struct _adapter *padapter = netdev_priv(dev);
2153 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2155 param = memdup_user(p->pointer, p->length);
2157 return PTR_ERR(param);
2158 switch (param->cmd) {
2159 case IEEE_CMD_SET_WPA_PARAM:
2160 ret = wpa_set_param(dev, param->u.wpa_param.name,
2161 param->u.wpa_param.value);
2163 case IEEE_CMD_SET_WPA_IE:
2164 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2165 (u16)param->u.wpa_ie.len);
2167 case IEEE_CMD_SET_ENCRYPTION:
2168 ret = wpa_set_encryption(dev, param, p->length);
2171 ret = wpa_mlme(dev, param->u.mlme.command,
2172 param->u.mlme.reason_code);
2178 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2184 /* based on "driver_ipw" and for hostapd */
2185 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2187 struct iwreq *wrq = (struct iwreq *)rq;
2190 case RTL_IOCTL_WPA_SUPPLICANT:
2191 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2198 static iw_handler r8711_handlers[] = {
2199 NULL, /* SIOCSIWCOMMIT */
2200 r8711_wx_get_name, /* SIOCGIWNAME */
2201 dummy, /* SIOCSIWNWID */
2202 dummy, /* SIOCGIWNWID */
2203 r8711_wx_set_freq, /* SIOCSIWFREQ */
2204 r8711_wx_get_freq, /* SIOCGIWFREQ */
2205 r8711_wx_set_mode, /* SIOCSIWMODE */
2206 r8711_wx_get_mode, /* SIOCGIWMODE */
2207 dummy, /* SIOCSIWSENS */
2208 r8711_wx_get_sens, /* SIOCGIWSENS */
2209 NULL, /* SIOCSIWRANGE */
2210 r8711_wx_get_range, /* SIOCGIWRANGE */
2211 r871x_wx_set_priv, /* SIOCSIWPRIV */
2212 NULL, /* SIOCGIWPRIV */
2213 NULL, /* SIOCSIWSTATS */
2214 NULL, /* SIOCGIWSTATS */
2215 dummy, /* SIOCSIWSPY */
2216 dummy, /* SIOCGIWSPY */
2217 NULL, /* SIOCGIWTHRSPY */
2218 NULL, /* SIOCWIWTHRSPY */
2219 r8711_wx_set_wap, /* SIOCSIWAP */
2220 r8711_wx_get_wap, /* SIOCGIWAP */
2221 r871x_wx_set_mlme, /* request MLME operation;
2222 * uses struct iw_mlme
2224 dummy, /* SIOCGIWAPLIST -- deprecated */
2225 r8711_wx_set_scan, /* SIOCSIWSCAN */
2226 r8711_wx_get_scan, /* SIOCGIWSCAN */
2227 r8711_wx_set_essid, /* SIOCSIWESSID */
2228 r8711_wx_get_essid, /* SIOCGIWESSID */
2229 dummy, /* SIOCSIWNICKN */
2230 r871x_wx_get_nick, /* SIOCGIWNICKN */
2231 NULL, /* -- hole -- */
2232 NULL, /* -- hole -- */
2233 r8711_wx_set_rate, /* SIOCSIWRATE */
2234 r8711_wx_get_rate, /* SIOCGIWRATE */
2235 dummy, /* SIOCSIWRTS */
2236 r8711_wx_get_rts, /* SIOCGIWRTS */
2237 r8711_wx_set_frag, /* SIOCSIWFRAG */
2238 r8711_wx_get_frag, /* SIOCGIWFRAG */
2239 dummy, /* SIOCSIWTXPOW */
2240 dummy, /* SIOCGIWTXPOW */
2241 dummy, /* SIOCSIWRETRY */
2242 r8711_wx_get_retry, /* SIOCGIWRETRY */
2243 r8711_wx_set_enc, /* SIOCSIWENCODE */
2244 r8711_wx_get_enc, /* SIOCGIWENCODE */
2245 dummy, /* SIOCSIWPOWER */
2246 r8711_wx_get_power, /* SIOCGIWPOWER */
2247 NULL, /*---hole---*/
2248 NULL, /*---hole---*/
2249 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2250 NULL, /* SIOCGIWGENIE */
2251 r871x_wx_set_auth, /* SIOCSIWAUTH */
2252 NULL, /* SIOCGIWAUTH */
2253 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2254 NULL, /* SIOCGIWENCODEEXT */
2255 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2256 NULL, /*---hole---*/
2259 static const struct iw_priv_args r8711_private_args[] = {
2261 SIOCIWFIRSTPRIV + 0x0,
2262 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2265 SIOCIWFIRSTPRIV + 0x1,
2266 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2269 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2272 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2275 SIOCIWFIRSTPRIV + 0x4,
2276 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2279 SIOCIWFIRSTPRIV + 0x5,
2280 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2283 SIOCIWFIRSTPRIV + 0x6,
2284 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2287 SIOCIWFIRSTPRIV + 0x7,
2288 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2292 static iw_handler r8711_private_handler[] = {
2297 r871x_get_ap_info, /*for MM DTV platform*/
2303 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2305 struct _adapter *padapter = netdev_priv(dev);
2306 struct iw_statistics *piwstats = &padapter->iwstats;
2311 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2312 piwstats->qual.qual = 0;
2313 piwstats->qual.level = 0;
2314 piwstats->qual.noise = 0;
2316 /* show percentage, we need transfer dbm to original value. */
2317 tmp_level = padapter->recvpriv.fw_rssi;
2318 tmp_qual = padapter->recvpriv.signal;
2319 tmp_noise = padapter->recvpriv.noise;
2320 piwstats->qual.level = tmp_level;
2321 piwstats->qual.qual = tmp_qual;
2322 piwstats->qual.noise = tmp_noise;
2324 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2325 return &padapter->iwstats;
2328 struct iw_handler_def r871x_handlers_def = {
2329 .standard = r8711_handlers,
2330 .num_standard = ARRAY_SIZE(r8711_handlers),
2331 .private = r8711_private_handler,
2332 .private_args = (struct iw_priv_args *)r8711_private_args,
2333 .num_private = ARRAY_SIZE(r8711_private_handler),
2334 .num_private_args = sizeof(r8711_private_args) /
2335 sizeof(struct iw_priv_args),
2336 .get_wireless_stats = r871x_get_wireless_stats