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 union Keytype *gk = padapter->securitypriv.XGrpKey;
118 union Keytype *gtk = padapter->securitypriv.XGrptxmickey;
119 union Keytype *grk = padapter->securitypriv.XGrprxmickey;
121 if (param->u.crypt.idx > 0 &&
122 param->u.crypt.idx < 3) {
123 /* group key idx is 1 or 2 */
124 memcpy(gk[param->u.crypt.idx - 1].skey,
126 (param->u.crypt.key_len > 16 ? 16 :
127 param->u.crypt.key_len));
128 memcpy(gtk[param->u.crypt.idx - 1].skey,
129 ¶m->u.crypt.key[16], 8);
130 memcpy(grk[param->u.crypt.idx - 1].skey,
131 ¶m->u.crypt.key[24], 8);
132 padapter->securitypriv.binstallGrpkey = true;
133 r8712_set_key(padapter, &padapter->securitypriv,
135 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
136 if (padapter->registrypriv.power_mgnt !=
137 padapter->pwrctrlpriv.pwr_mode)
138 mod_timer(&padapter->mlmepriv.dhcp_timer,
139 jiffies + msecs_to_jiffies(60000));
144 static noinline_for_stack char *translate_scan(struct _adapter *padapter,
145 struct iw_request_info *info,
146 struct wlan_network *pnetwork,
147 char *start, char *stop)
150 struct ieee80211_ht_cap *pht_capie;
153 u32 i = 0, ht_ielen = 0;
154 u16 cap, ht_cap = false, mcs_rate;
157 if ((pnetwork->network.Configuration.DSConfig < 1) ||
158 (pnetwork->network.Configuration.DSConfig > 14)) {
159 if (pnetwork->network.Configuration.DSConfig < 1)
160 pnetwork->network.Configuration.DSConfig = 1;
162 pnetwork->network.Configuration.DSConfig = 14;
166 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
167 ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
168 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
170 iwe.cmd = SIOCGIWESSID;
171 iwe.u.data.flags = 1;
172 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
173 start = iwe_stream_add_point(info, start, stop, &iwe,
174 pnetwork->network.Ssid.Ssid);
175 /* parsing HT_CAP_IE */
176 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
177 &ht_ielen, pnetwork->network.IELength - 12);
178 if (p && ht_ielen > 0) {
180 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
181 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
183 /* Add the protocol name */
184 iwe.cmd = SIOCGIWNAME;
185 if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
187 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
189 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
190 } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
192 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
194 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
197 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
199 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
201 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
203 iwe.cmd = SIOCGIWMODE;
204 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
207 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
208 if (cap & WLAN_CAPABILITY_BSS)
209 iwe.u.mode = (u32)IW_MODE_MASTER;
211 iwe.u.mode = (u32)IW_MODE_ADHOC;
212 start = iwe_stream_add_event(info, start, stop, &iwe,
215 /* Add frequency/channel */
216 iwe.cmd = SIOCGIWFREQ;
218 /* check legal index */
219 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
221 if (dsconfig >= 1 && dsconfig <= sizeof(
222 ieee80211_wlan_frequencies) / sizeof(long))
224 (s32)(ieee80211_wlan_frequencies
225 [dsconfig - 1] * 100000);
229 iwe.u.freq.e = (s16)1;
230 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
231 start = iwe_stream_add_event(info, start, stop, &iwe,
233 /* Add encryption capability */
234 iwe.cmd = SIOCGIWENCODE;
235 if (cap & WLAN_CAPABILITY_PRIVACY)
236 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
239 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
240 iwe.u.data.length = (u16)0;
241 start = iwe_stream_add_point(info, start, stop, &iwe,
242 pnetwork->network.Ssid.Ssid);
243 /*Add basic and extended rates */
244 current_val = start + iwe_stream_lcp_len(info);
245 iwe.cmd = SIOCGIWRATE;
246 iwe.u.bitrate.fixed = 0;
247 iwe.u.bitrate.disabled = 0;
248 iwe.u.bitrate.value = 0;
250 while (pnetwork->network.rates[i] != 0) {
251 /* Bit rate given in 500 kb/s units */
252 iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
254 current_val = iwe_stream_add_value(info, start, current_val,
255 stop, &iwe, IW_EV_PARAM_LEN);
257 /* Check if we added any event */
258 if ((current_val - start) > iwe_stream_lcp_len(info))
260 /* parsing WPA/WPA2 IE */
262 u8 buf[MAX_WPA_IE_LEN];
263 u8 wpa_ie[255], rsn_ie[255];
264 u16 wpa_len = 0, rsn_len = 0;
267 r8712_get_sec_ie(pnetwork->network.IEs,
268 pnetwork->network.IELength, rsn_ie, &rsn_len,
271 memset(buf, 0, MAX_WPA_IE_LEN);
272 n = sprintf(buf, "wpa_ie=");
273 for (i = 0; i < wpa_len; i++) {
274 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
276 if (n >= MAX_WPA_IE_LEN)
279 memset(&iwe, 0, sizeof(iwe));
280 iwe.cmd = IWEVCUSTOM;
281 iwe.u.data.length = (u16)strlen(buf);
282 start = iwe_stream_add_point(info, start, stop,
284 memset(&iwe, 0, sizeof(iwe));
286 iwe.u.data.length = (u16)wpa_len;
287 start = iwe_stream_add_point(info, start, stop,
291 memset(buf, 0, MAX_WPA_IE_LEN);
292 n = sprintf(buf, "rsn_ie=");
293 for (i = 0; i < rsn_len; i++) {
294 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
296 if (n >= MAX_WPA_IE_LEN)
299 memset(&iwe, 0, sizeof(iwe));
300 iwe.cmd = IWEVCUSTOM;
301 iwe.u.data.length = strlen(buf);
302 start = iwe_stream_add_point(info, start, stop,
304 memset(&iwe, 0, sizeof(iwe));
306 iwe.u.data.length = rsn_len;
307 start = iwe_stream_add_point(info, start, stop, &iwe,
312 { /* parsing WPS IE */
316 if (r8712_get_wps_ie(pnetwork->network.IEs,
317 pnetwork->network.IELength,
318 wps_ie, &wps_ielen)) {
321 iwe.u.data.length = (u16)wps_ielen;
322 start = iwe_stream_add_point(info, start, stop,
327 /* Add quality statistics */
329 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
330 /* we only update signal_level (signal strength) that is rssi. */
331 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
332 IW_QUAL_NOISE_INVALID);
333 iwe.u.qual.level = rssi; /* signal strength */
334 iwe.u.qual.qual = 0; /* signal quality */
335 iwe.u.qual.noise = 0; /* noise level */
336 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
337 /* how to translate rssi to ?% */
341 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
343 struct _adapter *padapter = netdev_priv(dev);
346 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
347 padapter->securitypriv.ndisencryptstatus =
348 Ndis802_11Encryption1Enabled;
349 padapter->securitypriv.ndisauthtype =
350 Ndis802_11AuthModeAutoSwitch;
351 padapter->securitypriv.AuthAlgrthm = 3;
352 } else if (value & AUTH_ALG_SHARED_KEY) {
353 padapter->securitypriv.ndisencryptstatus =
354 Ndis802_11Encryption1Enabled;
355 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
356 padapter->securitypriv.AuthAlgrthm = 1;
357 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
358 if (padapter->securitypriv.ndisauthtype <
359 Ndis802_11AuthModeWPAPSK) {
360 padapter->securitypriv.ndisauthtype =
361 Ndis802_11AuthModeOpen;
362 padapter->securitypriv.AuthAlgrthm = 0;
370 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
374 u32 wep_key_idx, wep_key_len = 0;
375 struct NDIS_802_11_WEP *pwep = NULL;
376 struct _adapter *padapter = netdev_priv(dev);
377 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
378 struct security_priv *psecuritypriv = &padapter->securitypriv;
380 param->u.crypt.err = 0;
381 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
382 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
383 param->u.crypt.key_len)
385 if (!is_broadcast_ether_addr(param->sta_addr))
388 if (param->u.crypt.idx >= WEP_KEYS) {
389 /* for large key indices, set the default (0) */
390 param->u.crypt.idx = 0;
392 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
393 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
394 padapter->securitypriv.ndisencryptstatus =
395 Ndis802_11Encryption1Enabled;
396 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
397 padapter->securitypriv.XGrpPrivacy = _WEP40_;
398 wep_key_idx = param->u.crypt.idx;
399 wep_key_len = param->u.crypt.key_len;
400 if (wep_key_idx >= WEP_KEYS)
402 if (wep_key_len <= 0)
405 wep_key_len = wep_key_len <= 5 ? 5 : 13;
406 pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
409 pwep->KeyLength = wep_key_len;
410 pwep->Length = wep_key_len +
411 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
412 if (wep_key_len == 13) {
413 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
414 padapter->securitypriv.XGrpPrivacy = _WEP104_;
416 pwep->KeyIndex = wep_key_idx;
417 pwep->KeyIndex |= 0x80000000;
418 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
419 if (param->u.crypt.set_tx) {
420 if (r8712_set_802_11_add_wep(padapter, pwep) ==
424 /* don't update "psecuritypriv->PrivacyAlgrthm" and
425 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
426 * r8712_set_key to fw/cam
428 if (wep_key_idx >= WEP_KEYS) {
432 memcpy(&psecuritypriv->DefKey[wep_key_idx].skey[0],
435 psecuritypriv->DefKeylen[wep_key_idx] =
437 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
441 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
442 struct sta_info *psta, *pbcmc_sta;
443 struct sta_priv *pstapriv = &padapter->stapriv;
444 struct security_priv *spriv = &padapter->securitypriv;
446 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
447 WIFI_MP_STATE)) { /* sta mode */
448 psta = r8712_get_stainfo(pstapriv,
449 get_bssid(pmlmepriv));
451 psta->ieee8021x_blocked = false;
452 if (spriv->ndisencryptstatus ==
453 Ndis802_11Encryption2Enabled ||
454 spriv->ndisencryptstatus ==
455 Ndis802_11Encryption3Enabled)
456 psta->XPrivacy = spriv->PrivacyAlgrthm;
457 if (param->u.crypt.set_tx == 1)
458 handle_pairwise_key(psta, param,
461 handle_group_key(param, padapter);
463 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
465 pbcmc_sta->ieee8021x_blocked = false;
466 if (spriv->ndisencryptstatus ==
467 Ndis802_11Encryption2Enabled ||
468 spriv->ndisencryptstatus ==
469 Ndis802_11Encryption3Enabled)
470 pbcmc_sta->XPrivacy =
471 spriv->PrivacyAlgrthm;
480 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
481 unsigned short ielen)
484 int group_cipher = 0, pairwise_cipher = 0;
487 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
490 buf = kmemdup(pie, ielen, GFP_ATOMIC);
493 if (ielen < RSN_HEADER_LEN) {
497 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
498 &pairwise_cipher) == _SUCCESS) {
499 padapter->securitypriv.AuthAlgrthm = 2;
500 padapter->securitypriv.ndisauthtype =
501 Ndis802_11AuthModeWPAPSK;
503 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
504 &pairwise_cipher) == _SUCCESS) {
505 padapter->securitypriv.AuthAlgrthm = 2;
506 padapter->securitypriv.ndisauthtype =
507 Ndis802_11AuthModeWPA2PSK;
509 switch (group_cipher) {
510 case WPA_CIPHER_NONE:
511 padapter->securitypriv.XGrpPrivacy =
513 padapter->securitypriv.ndisencryptstatus =
514 Ndis802_11EncryptionDisabled;
516 case WPA_CIPHER_WEP40:
517 padapter->securitypriv.XGrpPrivacy = _WEP40_;
518 padapter->securitypriv.ndisencryptstatus =
519 Ndis802_11Encryption1Enabled;
521 case WPA_CIPHER_TKIP:
522 padapter->securitypriv.XGrpPrivacy = _TKIP_;
523 padapter->securitypriv.ndisencryptstatus =
524 Ndis802_11Encryption2Enabled;
526 case WPA_CIPHER_CCMP:
527 padapter->securitypriv.XGrpPrivacy = _AES_;
528 padapter->securitypriv.ndisencryptstatus =
529 Ndis802_11Encryption3Enabled;
531 case WPA_CIPHER_WEP104:
532 padapter->securitypriv.XGrpPrivacy = _WEP104_;
533 padapter->securitypriv.ndisencryptstatus =
534 Ndis802_11Encryption1Enabled;
537 switch (pairwise_cipher) {
538 case WPA_CIPHER_NONE:
539 padapter->securitypriv.PrivacyAlgrthm =
541 padapter->securitypriv.ndisencryptstatus =
542 Ndis802_11EncryptionDisabled;
544 case WPA_CIPHER_WEP40:
545 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
546 padapter->securitypriv.ndisencryptstatus =
547 Ndis802_11Encryption1Enabled;
549 case WPA_CIPHER_TKIP:
550 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
551 padapter->securitypriv.ndisencryptstatus =
552 Ndis802_11Encryption2Enabled;
554 case WPA_CIPHER_CCMP:
555 padapter->securitypriv.PrivacyAlgrthm = _AES_;
556 padapter->securitypriv.ndisencryptstatus =
557 Ndis802_11Encryption3Enabled;
559 case WPA_CIPHER_WEP104:
560 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
561 padapter->securitypriv.ndisencryptstatus =
562 Ndis802_11Encryption1Enabled;
565 padapter->securitypriv.wps_phase = false;
568 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
570 while (cnt < ielen) {
573 if ((eid == _VENDOR_SPECIFIC_IE_) &&
574 (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
575 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
576 padapter->securitypriv.wps_ie_len =
577 ((buf[cnt + 1] + 2) <
578 (MAX_WPA_IE_LEN << 2)) ?
580 (MAX_WPA_IE_LEN << 2);
581 memcpy(padapter->securitypriv.wps_ie,
583 padapter->securitypriv.wps_ie_len);
584 padapter->securitypriv.wps_phase =
586 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
587 cnt += buf[cnt + 1] + 2;
591 cnt += buf[cnt + 1] + 2;
600 static int r8711_wx_get_name(struct net_device *dev,
601 struct iw_request_info *info,
602 union iwreq_data *wrqu, char *extra)
604 struct _adapter *padapter = netdev_priv(dev);
608 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
609 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
612 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
614 /* parsing HT_CAP_IE */
615 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
616 &ht_ielen, pcur_bss->IELength - 12);
617 if (p && ht_ielen > 0)
619 prates = pcur_bss->rates;
620 if (r8712_is_cckratesonly_included(prates)) {
622 snprintf(wrqu->name, IFNAMSIZ,
625 snprintf(wrqu->name, IFNAMSIZ,
627 } else if (r8712_is_cckrates_included(prates)) {
629 snprintf(wrqu->name, IFNAMSIZ,
632 snprintf(wrqu->name, IFNAMSIZ,
636 snprintf(wrqu->name, IFNAMSIZ,
639 snprintf(wrqu->name, IFNAMSIZ,
643 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
648 static const long frequency_list[] = {
649 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
650 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
651 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
652 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
653 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
657 static int r8711_wx_set_freq(struct net_device *dev,
658 struct iw_request_info *info,
659 union iwreq_data *wrqu, char *extra)
661 struct _adapter *padapter = netdev_priv(dev);
662 struct iw_freq *fwrq = &wrqu->freq;
665 /* If setting by frequency, convert to a channel */
666 if ((fwrq->e == 1) &&
667 (fwrq->m >= (int) 2.412e8) &&
668 (fwrq->m <= (int) 2.487e8)) {
669 int f = fwrq->m / 100000;
672 while ((c < 14) && (f != frequency_list[c]))
677 /* Setting by channel number */
678 if ((fwrq->m > 14) || (fwrq->e > 0)) {
681 int channel = fwrq->m;
683 if ((channel < 1) || (channel > 14)) {
686 /* Yes ! We can set it !!! */
687 padapter->registrypriv.channel = channel;
693 static int r8711_wx_get_freq(struct net_device *dev,
694 struct iw_request_info *info,
695 union iwreq_data *wrqu, char *extra)
697 struct _adapter *padapter = netdev_priv(dev);
698 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
699 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
701 if (!check_fwstate(pmlmepriv, _FW_LINKED))
704 wrqu->freq.m = ieee80211_wlan_frequencies[
705 pcur_bss->Configuration.DSConfig - 1] * 100000;
707 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
712 static int r8711_wx_set_mode(struct net_device *dev,
713 struct iw_request_info *a,
714 union iwreq_data *wrqu, char *b)
716 struct _adapter *padapter = netdev_priv(dev);
717 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
719 switch (wrqu->mode) {
721 networkType = Ndis802_11AutoUnknown;
724 networkType = Ndis802_11IBSS;
727 networkType = Ndis802_11APMode;
730 networkType = Ndis802_11Infrastructure;
735 if (Ndis802_11APMode == networkType)
736 r8712_setopmode_cmd(padapter, networkType);
738 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
740 r8712_set_802_11_infrastructure_mode(padapter, networkType);
744 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
745 union iwreq_data *wrqu, char *b)
747 struct _adapter *padapter = netdev_priv(dev);
748 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
750 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
751 wrqu->mode = IW_MODE_INFRA;
752 else if (check_fwstate(pmlmepriv,
753 WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
754 wrqu->mode = IW_MODE_ADHOC;
755 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
756 wrqu->mode = IW_MODE_MASTER;
758 wrqu->mode = IW_MODE_AUTO;
762 static int r871x_wx_set_pmkid(struct net_device *dev,
763 struct iw_request_info *a,
764 union iwreq_data *wrqu, char *extra)
766 struct _adapter *padapter = netdev_priv(dev);
767 struct security_priv *psecuritypriv = &padapter->securitypriv;
768 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
769 struct RT_PMKID_LIST *pl = psecuritypriv->PMKIDList;
770 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
771 u8 strIssueBssid[ETH_ALEN] = {0x00};
772 u8 j, blInserted = false;
773 int intReturn = false;
776 * There are the BSSID information in the bssid.sa_data array.
777 * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
778 * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
779 * wpa_supplicant wants to add a PMKID/BSSID to driver.
780 * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
781 * remove a PMKID/BSSID from driver.
785 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
788 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
792 /* overwrite PMKID */
793 for (j = 0; j < NUM_PMKID_CACHE; j++) {
794 if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
795 /* BSSID is matched, the same AP => rewrite
798 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
800 memcpy(pl[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
802 psecuritypriv->PMKIDIndex = j + 1;
808 /* Find a new entry */
809 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
810 __func__, psecuritypriv->PMKIDIndex);
811 memcpy(pl[psecuritypriv->PMKIDIndex].Bssid,
812 strIssueBssid, ETH_ALEN);
813 memcpy(pl[psecuritypriv->PMKIDIndex].PMKID,
814 pPMK->pmkid, IW_PMKID_LEN);
815 pl[psecuritypriv->PMKIDIndex].bUsed = true;
816 psecuritypriv->PMKIDIndex++;
817 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
818 psecuritypriv->PMKIDIndex = 0;
821 case IW_PMKSA_REMOVE:
823 for (j = 0; j < NUM_PMKID_CACHE; j++) {
824 if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
825 /* BSSID is matched, the same AP => Remove
826 * this PMKID information and reset it.
828 eth_zero_addr(pl[j].Bssid);
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);
1601 union Keytype *dk = padapter->securitypriv.DefKey;
1603 if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
1604 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1606 erq->flags |= IW_ENCODE_DISABLED;
1610 key = erq->flags & IW_ENCODE_INDEX;
1616 key = padapter->securitypriv.PrivacyKeyIndex;
1618 erq->flags = key + 1;
1619 switch (padapter->securitypriv.ndisencryptstatus) {
1620 case Ndis802_11EncryptionNotSupported:
1621 case Ndis802_11EncryptionDisabled:
1623 erq->flags |= IW_ENCODE_DISABLED;
1625 case Ndis802_11Encryption1Enabled:
1626 erq->length = padapter->securitypriv.DefKeylen[key];
1628 memcpy(keybuf, dk[key].skey,
1629 padapter->securitypriv.DefKeylen[key]);
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