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",
76 * hwaddr_aton - Convert ASCII string to MAC address
77 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
78 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
79 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
81 static int hwaddr_aton_i(const char *txt, u8 *addr)
85 for (i = 0; i < 6; i++) {
88 a = hex_to_bin(*txt++);
91 b = hex_to_bin(*txt++);
94 *addr++ = (a << 4) | b;
95 if (i < 5 && *txt++ != ':')
101 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
103 union iwreq_data wrqu;
104 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
106 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
107 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
109 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
112 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
114 union iwreq_data wrqu;
116 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
117 eth_zero_addr(wrqu.ap_addr.sa_data);
118 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
121 static inline void handle_pairwise_key(struct sta_info *psta,
122 struct ieee_param *param,
123 struct _adapter *padapter)
126 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
127 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
128 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
129 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
131 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
133 padapter->securitypriv. busetkipkey = false;
134 mod_timer(&padapter->securitypriv.tkip_timer,
135 jiffies + msecs_to_jiffies(50));
137 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
140 static inline void handle_group_key(struct ieee_param *param,
141 struct _adapter *padapter)
143 if (0 < param->u.crypt.idx &&
144 param->u.crypt.idx < 3) {
145 /* group key idx is 1 or 2 */
146 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
147 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
148 > 16 ? 16 : param->u.crypt.key_len));
149 memcpy(padapter->securitypriv.XGrptxmickey[param->
150 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
151 memcpy(padapter->securitypriv. XGrprxmickey[param->
152 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
153 padapter->securitypriv.binstallGrpkey = true;
154 r8712_set_key(padapter, &padapter->securitypriv,
156 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
157 if (padapter->registrypriv.power_mgnt != padapter->
158 pwrctrlpriv.pwr_mode)
159 mod_timer(&padapter->mlmepriv.dhcp_timer,
160 jiffies + msecs_to_jiffies(60000));
165 static inline char *translate_scan(struct _adapter *padapter,
166 struct iw_request_info *info,
167 struct wlan_network *pnetwork,
168 char *start, char *stop)
171 struct ieee80211_ht_cap *pht_capie;
174 u32 i = 0, ht_ielen = 0;
175 u16 cap, ht_cap = false, mcs_rate;
178 if ((pnetwork->network.Configuration.DSConfig < 1) ||
179 (pnetwork->network.Configuration.DSConfig > 14)) {
180 if (pnetwork->network.Configuration.DSConfig < 1)
181 pnetwork->network.Configuration.DSConfig = 1;
183 pnetwork->network.Configuration.DSConfig = 14;
187 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
188 ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
189 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
191 iwe.cmd = SIOCGIWESSID;
192 iwe.u.data.flags = 1;
193 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
194 start = iwe_stream_add_point(info, start, stop, &iwe,
195 pnetwork->network.Ssid.Ssid);
196 /* parsing HT_CAP_IE */
197 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
198 &ht_ielen, pnetwork->network.IELength - 12);
199 if (p && ht_ielen > 0) {
201 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
202 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
204 /* Add the protocol name */
205 iwe.cmd = SIOCGIWNAME;
206 if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
208 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
210 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
211 } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
213 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
215 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
218 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
220 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
222 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
224 iwe.cmd = SIOCGIWMODE;
225 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
227 cap = le16_to_cpu(cap);
228 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
229 if (cap & WLAN_CAPABILITY_BSS)
230 iwe.u.mode = (u32)IW_MODE_MASTER;
232 iwe.u.mode = (u32)IW_MODE_ADHOC;
233 start = iwe_stream_add_event(info, start, stop, &iwe,
236 /* Add frequency/channel */
237 iwe.cmd = SIOCGIWFREQ;
239 /* check legal index */
240 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
242 if (dsconfig >= 1 && dsconfig <= sizeof(
243 ieee80211_wlan_frequencies) / sizeof(long))
244 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
245 pnetwork->network.Configuration.
246 DSConfig - 1] * 100000);
250 iwe.u.freq.e = (s16)1;
251 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
252 start = iwe_stream_add_event(info, start, stop, &iwe,
254 /* Add encryption capability */
255 iwe.cmd = SIOCGIWENCODE;
256 if (cap & WLAN_CAPABILITY_PRIVACY)
257 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
260 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
261 iwe.u.data.length = (u16)0;
262 start = iwe_stream_add_point(info, start, stop, &iwe,
263 pnetwork->network.Ssid.Ssid);
264 /*Add basic and extended rates */
265 current_val = start + iwe_stream_lcp_len(info);
266 iwe.cmd = SIOCGIWRATE;
267 iwe.u.bitrate.fixed = 0;
268 iwe.u.bitrate.disabled = 0;
269 iwe.u.bitrate.value = 0;
271 while (pnetwork->network.rates[i] != 0) {
272 /* Bit rate given in 500 kb/s units */
273 iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
275 current_val = iwe_stream_add_value(info, start, current_val,
276 stop, &iwe, IW_EV_PARAM_LEN);
278 /* Check if we added any event */
279 if ((current_val - start) > iwe_stream_lcp_len(info))
281 /* parsing WPA/WPA2 IE */
283 u8 buf[MAX_WPA_IE_LEN];
284 u8 wpa_ie[255], rsn_ie[255];
285 u16 wpa_len = 0, rsn_len = 0;
288 r8712_get_sec_ie(pnetwork->network.IEs,
289 pnetwork->network.IELength, rsn_ie, &rsn_len,
292 memset(buf, 0, MAX_WPA_IE_LEN);
293 n = sprintf(buf, "wpa_ie=");
294 for (i = 0; i < wpa_len; i++) {
295 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
297 if (n >= MAX_WPA_IE_LEN)
300 memset(&iwe, 0, sizeof(iwe));
301 iwe.cmd = IWEVCUSTOM;
302 iwe.u.data.length = (u16)strlen(buf);
303 start = iwe_stream_add_point(info, start, stop,
305 memset(&iwe, 0, sizeof(iwe));
307 iwe.u.data.length = (u16)wpa_len;
308 start = iwe_stream_add_point(info, start, stop,
312 memset(buf, 0, MAX_WPA_IE_LEN);
313 n = sprintf(buf, "rsn_ie=");
314 for (i = 0; i < rsn_len; i++) {
315 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
317 if (n >= MAX_WPA_IE_LEN)
320 memset(&iwe, 0, sizeof(iwe));
321 iwe.cmd = IWEVCUSTOM;
322 iwe.u.data.length = strlen(buf);
323 start = iwe_stream_add_point(info, start, stop,
325 memset(&iwe, 0, sizeof(iwe));
327 iwe.u.data.length = rsn_len;
328 start = iwe_stream_add_point(info, start, stop, &iwe,
333 { /* parsing WPS IE */
337 if (r8712_get_wps_ie(pnetwork->network.IEs,
338 pnetwork->network.IELength,
339 wps_ie, &wps_ielen) == true) {
342 iwe.u.data.length = (u16)wps_ielen;
343 start = iwe_stream_add_point(info, start, stop,
348 /* Add quality statistics */
350 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
351 /* we only update signal_level (signal strength) that is rssi. */
352 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
353 IW_QUAL_NOISE_INVALID);
354 iwe.u.qual.level = rssi; /* signal strength */
355 iwe.u.qual.qual = 0; /* signal quality */
356 iwe.u.qual.noise = 0; /* noise level */
357 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
358 /* how to translate rssi to ?% */
362 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
364 struct _adapter *padapter = netdev_priv(dev);
367 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
368 padapter->securitypriv.ndisencryptstatus =
369 Ndis802_11Encryption1Enabled;
370 padapter->securitypriv.ndisauthtype =
371 Ndis802_11AuthModeAutoSwitch;
372 padapter->securitypriv.AuthAlgrthm = 3;
373 } else if (value & AUTH_ALG_SHARED_KEY) {
374 padapter->securitypriv.ndisencryptstatus =
375 Ndis802_11Encryption1Enabled;
376 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
377 padapter->securitypriv.AuthAlgrthm = 1;
378 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
379 if (padapter->securitypriv.ndisauthtype <
380 Ndis802_11AuthModeWPAPSK) {
381 padapter->securitypriv.ndisauthtype =
382 Ndis802_11AuthModeOpen;
383 padapter->securitypriv.AuthAlgrthm = 0;
390 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
394 u32 wep_key_idx, wep_key_len = 0;
395 struct NDIS_802_11_WEP *pwep = NULL;
396 struct _adapter *padapter = netdev_priv(dev);
397 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
398 struct security_priv *psecuritypriv = &padapter->securitypriv;
400 param->u.crypt.err = 0;
401 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
402 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
403 param->u.crypt.key_len)
405 if (is_broadcast_ether_addr(param->sta_addr)) {
406 if (param->u.crypt.idx >= WEP_KEYS) {
407 /* for large key indices, set the default (0) */
408 param->u.crypt.idx = 0;
412 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
413 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
414 padapter->securitypriv.ndisencryptstatus =
415 Ndis802_11Encryption1Enabled;
416 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
417 padapter->securitypriv.XGrpPrivacy = _WEP40_;
418 wep_key_idx = param->u.crypt.idx;
419 wep_key_len = param->u.crypt.key_len;
420 if (wep_key_idx >= WEP_KEYS)
422 if (wep_key_len > 0) {
423 wep_key_len = wep_key_len <= 5 ? 5 : 13;
424 pwep = kmalloc((u32)(wep_key_len +
425 FIELD_OFFSET(struct NDIS_802_11_WEP,
426 KeyMaterial)), GFP_ATOMIC);
429 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
430 pwep->KeyLength = wep_key_len;
431 pwep->Length = wep_key_len +
432 FIELD_OFFSET(struct NDIS_802_11_WEP,
434 if (wep_key_len == 13) {
435 padapter->securitypriv.PrivacyAlgrthm =
437 padapter->securitypriv.XGrpPrivacy =
442 pwep->KeyIndex = wep_key_idx;
443 pwep->KeyIndex |= 0x80000000;
444 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
445 if (param->u.crypt.set_tx) {
446 if (r8712_set_802_11_add_wep(padapter, pwep) ==
450 /* don't update "psecuritypriv->PrivacyAlgrthm" and
451 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
452 * r8712_set_key to fw/cam
454 if (wep_key_idx >= WEP_KEYS) {
458 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
459 skey[0]), pwep->KeyMaterial,
461 psecuritypriv->DefKeylen[wep_key_idx] =
463 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
467 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
468 struct sta_info *psta, *pbcmc_sta;
469 struct sta_priv *pstapriv = &padapter->stapriv;
471 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
472 WIFI_MP_STATE) == true) { /* sta mode */
473 psta = r8712_get_stainfo(pstapriv,
474 get_bssid(pmlmepriv));
476 psta->ieee8021x_blocked = false;
477 if ((padapter->securitypriv.ndisencryptstatus ==
478 Ndis802_11Encryption2Enabled) ||
479 (padapter->securitypriv.ndisencryptstatus ==
480 Ndis802_11Encryption3Enabled))
481 psta->XPrivacy = padapter->
482 securitypriv.PrivacyAlgrthm;
483 if (param->u.crypt.set_tx == 1)
484 handle_pairwise_key(psta, param,
487 handle_group_key(param, padapter);
489 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
491 pbcmc_sta->ieee8021x_blocked = false;
492 if ((padapter->securitypriv.ndisencryptstatus ==
493 Ndis802_11Encryption2Enabled) ||
494 (padapter->securitypriv.ndisencryptstatus ==
495 Ndis802_11Encryption3Enabled))
496 pbcmc_sta->XPrivacy =
497 padapter->securitypriv.
507 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
508 unsigned short ielen)
511 int group_cipher = 0, pairwise_cipher = 0;
514 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
517 buf = kmemdup(pie, ielen, GFP_ATOMIC);
520 if (ielen < RSN_HEADER_LEN) {
524 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
525 &pairwise_cipher) == _SUCCESS) {
526 padapter->securitypriv.AuthAlgrthm = 2;
527 padapter->securitypriv.ndisauthtype =
528 Ndis802_11AuthModeWPAPSK;
530 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
531 &pairwise_cipher) == _SUCCESS) {
532 padapter->securitypriv.AuthAlgrthm = 2;
533 padapter->securitypriv.ndisauthtype =
534 Ndis802_11AuthModeWPA2PSK;
536 switch (group_cipher) {
537 case WPA_CIPHER_NONE:
538 padapter->securitypriv.XGrpPrivacy =
540 padapter->securitypriv.ndisencryptstatus =
541 Ndis802_11EncryptionDisabled;
543 case WPA_CIPHER_WEP40:
544 padapter->securitypriv.XGrpPrivacy = _WEP40_;
545 padapter->securitypriv.ndisencryptstatus =
546 Ndis802_11Encryption1Enabled;
548 case WPA_CIPHER_TKIP:
549 padapter->securitypriv.XGrpPrivacy = _TKIP_;
550 padapter->securitypriv.ndisencryptstatus =
551 Ndis802_11Encryption2Enabled;
553 case WPA_CIPHER_CCMP:
554 padapter->securitypriv.XGrpPrivacy = _AES_;
555 padapter->securitypriv.ndisencryptstatus =
556 Ndis802_11Encryption3Enabled;
558 case WPA_CIPHER_WEP104:
559 padapter->securitypriv.XGrpPrivacy = _WEP104_;
560 padapter->securitypriv.ndisencryptstatus =
561 Ndis802_11Encryption1Enabled;
564 switch (pairwise_cipher) {
565 case WPA_CIPHER_NONE:
566 padapter->securitypriv.PrivacyAlgrthm =
568 padapter->securitypriv.ndisencryptstatus =
569 Ndis802_11EncryptionDisabled;
571 case WPA_CIPHER_WEP40:
572 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
573 padapter->securitypriv.ndisencryptstatus =
574 Ndis802_11Encryption1Enabled;
576 case WPA_CIPHER_TKIP:
577 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
578 padapter->securitypriv.ndisencryptstatus =
579 Ndis802_11Encryption2Enabled;
581 case WPA_CIPHER_CCMP:
582 padapter->securitypriv.PrivacyAlgrthm = _AES_;
583 padapter->securitypriv.ndisencryptstatus =
584 Ndis802_11Encryption3Enabled;
586 case WPA_CIPHER_WEP104:
587 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
588 padapter->securitypriv.ndisencryptstatus =
589 Ndis802_11Encryption1Enabled;
592 padapter->securitypriv.wps_phase = false;
595 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
597 while (cnt < ielen) {
600 if ((eid == _VENDOR_SPECIFIC_IE_) &&
601 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
602 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
603 padapter->securitypriv.wps_ie_len =
605 (MAX_WPA_IE_LEN << 2)) ?
607 (MAX_WPA_IE_LEN << 2);
608 memcpy(padapter->securitypriv.wps_ie,
610 padapter->securitypriv.wps_ie_len);
611 padapter->securitypriv.wps_phase =
613 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
617 cnt += buf[cnt + 1] + 2;
626 static int r8711_wx_get_name(struct net_device *dev,
627 struct iw_request_info *info,
628 union iwreq_data *wrqu, char *extra)
630 struct _adapter *padapter = netdev_priv(dev);
634 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
635 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
638 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
640 /* parsing HT_CAP_IE */
641 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
642 &ht_ielen, pcur_bss->IELength - 12);
643 if (p && ht_ielen > 0)
645 prates = pcur_bss->rates;
646 if (r8712_is_cckratesonly_included(prates) == true) {
648 snprintf(wrqu->name, IFNAMSIZ,
651 snprintf(wrqu->name, IFNAMSIZ,
653 } else if ((r8712_is_cckrates_included(prates)) == true) {
655 snprintf(wrqu->name, IFNAMSIZ,
658 snprintf(wrqu->name, IFNAMSIZ,
662 snprintf(wrqu->name, IFNAMSIZ,
665 snprintf(wrqu->name, IFNAMSIZ,
669 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
673 static const long frequency_list[] = {
674 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
675 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
676 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
677 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
678 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
682 static int r8711_wx_set_freq(struct net_device *dev,
683 struct iw_request_info *info,
684 union iwreq_data *wrqu, char *extra)
686 struct _adapter *padapter = netdev_priv(dev);
687 struct iw_freq *fwrq = &wrqu->freq;
690 /* If setting by frequency, convert to a channel */
691 if ((fwrq->e == 1) &&
692 (fwrq->m >= (int) 2.412e8) &&
693 (fwrq->m <= (int) 2.487e8)) {
694 int f = fwrq->m / 100000;
697 while ((c < 14) && (f != frequency_list[c]))
702 /* Setting by channel number */
703 if ((fwrq->m > 14) || (fwrq->e > 0))
706 int channel = fwrq->m;
708 if ((channel < 1) || (channel > 14))
711 /* Yes ! We can set it !!! */
712 padapter->registrypriv.channel = channel;
718 static int r8711_wx_get_freq(struct net_device *dev,
719 struct iw_request_info *info,
720 union iwreq_data *wrqu, char *extra)
722 struct _adapter *padapter = netdev_priv(dev);
723 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
724 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
726 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
727 wrqu->freq.m = ieee80211_wlan_frequencies[
728 pcur_bss->Configuration.DSConfig-1] * 100000;
730 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
737 static int r8711_wx_set_mode(struct net_device *dev,
738 struct iw_request_info *a,
739 union iwreq_data *wrqu, char *b)
741 struct _adapter *padapter = netdev_priv(dev);
742 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
744 switch (wrqu->mode) {
746 networkType = Ndis802_11AutoUnknown;
749 networkType = Ndis802_11IBSS;
752 networkType = Ndis802_11APMode;
755 networkType = Ndis802_11Infrastructure;
760 if (Ndis802_11APMode == networkType)
761 r8712_setopmode_cmd(padapter, networkType);
763 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
765 r8712_set_802_11_infrastructure_mode(padapter, networkType);
769 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
770 union iwreq_data *wrqu, char *b)
772 struct _adapter *padapter = netdev_priv(dev);
773 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
775 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
776 wrqu->mode = IW_MODE_INFRA;
777 else if (check_fwstate(pmlmepriv,
778 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
779 wrqu->mode = IW_MODE_ADHOC;
780 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
781 wrqu->mode = IW_MODE_MASTER;
783 wrqu->mode = IW_MODE_AUTO;
787 static int r871x_wx_set_pmkid(struct net_device *dev,
788 struct iw_request_info *a,
789 union iwreq_data *wrqu, char *extra)
791 struct _adapter *padapter = netdev_priv(dev);
792 struct security_priv *psecuritypriv = &padapter->securitypriv;
793 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
794 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
795 u8 strIssueBssid[ETH_ALEN] = {0x00};
796 u8 j, blInserted = false;
797 int intReturn = false;
800 There are the BSSID information in the bssid.sa_data array.
801 If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
802 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
803 wpa_supplicant wants to add a PMKID/BSSID to driver.
804 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
805 remove a PMKID/BSSID from driver.
809 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
812 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
816 /* overwrite PMKID */
817 for (j = 0; j < NUM_PMKID_CACHE; j++) {
818 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
819 strIssueBssid, ETH_ALEN)) {
820 /* BSSID is matched, the same AP => rewrite
822 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
824 memcpy(psecuritypriv->PMKIDList[j].PMKID,
825 pPMK->pmkid, IW_PMKID_LEN);
826 psecuritypriv->PMKIDList[j].bUsed = true;
827 psecuritypriv->PMKIDIndex = j + 1;
833 /* Find a new entry */
834 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
835 __func__, psecuritypriv->PMKIDIndex);
836 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
837 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
838 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
839 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
840 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
842 psecuritypriv->PMKIDIndex++;
843 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
844 psecuritypriv->PMKIDIndex = 0;
847 case IW_PMKSA_REMOVE:
849 for (j = 0; j < NUM_PMKID_CACHE; j++) {
850 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
851 strIssueBssid, ETH_ALEN)) {
852 /* BSSID is matched, the same AP => Remove
853 * this PMKID information and reset it. */
854 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
855 psecuritypriv->PMKIDList[j].bUsed = false;
861 memset(psecuritypriv->PMKIDList, 0,
862 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
863 psecuritypriv->PMKIDIndex = 0;
867 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
874 static int r8711_wx_get_sens(struct net_device *dev,
875 struct iw_request_info *info,
876 union iwreq_data *wrqu, char *extra)
878 wrqu->sens.value = 0;
879 wrqu->sens.fixed = 0; /* no auto select */
880 wrqu->sens.disabled = 1;
884 static int r8711_wx_get_range(struct net_device *dev,
885 struct iw_request_info *info,
886 union iwreq_data *wrqu, char *extra)
888 struct iw_range *range = (struct iw_range *)extra;
892 wrqu->data.length = sizeof(*range);
893 memset(range, 0, sizeof(*range));
894 /* Let's try to keep this struct in the same order as in
895 * linux/include/wireless.h
898 /* TODO: See what values we can set, and remove the ones we can't
899 * set, or fill them with some default data.
901 /* ~5 Mb/s real (802.11b) */
902 range->throughput = 5 * 1000 * 1000;
903 /* TODO: 8711 sensitivity ? */
904 /* signal level threshold range */
905 /* percent values between 0 and 100. */
906 range->max_qual.qual = 100;
907 range->max_qual.level = 100;
908 range->max_qual.noise = 100;
909 range->max_qual.updated = 7; /* Updated all three */
910 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
911 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
912 range->avg_qual.level = 20 + -98;
913 range->avg_qual.noise = 0;
914 range->avg_qual.updated = 7; /* Updated all three */
915 range->num_bitrates = RATE_COUNT;
916 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
917 range->bitrate[i] = rtl8180_rates[i];
918 range->min_frag = MIN_FRAG_THRESHOLD;
919 range->max_frag = MAX_FRAG_THRESHOLD;
921 range->we_version_compiled = WIRELESS_EXT;
922 range->we_version_source = 16;
923 range->num_channels = 14;
924 for (i = 0, val = 0; i < 14; i++) {
925 /* Include only legal frequencies for some countries */
926 range->freq[val].i = i + 1;
927 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
928 range->freq[val].e = 1;
930 if (val == IW_MAX_FREQUENCIES)
933 range->num_frequency = val;
934 range->enc_capa = IW_ENC_CAPA_WPA |
936 IW_ENC_CAPA_CIPHER_TKIP |
937 IW_ENC_CAPA_CIPHER_CCMP;
941 static int r8711_wx_get_rate(struct net_device *dev,
942 struct iw_request_info *info,
943 union iwreq_data *wrqu, char *extra);
945 static int r871x_wx_set_priv(struct net_device *dev,
946 struct iw_request_info *info,
947 union iwreq_data *awrq,
950 int ret = 0, len = 0;
952 struct _adapter *padapter = netdev_priv(dev);
953 struct iw_point *dwrq = (struct iw_point *)awrq;
956 ext = memdup_user(dwrq->pointer, len);
960 if (0 == strcasecmp(ext, "RSSI")) {
961 /*Return received signal strength indicator in -db for */
964 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
965 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
967 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
968 sprintf(ext, "%s rssi %d",
969 pcur_network->network.Ssid.Ssid,
971 ((padapter->recvpriv.fw_rssi)>>1)-95
972 /*pcur_network->network.Rssi */
977 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
978 /*Return link speed in MBPS */
980 union iwreq_data wrqd;
984 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
988 mbps = wrqd.bitrate.value / 1000000;
989 sprintf(ext, "LINKSPEED %d", mbps);
990 } else if (0 == strcasecmp(ext, "MACADDR")) {
991 /*Return mac address of the station */
992 /* Macaddr = xx:xx:xx:xx:xx:xx */
993 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
994 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
995 /*Set scan type to active */
996 /*OK if successful */
997 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
999 pmlmepriv->passive_mode = 1;
1001 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1002 /*Set scan type to passive */
1003 /*OK if successful */
1004 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1006 pmlmepriv->passive_mode = 0;
1008 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1009 /*Set scan type to passive */
1010 /*OK if successful */
1011 r8712_disconnectCtrlEx_cmd(padapter
1012 , 1 /*u32 enableDrvCtrl */
1013 , 5 /*u32 tryPktCnt */
1014 , 100 /*u32 tryPktInterval */
1015 , 5000 /*u32 firstStageTO */
1018 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1019 /*Set scan type to passive */
1020 /*OK if successfu */
1021 r8712_disconnectCtrlEx_cmd(padapter
1022 , 0 /*u32 enableDrvCtrl */
1023 , 5 /*u32 tryPktCnt */
1024 , 100 /*u32 tryPktInterval */
1025 , 5000 /*u32 firstStageTO */
1029 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1033 if (copy_to_user(dwrq->pointer, ext,
1034 min(dwrq->length, (__u16)(strlen(ext)+1))))
1043 * s1. set_802_11_infrastructure_mode()
1044 * s2. set_802_11_authentication_mode()
1045 * s3. set_802_11_encryption_mode()
1046 * s4. set_802_11_bssid()
1048 * This function intends to handle the Set AP command, which specifies the
1049 * MAC# of a preferred Access Point.
1050 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1052 * For this operation to succeed, there is no need for the interface to be up.
1055 static int r8711_wx_set_wap(struct net_device *dev,
1056 struct iw_request_info *info,
1057 union iwreq_data *awrq,
1060 int ret = -EINPROGRESS;
1061 struct _adapter *padapter = netdev_priv(dev);
1062 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1063 struct __queue *queue = &pmlmepriv->scanned_queue;
1064 struct sockaddr *temp = (struct sockaddr *)awrq;
1066 struct list_head *phead;
1068 struct wlan_network *pnetwork = NULL;
1069 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1071 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1073 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1075 if (temp->sa_family != ARPHRD_ETHER)
1077 authmode = padapter->securitypriv.ndisauthtype;
1078 spin_lock_irqsave(&queue->lock, irqL);
1079 phead = &queue->queue;
1080 pmlmepriv->pscanned = phead->next;
1082 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1084 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1085 struct wlan_network, list);
1086 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1087 dst_bssid = pnetwork->network.MacAddress;
1088 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1089 r8712_set_802_11_infrastructure_mode(padapter,
1090 pnetwork->network.InfrastructureMode);
1094 spin_unlock_irqrestore(&queue->lock, irqL);
1096 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1099 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1106 static int r8711_wx_get_wap(struct net_device *dev,
1107 struct iw_request_info *info,
1108 union iwreq_data *wrqu, char *extra)
1110 struct _adapter *padapter = netdev_priv(dev);
1111 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1112 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1114 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1115 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1117 ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
1119 eth_zero_addr(wrqu->ap_addr.sa_data);
1123 static int r871x_wx_set_mlme(struct net_device *dev,
1124 struct iw_request_info *info,
1125 union iwreq_data *wrqu, char *extra)
1128 struct _adapter *padapter = netdev_priv(dev);
1129 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1133 switch (mlme->cmd) {
1134 case IW_MLME_DEAUTH:
1135 if (!r8712_set_802_11_disassociate(padapter))
1138 case IW_MLME_DISASSOC:
1139 if (!r8712_set_802_11_disassociate(padapter))
1150 * This function intends to handle the Set Scan command.
1151 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1153 * For this operation to succeed, the interface is brought Up beforehand.
1156 static int r8711_wx_set_scan(struct net_device *dev,
1157 struct iw_request_info *a,
1158 union iwreq_data *wrqu, char *extra)
1160 struct _adapter *padapter = netdev_priv(dev);
1161 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1164 if (padapter->bDriverStopped == true) {
1165 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1166 __func__, padapter->bDriverStopped);
1169 if (padapter->bup == false)
1171 if (padapter->hw_init_completed == false)
1173 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1174 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1176 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1177 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1179 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1180 struct ndis_802_11_ssid ssid;
1182 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1184 memset((unsigned char *)&ssid, 0,
1185 sizeof(struct ndis_802_11_ssid));
1186 memcpy(ssid.Ssid, req->essid, len);
1187 ssid.SsidLength = len;
1188 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1189 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1190 _FW_UNDER_LINKING)) ||
1191 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1192 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1195 status = r8712_sitesurvey_cmd(padapter, &ssid);
1196 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1199 status = r8712_set_802_11_bssid_list_scan(padapter);
1200 if (status == false)
1205 static int r8711_wx_get_scan(struct net_device *dev,
1206 struct iw_request_info *a,
1207 union iwreq_data *wrqu, char *extra)
1209 struct _adapter *padapter = netdev_priv(dev);
1210 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1211 struct __queue *queue = &pmlmepriv->scanned_queue;
1212 struct wlan_network *pnetwork = NULL;
1214 struct list_head *plist, *phead;
1216 char *stop = ev + wrqu->data.length;
1217 u32 ret = 0, cnt = 0;
1219 if (padapter->bDriverStopped)
1221 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1227 spin_lock_irqsave(&queue->lock, irqL);
1228 phead = &queue->queue;
1229 plist = phead->next;
1231 if (end_of_queue_search(phead, plist) == true)
1233 if ((stop - ev) < SCAN_ITEM_SIZE) {
1237 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1238 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1239 plist = plist->next;
1241 spin_unlock_irqrestore(&queue->lock, irqL);
1242 wrqu->data.length = ev - extra;
1243 wrqu->data.flags = 0;
1248 * s1. set_802_11_infrastructure_mode()
1249 * s2. set_802_11_authenticaion_mode()
1250 * s3. set_802_11_encryption_mode()
1251 * s4. set_802_11_ssid()
1253 * This function intends to handle the Set ESSID command.
1254 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1256 * For this operation to succeed, there is no need for the interface to be Up.
1259 static int r8711_wx_set_essid(struct net_device *dev,
1260 struct iw_request_info *a,
1261 union iwreq_data *wrqu, char *extra)
1263 struct _adapter *padapter = netdev_priv(dev);
1264 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1265 struct __queue *queue = &pmlmepriv->scanned_queue;
1266 struct wlan_network *pnetwork = NULL;
1267 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1268 struct ndis_802_11_ssid ndis_ssid;
1269 u8 *dst_ssid, *src_ssid;
1270 struct list_head *phead;
1273 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1275 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1277 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1279 authmode = padapter->securitypriv.ndisauthtype;
1280 if (wrqu->essid.flags && wrqu->essid.length) {
1281 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1282 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1283 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1284 ndis_ssid.SsidLength = len;
1285 memcpy(ndis_ssid.Ssid, extra, len);
1286 src_ssid = ndis_ssid.Ssid;
1287 phead = &queue->queue;
1288 pmlmepriv->pscanned = phead->next;
1290 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1292 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1293 struct wlan_network, list);
1294 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1295 dst_ssid = pnetwork->network.Ssid.Ssid;
1296 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1297 && (pnetwork->network.Ssid.SsidLength ==
1298 ndis_ssid.SsidLength)) {
1299 if (check_fwstate(pmlmepriv,
1300 WIFI_ADHOC_STATE)) {
1301 if (pnetwork->network.
1305 cur_network.network.
1310 r8712_set_802_11_infrastructure_mode(
1312 pnetwork->network.InfrastructureMode);
1316 r8712_set_802_11_authentication_mode(padapter, authmode);
1317 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1319 return -EINPROGRESS;
1322 static int r8711_wx_get_essid(struct net_device *dev,
1323 struct iw_request_info *a,
1324 union iwreq_data *wrqu, char *extra)
1326 struct _adapter *padapter = netdev_priv(dev);
1327 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1328 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1331 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1332 len = pcur_bss->Ssid.SsidLength;
1333 wrqu->essid.length = len;
1334 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1335 wrqu->essid.flags = 1;
1342 static int r8711_wx_set_rate(struct net_device *dev,
1343 struct iw_request_info *a,
1344 union iwreq_data *wrqu, char *extra)
1346 struct _adapter *padapter = netdev_priv(dev);
1347 u32 target_rate = wrqu->bitrate.value;
1348 u32 fixed = wrqu->bitrate.fixed;
1350 u8 datarates[NumRates];
1351 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1354 if (target_rate == -1) {
1358 target_rate = target_rate / 100000;
1359 switch (target_rate) {
1401 for (i = 0; i < NumRates; i++) {
1402 if (ratevalue == mpdatarate[i]) {
1403 datarates[i] = mpdatarate[i];
1407 datarates[i] = 0xff;
1409 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1414 static int r8711_wx_get_rate(struct net_device *dev,
1415 struct iw_request_info *info,
1416 union iwreq_data *wrqu, char *extra)
1418 struct _adapter *padapter = netdev_priv(dev);
1419 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1420 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1421 struct ieee80211_ht_cap *pht_capie;
1422 unsigned char rf_type = padapter->registrypriv.rf_config;
1425 u16 rate, max_rate = 0, ht_cap = false;
1427 u8 bw_40MHz = 0, short_GI = 0;
1431 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1432 p = r8712_get_ie(&pcur_bss->IEs[12],
1433 _HT_CAPABILITY_IE_, &ht_ielen,
1434 pcur_bss->IELength - 12);
1435 if (p && ht_ielen > 0) {
1437 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1438 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
1439 bw_40MHz = (pht_capie->cap_info &
1440 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1441 short_GI = (pht_capie->cap_info &
1442 (IEEE80211_HT_CAP_SGI_20 |
1443 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1445 while ((pcur_bss->rates[i] != 0) &&
1446 (pcur_bss->rates[i] != 0xFF)) {
1447 rate = pcur_bss->rates[i] & 0x7F;
1448 if (rate > max_rate)
1450 wrqu->bitrate.fixed = 0; /* no auto select */
1451 wrqu->bitrate.value = rate*500000;
1454 if (ht_cap == true) {
1455 if (mcs_rate & 0x8000 /* MCS15 */
1457 RTL8712_RF_2T2R == rf_type)
1458 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1459 270) : ((short_GI) ? 144 : 130);
1460 else /* default MCS7 */
1461 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1462 135) : ((short_GI) ? 72 : 65);
1463 max_rate *= 2; /* Mbps/2 */
1465 wrqu->bitrate.value = max_rate * 500000;
1471 static int r8711_wx_get_rts(struct net_device *dev,
1472 struct iw_request_info *info,
1473 union iwreq_data *wrqu, char *extra)
1475 struct _adapter *padapter = netdev_priv(dev);
1477 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1478 wrqu->rts.fixed = 0; /* no auto select */
1482 static int r8711_wx_set_frag(struct net_device *dev,
1483 struct iw_request_info *info,
1484 union iwreq_data *wrqu, char *extra)
1486 struct _adapter *padapter = netdev_priv(dev);
1488 if (wrqu->frag.disabled)
1489 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1491 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1492 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1494 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1499 static int r8711_wx_get_frag(struct net_device *dev,
1500 struct iw_request_info *info,
1501 union iwreq_data *wrqu, char *extra)
1503 struct _adapter *padapter = netdev_priv(dev);
1505 wrqu->frag.value = padapter->xmitpriv.frag_len;
1506 wrqu->frag.fixed = 0; /* no auto select */
1510 static int r8711_wx_get_retry(struct net_device *dev,
1511 struct iw_request_info *info,
1512 union iwreq_data *wrqu, char *extra)
1514 wrqu->retry.value = 7;
1515 wrqu->retry.fixed = 0; /* no auto select */
1516 wrqu->retry.disabled = 1;
1520 static int r8711_wx_set_enc(struct net_device *dev,
1521 struct iw_request_info *info,
1522 union iwreq_data *wrqu, char *keybuf)
1525 u32 keyindex_provided;
1526 struct NDIS_802_11_WEP wep;
1527 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1528 struct iw_point *erq = &(wrqu->encoding);
1529 struct _adapter *padapter = netdev_priv(dev);
1531 key = erq->flags & IW_ENCODE_INDEX;
1532 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1533 if (erq->flags & IW_ENCODE_DISABLED) {
1534 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1535 padapter->securitypriv.ndisencryptstatus =
1536 Ndis802_11EncryptionDisabled;
1537 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1538 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1539 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1540 authmode = Ndis802_11AuthModeOpen;
1541 padapter->securitypriv.ndisauthtype = authmode;
1548 keyindex_provided = 1;
1550 keyindex_provided = 0;
1551 key = padapter->securitypriv.PrivacyKeyIndex;
1553 /* set authentication mode */
1554 if (erq->flags & IW_ENCODE_OPEN) {
1555 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1556 padapter->securitypriv.ndisencryptstatus =
1557 Ndis802_11Encryption1Enabled;
1558 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1559 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1560 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1561 authmode = Ndis802_11AuthModeOpen;
1562 padapter->securitypriv.ndisauthtype = authmode;
1563 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1565 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1566 padapter->securitypriv.ndisencryptstatus =
1567 Ndis802_11Encryption1Enabled;
1568 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1569 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1570 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1571 authmode = Ndis802_11AuthModeShared;
1572 padapter->securitypriv.ndisauthtype = authmode;
1574 padapter->securitypriv.ndisencryptstatus =
1575 Ndis802_11Encryption1Enabled;
1576 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1577 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1578 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1579 authmode = Ndis802_11AuthModeOpen;
1580 padapter->securitypriv.ndisauthtype = authmode;
1583 if (erq->length > 0) {
1584 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1585 wep.Length = wep.KeyLength +
1586 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1589 if (keyindex_provided == 1) { /* set key_id only, no given
1590 * KeyMaterial(erq->length==0).*/
1591 padapter->securitypriv.PrivacyKeyIndex = key;
1592 switch (padapter->securitypriv.DefKeylen[key]) {
1594 padapter->securitypriv.PrivacyAlgrthm =
1598 padapter->securitypriv.PrivacyAlgrthm =
1602 padapter->securitypriv.PrivacyAlgrthm =
1609 wep.KeyIndex |= 0x80000000; /* transmit key */
1610 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1611 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1616 static int r8711_wx_get_enc(struct net_device *dev,
1617 struct iw_request_info *info,
1618 union iwreq_data *wrqu, char *keybuf)
1621 struct _adapter *padapter = netdev_priv(dev);
1622 struct iw_point *erq = &(wrqu->encoding);
1623 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1625 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1626 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1628 erq->flags |= IW_ENCODE_DISABLED;
1632 key = erq->flags & IW_ENCODE_INDEX;
1638 key = padapter->securitypriv.PrivacyKeyIndex;
1640 erq->flags = key + 1;
1641 switch (padapter->securitypriv.ndisencryptstatus) {
1642 case Ndis802_11EncryptionNotSupported:
1643 case Ndis802_11EncryptionDisabled:
1645 erq->flags |= IW_ENCODE_DISABLED;
1647 case Ndis802_11Encryption1Enabled:
1648 erq->length = padapter->securitypriv.DefKeylen[key];
1650 memcpy(keybuf, padapter->securitypriv.DefKey[
1651 key].skey, padapter->securitypriv.
1653 erq->flags |= IW_ENCODE_ENABLED;
1654 if (padapter->securitypriv.ndisauthtype ==
1655 Ndis802_11AuthModeOpen)
1656 erq->flags |= IW_ENCODE_OPEN;
1657 else if (padapter->securitypriv.ndisauthtype ==
1658 Ndis802_11AuthModeShared)
1659 erq->flags |= IW_ENCODE_RESTRICTED;
1662 erq->flags |= IW_ENCODE_DISABLED;
1665 case Ndis802_11Encryption2Enabled:
1666 case Ndis802_11Encryption3Enabled:
1668 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1673 erq->flags |= IW_ENCODE_DISABLED;
1679 static int r8711_wx_get_power(struct net_device *dev,
1680 struct iw_request_info *info,
1681 union iwreq_data *wrqu, char *extra)
1683 wrqu->power.value = 0;
1684 wrqu->power.fixed = 0; /* no auto select */
1685 wrqu->power.disabled = 1;
1689 static int r871x_wx_set_gen_ie(struct net_device *dev,
1690 struct iw_request_info *info,
1691 union iwreq_data *wrqu, char *extra)
1693 struct _adapter *padapter = netdev_priv(dev);
1695 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1698 static int r871x_wx_set_auth(struct net_device *dev,
1699 struct iw_request_info *info,
1700 union iwreq_data *wrqu, char *extra)
1702 struct _adapter *padapter = netdev_priv(dev);
1703 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1708 paramid = param->flags & IW_AUTH_INDEX;
1709 paramval = param->value;
1711 case IW_AUTH_WPA_VERSION:
1713 case IW_AUTH_CIPHER_PAIRWISE:
1715 case IW_AUTH_CIPHER_GROUP:
1717 case IW_AUTH_KEY_MGMT:
1719 * ??? does not use these parameters
1722 case IW_AUTH_TKIP_COUNTERMEASURES:
1724 /* wpa_supplicant is enabling tkip countermeasure. */
1725 padapter->securitypriv.btkip_countermeasure = true;
1727 /* wpa_supplicant is disabling tkip countermeasure. */
1728 padapter->securitypriv.btkip_countermeasure = false;
1731 case IW_AUTH_DROP_UNENCRYPTED:
1734 * wpa_supplicant calls set_wpa_enabled when the driver
1735 * is loaded and unloaded, regardless of if WPA is being
1736 * used. No other calls are made which can be used to
1737 * determine if encryption will be used or not prior to
1738 * association being expected. If encryption is not being
1739 * used, drop_unencrypted is set to false, else true -- we
1740 * can use this to determine if the CAP_PRIVACY_ON bit should
1743 if (padapter->securitypriv.ndisencryptstatus ==
1744 Ndis802_11Encryption1Enabled) {
1745 /* it means init value, or using wep,
1746 * ndisencryptstatus =
1747 * Ndis802_11Encryption1Enabled,
1748 * then it needn't reset it;
1754 padapter->securitypriv.ndisencryptstatus =
1755 Ndis802_11EncryptionDisabled;
1756 padapter->securitypriv.PrivacyAlgrthm =
1758 padapter->securitypriv.XGrpPrivacy =
1760 padapter->securitypriv.AuthAlgrthm = 0;
1761 padapter->securitypriv.ndisauthtype =
1762 Ndis802_11AuthModeOpen;
1765 case IW_AUTH_80211_AUTH_ALG:
1766 ret = wpa_set_auth_algs(dev, (u32)paramval);
1768 case IW_AUTH_WPA_ENABLED:
1770 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1772 case IW_AUTH_PRIVACY_INVOKED:
1781 static int r871x_wx_set_enc_ext(struct net_device *dev,
1782 struct iw_request_info *info,
1783 union iwreq_data *wrqu, char *extra)
1785 struct iw_point *pencoding = &wrqu->encoding;
1786 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1787 struct ieee_param *param = NULL;
1792 switch (pext->alg) {
1793 case IW_ENCODE_ALG_NONE:
1796 case IW_ENCODE_ALG_WEP:
1799 case IW_ENCODE_ALG_TKIP:
1802 case IW_ENCODE_ALG_CCMP:
1809 param_len = sizeof(struct ieee_param) + pext->key_len;
1810 param = kzalloc(param_len, GFP_ATOMIC);
1813 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1814 memset(param->sta_addr, 0xff, ETH_ALEN);
1816 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1817 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1818 param->u.crypt.set_tx = 0;
1819 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1820 param->u.crypt.set_tx = 1;
1821 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1822 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1823 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1824 if (pext->key_len) {
1825 param->u.crypt.key_len = pext->key_len;
1826 memcpy(param + 1, pext + 1, pext->key_len);
1828 ret = wpa_set_encryption(dev, param, param_len);
1833 static int r871x_wx_get_nick(struct net_device *dev,
1834 struct iw_request_info *info,
1835 union iwreq_data *wrqu, char *extra)
1838 wrqu->data.length = 8;
1839 wrqu->data.flags = 1;
1840 memcpy(extra, "rtl_wifi", 8);
1845 static int r8711_wx_read32(struct net_device *dev,
1846 struct iw_request_info *info,
1847 union iwreq_data *wrqu, char *keybuf)
1849 struct _adapter *padapter = netdev_priv(dev);
1853 get_user(addr, (u32 __user *)wrqu->data.pointer);
1854 data32 = r8712_read32(padapter, addr);
1855 put_user(data32, (u32 __user *)wrqu->data.pointer);
1856 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1857 wrqu->data.flags = data32 & 0xffff;
1858 get_user(addr, (u32 __user *)wrqu->data.pointer);
1862 static int r8711_wx_write32(struct net_device *dev,
1863 struct iw_request_info *info,
1864 union iwreq_data *wrqu, char *keybuf)
1866 struct _adapter *padapter = netdev_priv(dev);
1870 get_user(addr, (u32 __user *)wrqu->data.pointer);
1871 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
1872 r8712_write32(padapter, addr, data32);
1876 static int dummy(struct net_device *dev,
1877 struct iw_request_info *a,
1878 union iwreq_data *wrqu, char *b)
1883 static int r8711_drvext_hdl(struct net_device *dev,
1884 struct iw_request_info *info,
1885 union iwreq_data *wrqu, char *extra)
1890 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1891 struct iw_request_info *info,
1892 union iwreq_data *wrqu, char *extra)
1894 struct _adapter *padapter = netdev_priv(dev);
1895 struct iw_point *p = &wrqu->data;
1896 struct oid_par_priv oid_par;
1897 struct mp_ioctl_handler *phandler;
1898 struct mp_ioctl_param *poidparam;
1899 unsigned long BytesRead, BytesWritten, BytesNeeded;
1905 if ((!p->length) || (!p->pointer))
1908 bset = (u8)(p->flags & 0xFFFF);
1910 pparmbuf = memdup_user(p->pointer, len);
1911 if (IS_ERR(pparmbuf))
1912 return PTR_ERR(pparmbuf);
1914 poidparam = (struct mp_ioctl_param *)pparmbuf;
1915 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1917 goto _r871x_mp_ioctl_hdl_exit;
1919 phandler = mp_ioctl_hdl + poidparam->subcode;
1920 if ((phandler->paramsize != 0) &&
1921 (poidparam->len < phandler->paramsize)) {
1923 goto _r871x_mp_ioctl_hdl_exit;
1925 if (phandler->oid == 0 && phandler->handler)
1926 status = phandler->handler(&oid_par);
1927 else if (phandler->handler) {
1928 oid_par.adapter_context = padapter;
1929 oid_par.oid = phandler->oid;
1930 oid_par.information_buf = poidparam->data;
1931 oid_par.information_buf_len = poidparam->len;
1936 oid_par.bytes_rw = &BytesRead;
1937 oid_par.bytes_needed = &BytesNeeded;
1938 oid_par.type_of_oid = SET_OID;
1940 oid_par.bytes_rw = &BytesWritten;
1941 oid_par.bytes_needed = &BytesNeeded;
1942 oid_par.type_of_oid = QUERY_OID;
1944 status = phandler->handler(&oid_par);
1945 /* todo:check status, BytesNeeded, etc. */
1947 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1948 __func__, poidparam->subcode, phandler->oid,
1951 goto _r871x_mp_ioctl_hdl_exit;
1953 if (bset == 0x00) { /* query info */
1954 if (copy_to_user(p->pointer, pparmbuf, len))
1959 goto _r871x_mp_ioctl_hdl_exit;
1961 _r871x_mp_ioctl_hdl_exit:
1966 static int r871x_get_ap_info(struct net_device *dev,
1967 struct iw_request_info *info,
1968 union iwreq_data *wrqu, char *extra)
1970 struct _adapter *padapter = netdev_priv(dev);
1971 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1972 struct __queue *queue = &pmlmepriv->scanned_queue;
1973 struct iw_point *pdata = &wrqu->data;
1974 struct wlan_network *pnetwork = NULL;
1975 u32 cnt = 0, wpa_ielen;
1977 struct list_head *plist, *phead;
1978 unsigned char *pbuf;
1982 if (padapter->bDriverStopped || (pdata == NULL))
1984 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1991 if (pdata->length >= 32) {
1992 if (copy_from_user(data, pdata->pointer, 32))
1996 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
1997 phead = &queue->queue;
1998 plist = phead->next;
2000 if (end_of_queue_search(phead, plist) == true)
2002 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2003 if (hwaddr_aton_i(data, bssid)) {
2004 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
2006 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2010 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
2011 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2012 /* BSSID match, then check if supporting wpa/wpa2 */
2013 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2014 &wpa_ielen, pnetwork->network.IELength-12);
2015 if (pbuf && (wpa_ielen > 0)) {
2019 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2020 &wpa_ielen, pnetwork->network.IELength-12);
2021 if (pbuf && (wpa_ielen > 0)) {
2026 plist = plist->next;
2028 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2029 if (pdata->length >= 34) {
2030 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2031 (u8 *)&pdata->flags, 1))
2037 static int r871x_set_pid(struct net_device *dev,
2038 struct iw_request_info *info,
2039 union iwreq_data *wrqu, char *extra)
2041 struct _adapter *padapter = netdev_priv(dev);
2042 struct iw_point *pdata = &wrqu->data;
2044 if ((padapter->bDriverStopped) || (pdata == NULL))
2046 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2051 static int r871x_set_chplan(struct net_device *dev,
2052 struct iw_request_info *info,
2053 union iwreq_data *wrqu, char *extra)
2056 struct _adapter *padapter = netdev_priv(dev);
2057 struct iw_point *pdata = &wrqu->data;
2060 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2064 ch_plan = (int)*extra;
2065 r8712_set_chplan_cmd(padapter, ch_plan);
2072 static int r871x_wps_start(struct net_device *dev,
2073 struct iw_request_info *info,
2074 union iwreq_data *wrqu, char *extra)
2076 struct _adapter *padapter = netdev_priv(dev);
2077 struct iw_point *pdata = &wrqu->data;
2078 u32 u32wps_start = 0;
2080 if ((padapter->bDriverStopped) || (pdata == NULL))
2082 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2084 if (u32wps_start == 0)
2085 u32wps_start = *extra;
2086 if (u32wps_start == 1) /* WPS Start */
2087 padapter->ledpriv.LedControlHandler(padapter,
2089 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2090 padapter->ledpriv.LedControlHandler(padapter,
2092 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2093 padapter->ledpriv.LedControlHandler(padapter,
2094 LED_CTL_STOP_WPS_FAIL);
2098 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2100 struct _adapter *padapter = netdev_priv(dev);
2103 case IEEE_PARAM_WPA_ENABLED:
2104 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2105 switch ((value)&0xff) {
2107 padapter->securitypriv.ndisauthtype =
2108 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2109 padapter->securitypriv.ndisencryptstatus =
2110 Ndis802_11Encryption2Enabled;
2113 padapter->securitypriv.ndisauthtype =
2114 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2115 padapter->securitypriv.ndisencryptstatus =
2116 Ndis802_11Encryption3Enabled;
2120 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2122 case IEEE_PARAM_DROP_UNENCRYPTED:
2125 * wpa_supplicant calls set_wpa_enabled when the driver
2126 * is loaded and unloaded, regardless of if WPA is being
2127 * used. No other calls are made which can be used to
2128 * determine if encryption will be used or not prior to
2129 * association being expected. If encryption is not being
2130 * used, drop_unencrypted is set to false, else true -- we
2131 * can use this to determine if the CAP_PRIVACY_ON bit should
2135 case IEEE_PARAM_PRIVACY_INVOKED:
2137 case IEEE_PARAM_AUTH_ALGS:
2138 return wpa_set_auth_algs(dev, value);
2139 case IEEE_PARAM_IEEE_802_1X:
2141 case IEEE_PARAM_WPAX_SELECT:
2142 /* added for WPA2 mixed mode */
2150 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2152 struct _adapter *padapter = netdev_priv(dev);
2155 case IEEE_MLME_STA_DEAUTH:
2156 if (!r8712_set_802_11_disassociate(padapter))
2159 case IEEE_MLME_STA_DISASSOC:
2160 if (!r8712_set_802_11_disassociate(padapter))
2169 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2171 struct ieee_param *param;
2173 struct _adapter *padapter = netdev_priv(dev);
2175 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2177 param = memdup_user(p->pointer, p->length);
2179 return PTR_ERR(param);
2180 switch (param->cmd) {
2181 case IEEE_CMD_SET_WPA_PARAM:
2182 ret = wpa_set_param(dev, param->u.wpa_param.name,
2183 param->u.wpa_param.value);
2185 case IEEE_CMD_SET_WPA_IE:
2186 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2187 (u16)param->u.wpa_ie.len);
2189 case IEEE_CMD_SET_ENCRYPTION:
2190 ret = wpa_set_encryption(dev, param, p->length);
2193 ret = wpa_mlme(dev, param->u.mlme.command,
2194 param->u.mlme.reason_code);
2200 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2206 /* based on "driver_ipw" and for hostapd */
2207 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2209 struct iwreq *wrq = (struct iwreq *)rq;
2212 case RTL_IOCTL_WPA_SUPPLICANT:
2213 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2220 static iw_handler r8711_handlers[] = {
2221 NULL, /* SIOCSIWCOMMIT */
2222 r8711_wx_get_name, /* SIOCGIWNAME */
2223 dummy, /* SIOCSIWNWID */
2224 dummy, /* SIOCGIWNWID */
2225 r8711_wx_set_freq, /* SIOCSIWFREQ */
2226 r8711_wx_get_freq, /* SIOCGIWFREQ */
2227 r8711_wx_set_mode, /* SIOCSIWMODE */
2228 r8711_wx_get_mode, /* SIOCGIWMODE */
2229 dummy, /* SIOCSIWSENS */
2230 r8711_wx_get_sens, /* SIOCGIWSENS */
2231 NULL, /* SIOCSIWRANGE */
2232 r8711_wx_get_range, /* SIOCGIWRANGE */
2233 r871x_wx_set_priv, /* SIOCSIWPRIV */
2234 NULL, /* SIOCGIWPRIV */
2235 NULL, /* SIOCSIWSTATS */
2236 NULL, /* SIOCGIWSTATS */
2237 dummy, /* SIOCSIWSPY */
2238 dummy, /* SIOCGIWSPY */
2239 NULL, /* SIOCGIWTHRSPY */
2240 NULL, /* SIOCWIWTHRSPY */
2241 r8711_wx_set_wap, /* SIOCSIWAP */
2242 r8711_wx_get_wap, /* SIOCGIWAP */
2243 r871x_wx_set_mlme, /* request MLME operation;
2244 * uses struct iw_mlme */
2245 dummy, /* SIOCGIWAPLIST -- deprecated */
2246 r8711_wx_set_scan, /* SIOCSIWSCAN */
2247 r8711_wx_get_scan, /* SIOCGIWSCAN */
2248 r8711_wx_set_essid, /* SIOCSIWESSID */
2249 r8711_wx_get_essid, /* SIOCGIWESSID */
2250 dummy, /* SIOCSIWNICKN */
2251 r871x_wx_get_nick, /* SIOCGIWNICKN */
2252 NULL, /* -- hole -- */
2253 NULL, /* -- hole -- */
2254 r8711_wx_set_rate, /* SIOCSIWRATE */
2255 r8711_wx_get_rate, /* SIOCGIWRATE */
2256 dummy, /* SIOCSIWRTS */
2257 r8711_wx_get_rts, /* SIOCGIWRTS */
2258 r8711_wx_set_frag, /* SIOCSIWFRAG */
2259 r8711_wx_get_frag, /* SIOCGIWFRAG */
2260 dummy, /* SIOCSIWTXPOW */
2261 dummy, /* SIOCGIWTXPOW */
2262 dummy, /* SIOCSIWRETRY */
2263 r8711_wx_get_retry, /* SIOCGIWRETRY */
2264 r8711_wx_set_enc, /* SIOCSIWENCODE */
2265 r8711_wx_get_enc, /* SIOCGIWENCODE */
2266 dummy, /* SIOCSIWPOWER */
2267 r8711_wx_get_power, /* SIOCGIWPOWER */
2268 NULL, /*---hole---*/
2269 NULL, /*---hole---*/
2270 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2271 NULL, /* SIOCGIWGENIE */
2272 r871x_wx_set_auth, /* SIOCSIWAUTH */
2273 NULL, /* SIOCGIWAUTH */
2274 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2275 NULL, /* SIOCGIWENCODEEXT */
2276 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2277 NULL, /*---hole---*/
2280 static const struct iw_priv_args r8711_private_args[] = {
2282 SIOCIWFIRSTPRIV + 0x0,
2283 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2286 SIOCIWFIRSTPRIV + 0x1,
2287 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2290 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2293 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2296 SIOCIWFIRSTPRIV + 0x4,
2297 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2300 SIOCIWFIRSTPRIV + 0x5,
2301 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2304 SIOCIWFIRSTPRIV + 0x6,
2305 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2308 SIOCIWFIRSTPRIV + 0x7,
2309 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2313 static iw_handler r8711_private_handler[] = {
2318 r871x_get_ap_info, /*for MM DTV platform*/
2324 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2326 struct _adapter *padapter = netdev_priv(dev);
2327 struct iw_statistics *piwstats = &padapter->iwstats;
2332 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2333 piwstats->qual.qual = 0;
2334 piwstats->qual.level = 0;
2335 piwstats->qual.noise = 0;
2337 /* show percentage, we need transfer dbm to orignal value. */
2338 tmp_level = padapter->recvpriv.fw_rssi;
2339 tmp_qual = padapter->recvpriv.signal;
2340 tmp_noise = padapter->recvpriv.noise;
2341 piwstats->qual.level = tmp_level;
2342 piwstats->qual.qual = tmp_qual;
2343 piwstats->qual.noise = tmp_noise;
2345 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2346 return &padapter->iwstats;
2349 struct iw_handler_def r871x_handlers_def = {
2350 .standard = r8711_handlers,
2351 .num_standard = ARRAY_SIZE(r8711_handlers),
2352 .private = r8711_private_handler,
2353 .private_args = (struct iw_priv_args *)r8711_private_args,
2354 .num_private = ARRAY_SIZE(r8711_private_handler),
2355 .num_private_args = sizeof(r8711_private_args) /
2356 sizeof(struct iw_priv_args),
2357 .get_wireless_stats = r871x_get_wireless_stats