1 /******************************************************************************
2 * rtl871x_ioctl_linux.c
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.h"
37 #include "rtl871x_mlme.h"
38 #include "rtl871x_ioctl.h"
39 #include "rtl871x_ioctl_set.h"
40 #include "rtl871x_mp_ioctl.h"
41 #include "mlme_osdep.h"
42 #include <linux/wireless.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/init.h>
47 #include <linux/semaphore.h>
48 #include <net/iw_handler.h>
49 #include <linux/if_arp.h>
51 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
53 #define SCAN_ITEM_SIZE 768
54 #define MAX_CUSTOM_LEN 64
58 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
59 6000000, 9000000, 12000000, 18000000,
60 24000000, 36000000, 48000000, 54000000};
62 static const long ieee80211_wlan_frequencies[] = {
63 2412, 2417, 2422, 2427,
64 2432, 2437, 2442, 2447,
65 2452, 2457, 2462, 2467,
69 static const char * const iw_operation_mode[] = {
70 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
75 * hwaddr_aton - Convert ASCII string to MAC address
76 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
77 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
78 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
80 static int hwaddr_aton_i(const char *txt, u8 *addr)
84 for (i = 0; i < 6; i++) {
87 a = hex_to_bin(*txt++);
90 b = hex_to_bin(*txt++);
93 *addr++ = (a << 4) | b;
94 if (i < 5 && *txt++ != ':')
100 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
102 union iwreq_data wrqu;
103 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
105 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
106 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
108 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
111 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
113 union iwreq_data wrqu;
115 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
116 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
117 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
120 static inline void handle_pairwise_key(struct sta_info *psta,
121 struct ieee_param *param,
122 struct _adapter *padapter)
125 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
126 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
127 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
128 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
130 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
132 padapter->securitypriv. busetkipkey = false;
133 _set_timer(&padapter->securitypriv.tkip_timer, 50);
135 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
138 static inline void handle_group_key(struct ieee_param *param,
139 struct _adapter *padapter)
141 if (0 < param->u.crypt.idx &&
142 param->u.crypt.idx < 3) {
143 /* group key idx is 1 or 2 */
144 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
145 idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
146 > 16 ? 16 : param->u.crypt.key_len));
147 memcpy(padapter->securitypriv.XGrptxmickey[param->
148 u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
149 memcpy(padapter->securitypriv. XGrprxmickey[param->
150 u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
151 padapter->securitypriv.binstallGrpkey = true;
152 r8712_set_key(padapter, &padapter->securitypriv,
154 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
155 if (padapter->registrypriv.power_mgnt != padapter->
156 pwrctrlpriv.pwr_mode)
157 _set_timer(&(padapter->mlmepriv.dhcp_timer),
163 static inline char *translate_scan(struct _adapter *padapter,
164 struct iw_request_info *info,
165 struct wlan_network *pnetwork,
166 char *start, char *stop)
169 struct ieee80211_ht_cap *pht_capie;
172 u32 i = 0, ht_ielen = 0;
173 u16 cap, ht_cap = false, mcs_rate;
174 u8 rssi, bw_40MHz = 0, short_GI = 0;
176 if ((pnetwork->network.Configuration.DSConfig < 1) ||
177 (pnetwork->network.Configuration.DSConfig > 14)) {
178 if (pnetwork->network.Configuration.DSConfig < 1)
179 pnetwork->network.Configuration.DSConfig = 1;
181 pnetwork->network.Configuration.DSConfig = 14;
185 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
186 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
187 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
189 iwe.cmd = SIOCGIWESSID;
190 iwe.u.data.flags = 1;
191 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
192 start = iwe_stream_add_point(info, start, stop, &iwe,
193 pnetwork->network.Ssid.Ssid);
194 /* parsing HT_CAP_IE */
195 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
196 &ht_ielen, pnetwork->network.IELength - 12);
197 if (p && ht_ielen > 0) {
199 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
200 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
201 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
203 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
204 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
206 /* Add the protocol name */
207 iwe.cmd = SIOCGIWNAME;
208 if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
209 SupportedRates)) == true) {
211 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
213 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
214 } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
215 SupportedRates)) == true) {
217 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
219 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
222 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
224 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
226 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
228 iwe.cmd = SIOCGIWMODE;
229 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
231 cap = le16_to_cpu(cap);
232 if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
233 if (cap & WLAN_CAPABILITY_BSS)
234 iwe.u.mode = (u32)IW_MODE_MASTER;
236 iwe.u.mode = (u32)IW_MODE_ADHOC;
237 start = iwe_stream_add_event(info, start, stop, &iwe,
240 /* Add frequency/channel */
241 iwe.cmd = SIOCGIWFREQ;
243 /* check legal index */
244 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
245 if (dsconfig >= 1 && dsconfig <= sizeof(
246 ieee80211_wlan_frequencies) / sizeof(long))
247 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
248 pnetwork->network.Configuration.
249 DSConfig - 1] * 100000);
253 iwe.u.freq.e = (s16)1;
254 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
255 start = iwe_stream_add_event(info, start, stop, &iwe,
257 /* Add encryption capability */
258 iwe.cmd = SIOCGIWENCODE;
259 if (cap & WLAN_CAPABILITY_PRIVACY)
260 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
263 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
264 iwe.u.data.length = (u16)0;
265 start = iwe_stream_add_point(info, start, stop, &iwe,
266 pnetwork->network.Ssid.Ssid);
267 /*Add basic and extended rates */
268 current_val = start + iwe_stream_lcp_len(info);
269 iwe.cmd = SIOCGIWRATE;
270 iwe.u.bitrate.fixed = 0;
271 iwe.u.bitrate.disabled = 0;
272 iwe.u.bitrate.value = 0;
274 while (pnetwork->network.SupportedRates[i] != 0) {
275 /* Bit rate given in 500 kb/s units */
276 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
278 current_val = iwe_stream_add_value(info, start, current_val,
279 stop, &iwe, IW_EV_PARAM_LEN);
281 /* Check if we added any event */
282 if ((current_val - start) > iwe_stream_lcp_len(info))
284 /* parsing WPA/WPA2 IE */
286 u8 buf[MAX_WPA_IE_LEN];
287 u8 wpa_ie[255], rsn_ie[255];
288 u16 wpa_len = 0, rsn_len = 0;
291 out_len = r8712_get_sec_ie(pnetwork->network.IEs,
293 IELength, rsn_ie, &rsn_len,
296 memset(buf, 0, MAX_WPA_IE_LEN);
297 n = sprintf(buf, "wpa_ie=");
298 for (i = 0; i < wpa_len; i++) {
299 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
301 if (n >= MAX_WPA_IE_LEN)
304 memset(&iwe, 0, sizeof(iwe));
305 iwe.cmd = IWEVCUSTOM;
306 iwe.u.data.length = (u16)strlen(buf);
307 start = iwe_stream_add_point(info, start, stop,
309 memset(&iwe, 0, sizeof(iwe));
311 iwe.u.data.length = (u16)wpa_len;
312 start = iwe_stream_add_point(info, start, stop,
316 memset(buf, 0, MAX_WPA_IE_LEN);
317 n = sprintf(buf, "rsn_ie=");
318 for (i = 0; i < rsn_len; i++) {
319 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
321 if (n >= MAX_WPA_IE_LEN)
324 memset(&iwe, 0, sizeof(iwe));
325 iwe.cmd = IWEVCUSTOM;
326 iwe.u.data.length = strlen(buf);
327 start = iwe_stream_add_point(info, start, stop,
329 memset(&iwe, 0, sizeof(iwe));
331 iwe.u.data.length = rsn_len;
332 start = iwe_stream_add_point(info, start, stop, &iwe,
337 { /* parsing WPS IE */
341 if (r8712_get_wps_ie(pnetwork->network.IEs,
342 pnetwork->network.IELength,
343 wps_ie, &wps_ielen) == true) {
346 iwe.u.data.length = (u16)wps_ielen;
347 start = iwe_stream_add_point(info, start, stop,
352 /* Add quality statistics */
354 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
355 /* we only update signal_level (signal strength) that is rssi. */
356 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
357 IW_QUAL_NOISE_INVALID);
358 iwe.u.qual.level = rssi; /* signal strength */
359 iwe.u.qual.qual = 0; /* signal quality */
360 iwe.u.qual.noise = 0; /* noise level */
361 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
362 /* how to translate rssi to ?% */
366 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
368 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
371 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
372 padapter->securitypriv.ndisencryptstatus =
373 Ndis802_11Encryption1Enabled;
374 padapter->securitypriv.ndisauthtype =
375 Ndis802_11AuthModeAutoSwitch;
376 padapter->securitypriv.AuthAlgrthm = 3;
377 } else if (value & AUTH_ALG_SHARED_KEY) {
378 padapter->securitypriv.ndisencryptstatus =
379 Ndis802_11Encryption1Enabled;
380 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
381 padapter->securitypriv.AuthAlgrthm = 1;
382 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
383 if (padapter->securitypriv.ndisauthtype <
384 Ndis802_11AuthModeWPAPSK) {
385 padapter->securitypriv.ndisauthtype =
386 Ndis802_11AuthModeOpen;
387 padapter->securitypriv.AuthAlgrthm = 0;
394 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
398 u32 wep_key_idx, wep_key_len = 0;
399 struct NDIS_802_11_WEP *pwep = NULL;
400 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
401 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
402 struct security_priv *psecuritypriv = &padapter->securitypriv;
404 param->u.crypt.err = 0;
405 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
406 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
407 param->u.crypt.key_len)
409 if (is_broadcast_ether_addr(param->sta_addr)) {
410 if (param->u.crypt.idx >= WEP_KEYS) {
411 /* for large key indices, set the default (0) */
412 param->u.crypt.idx = 0;
416 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
417 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
418 padapter->securitypriv.ndisencryptstatus =
419 Ndis802_11Encryption1Enabled;
420 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
421 padapter->securitypriv.XGrpPrivacy = _WEP40_;
422 wep_key_idx = param->u.crypt.idx;
423 wep_key_len = param->u.crypt.key_len;
424 if (wep_key_idx >= WEP_KEYS)
426 if (wep_key_len > 0) {
427 wep_key_len = wep_key_len <= 5 ? 5 : 13;
428 pwep = (struct NDIS_802_11_WEP *)_malloc((u32)
430 FIELD_OFFSET(struct NDIS_802_11_WEP,
434 memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
435 pwep->KeyLength = wep_key_len;
436 pwep->Length = wep_key_len +
437 FIELD_OFFSET(struct NDIS_802_11_WEP,
439 if (wep_key_len == 13) {
440 padapter->securitypriv.PrivacyAlgrthm =
442 padapter->securitypriv.XGrpPrivacy =
447 pwep->KeyIndex = wep_key_idx;
448 pwep->KeyIndex |= 0x80000000;
449 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
450 if (param->u.crypt.set_tx) {
451 if (r8712_set_802_11_add_wep(padapter, pwep) ==
455 /* don't update "psecuritypriv->PrivacyAlgrthm" and
456 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
457 * r8712_set_key to fw/cam
459 if (wep_key_idx >= WEP_KEYS) {
463 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
464 skey[0]), pwep->KeyMaterial,
466 psecuritypriv->DefKeylen[wep_key_idx] =
468 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
472 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
473 struct sta_info *psta, *pbcmc_sta;
474 struct sta_priv *pstapriv = &padapter->stapriv;
476 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
477 WIFI_MP_STATE) == true) { /* sta mode */
478 psta = r8712_get_stainfo(pstapriv,
479 get_bssid(pmlmepriv));
481 psta->ieee8021x_blocked = false;
482 if ((padapter->securitypriv.ndisencryptstatus ==
483 Ndis802_11Encryption2Enabled) ||
484 (padapter->securitypriv.ndisencryptstatus ==
485 Ndis802_11Encryption3Enabled))
486 psta->XPrivacy = padapter->
487 securitypriv.PrivacyAlgrthm;
488 if (param->u.crypt.set_tx == 1)
489 handle_pairwise_key(psta, param,
492 handle_group_key(param, padapter);
494 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
496 pbcmc_sta->ieee8021x_blocked = false;
497 if ((padapter->securitypriv.ndisencryptstatus ==
498 Ndis802_11Encryption2Enabled) ||
499 (padapter->securitypriv.ndisencryptstatus ==
500 Ndis802_11Encryption3Enabled))
501 pbcmc_sta->XPrivacy =
502 padapter->securitypriv.
512 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
513 unsigned short ielen)
515 u8 *buf = NULL, *pos = NULL;
516 int group_cipher = 0, pairwise_cipher = 0;
519 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
522 buf = _malloc(ielen);
525 memcpy(buf, pie , ielen);
527 if (ielen < RSN_HEADER_LEN) {
531 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
532 &pairwise_cipher) == _SUCCESS) {
533 padapter->securitypriv.AuthAlgrthm = 2;
534 padapter->securitypriv.ndisauthtype =
535 Ndis802_11AuthModeWPAPSK;
537 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
538 &pairwise_cipher) == _SUCCESS) {
539 padapter->securitypriv.AuthAlgrthm = 2;
540 padapter->securitypriv.ndisauthtype =
541 Ndis802_11AuthModeWPA2PSK;
543 switch (group_cipher) {
544 case WPA_CIPHER_NONE:
545 padapter->securitypriv.XGrpPrivacy =
547 padapter->securitypriv.ndisencryptstatus =
548 Ndis802_11EncryptionDisabled;
550 case WPA_CIPHER_WEP40:
551 padapter->securitypriv.XGrpPrivacy = _WEP40_;
552 padapter->securitypriv.ndisencryptstatus =
553 Ndis802_11Encryption1Enabled;
555 case WPA_CIPHER_TKIP:
556 padapter->securitypriv.XGrpPrivacy = _TKIP_;
557 padapter->securitypriv.ndisencryptstatus =
558 Ndis802_11Encryption2Enabled;
560 case WPA_CIPHER_CCMP:
561 padapter->securitypriv.XGrpPrivacy = _AES_;
562 padapter->securitypriv.ndisencryptstatus =
563 Ndis802_11Encryption3Enabled;
565 case WPA_CIPHER_WEP104:
566 padapter->securitypriv.XGrpPrivacy = _WEP104_;
567 padapter->securitypriv.ndisencryptstatus =
568 Ndis802_11Encryption1Enabled;
571 switch (pairwise_cipher) {
572 case WPA_CIPHER_NONE:
573 padapter->securitypriv.PrivacyAlgrthm =
575 padapter->securitypriv.ndisencryptstatus =
576 Ndis802_11EncryptionDisabled;
578 case WPA_CIPHER_WEP40:
579 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
580 padapter->securitypriv.ndisencryptstatus =
581 Ndis802_11Encryption1Enabled;
583 case WPA_CIPHER_TKIP:
584 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
585 padapter->securitypriv.ndisencryptstatus =
586 Ndis802_11Encryption2Enabled;
588 case WPA_CIPHER_CCMP:
589 padapter->securitypriv.PrivacyAlgrthm = _AES_;
590 padapter->securitypriv.ndisencryptstatus =
591 Ndis802_11Encryption3Enabled;
593 case WPA_CIPHER_WEP104:
594 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
595 padapter->securitypriv.ndisencryptstatus =
596 Ndis802_11Encryption1Enabled;
599 padapter->securitypriv.wps_phase = false;
602 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
604 while (cnt < ielen) {
607 if ((eid == _VENDOR_SPECIFIC_IE_) &&
608 (!memcmp(&buf[cnt+2], wps_oui, 4))) {
609 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
610 padapter->securitypriv.wps_ie_len =
612 (MAX_WPA_IE_LEN << 2)) ?
614 (MAX_WPA_IE_LEN << 2);
615 memcpy(padapter->securitypriv.wps_ie,
617 padapter->securitypriv.wps_ie_len);
618 padapter->securitypriv.wps_phase =
620 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
624 cnt += buf[cnt + 1] + 2;
633 static int r8711_wx_get_name(struct net_device *dev,
634 struct iw_request_info *info,
635 union iwreq_data *wrqu, char *extra)
637 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
641 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
642 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
643 NDIS_802_11_RATES_EX *prates = NULL;
645 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
647 /* parsing HT_CAP_IE */
648 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
649 &ht_ielen, pcur_bss->IELength - 12);
650 if (p && ht_ielen > 0)
652 prates = &pcur_bss->SupportedRates;
653 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
655 snprintf(wrqu->name, IFNAMSIZ,
658 snprintf(wrqu->name, IFNAMSIZ,
660 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
662 snprintf(wrqu->name, IFNAMSIZ,
665 snprintf(wrqu->name, IFNAMSIZ,
669 snprintf(wrqu->name, IFNAMSIZ,
672 snprintf(wrqu->name, IFNAMSIZ,
676 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
680 static const long frequency_list[] = {
681 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
682 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
683 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
684 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
685 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
689 static int r8711_wx_set_freq(struct net_device *dev,
690 struct iw_request_info *info,
691 union iwreq_data *wrqu, char *extra)
693 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
694 struct iw_freq *fwrq = &wrqu->freq;
697 /* If setting by frequency, convert to a channel */
698 if ((fwrq->e == 1) &&
699 (fwrq->m >= (int) 2.412e8) &&
700 (fwrq->m <= (int) 2.487e8)) {
701 int f = fwrq->m / 100000;
703 while ((c < 14) && (f != frequency_list[c]))
708 /* Setting by channel number */
709 if ((fwrq->m > 14) || (fwrq->e > 0))
712 int channel = fwrq->m;
713 if ((channel < 1) || (channel > 14))
716 /* Yes ! We can set it !!! */
717 padapter->registrypriv.channel = channel;
723 static int r8711_wx_get_freq(struct net_device *dev,
724 struct iw_request_info *info,
725 union iwreq_data *wrqu, char *extra)
727 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
728 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
729 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
731 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
732 wrqu->freq.m = ieee80211_wlan_frequencies[
733 pcur_bss->Configuration.DSConfig-1] * 100000;
735 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
742 static int r8711_wx_set_mode(struct net_device *dev,
743 struct iw_request_info *a,
744 union iwreq_data *wrqu, char *b)
746 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
747 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
749 switch (wrqu->mode) {
751 networkType = Ndis802_11AutoUnknown;
754 networkType = Ndis802_11IBSS;
757 networkType = Ndis802_11APMode;
760 networkType = Ndis802_11Infrastructure;
765 if (Ndis802_11APMode == networkType)
766 r8712_setopmode_cmd(padapter, networkType);
768 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
770 r8712_set_802_11_infrastructure_mode(padapter, networkType);
774 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
775 union iwreq_data *wrqu, char *b)
777 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
778 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
780 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
781 wrqu->mode = IW_MODE_INFRA;
782 else if (check_fwstate(pmlmepriv,
783 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
784 wrqu->mode = IW_MODE_ADHOC;
785 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
786 wrqu->mode = IW_MODE_MASTER;
788 wrqu->mode = IW_MODE_AUTO;
792 static int r871x_wx_set_pmkid(struct net_device *dev,
793 struct iw_request_info *a,
794 union iwreq_data *wrqu, char *extra)
796 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
797 struct security_priv *psecuritypriv = &padapter->securitypriv;
798 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
799 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
800 u8 strIssueBssid[ETH_ALEN] = {0x00};
801 u8 j, blInserted = false;
802 int intReturn = false;
805 There are the BSSID information in the bssid.sa_data array.
806 If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
807 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
808 wpa_supplicant wants to add a PMKID/BSSID to driver.
809 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
810 remove a PMKID/BSSID from driver.
814 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
817 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
822 /* overwrite PMKID */
823 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
824 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
825 strIssueBssid, ETH_ALEN)) {
826 /* BSSID is matched, the same AP => rewrite
828 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
830 memcpy(psecuritypriv->PMKIDList[j].PMKID,
831 pPMK->pmkid, IW_PMKID_LEN);
832 psecuritypriv->PMKIDList[j].bUsed = true;
833 psecuritypriv->PMKIDIndex = j + 1;
839 /* Find a new entry */
840 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
841 __func__, psecuritypriv->PMKIDIndex);
842 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
843 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
844 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
845 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
846 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
848 psecuritypriv->PMKIDIndex++ ;
849 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
850 psecuritypriv->PMKIDIndex = 0;
853 case IW_PMKSA_REMOVE:
855 for (j = 0; j < NUM_PMKID_CACHE; j++) {
856 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
857 strIssueBssid, ETH_ALEN)) {
858 /* BSSID is matched, the same AP => Remove
859 * this PMKID information and reset it. */
860 memset(psecuritypriv->PMKIDList[j].Bssid,
862 psecuritypriv->PMKIDList[j].bUsed = false;
868 memset(psecuritypriv->PMKIDList, 0,
869 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
870 psecuritypriv->PMKIDIndex = 0;
874 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
881 static int r8711_wx_get_sens(struct net_device *dev,
882 struct iw_request_info *info,
883 union iwreq_data *wrqu, char *extra)
885 wrqu->sens.value = 0;
886 wrqu->sens.fixed = 0; /* no auto select */
887 wrqu->sens.disabled = 1;
891 static int r8711_wx_get_range(struct net_device *dev,
892 struct iw_request_info *info,
893 union iwreq_data *wrqu, char *extra)
895 struct iw_range *range = (struct iw_range *)extra;
899 wrqu->data.length = sizeof(*range);
900 memset(range, 0, sizeof(*range));
901 /* Let's try to keep this struct in the same order as in
902 * linux/include/wireless.h
905 /* TODO: See what values we can set, and remove the ones we can't
906 * set, or fill them with some default data.
908 /* ~5 Mb/s real (802.11b) */
909 range->throughput = 5 * 1000 * 1000;
910 /* TODO: 8711 sensitivity ? */
911 /* signal level threshold range */
912 /* percent values between 0 and 100. */
913 range->max_qual.qual = 100;
914 range->max_qual.level = 100;
915 range->max_qual.noise = 100;
916 range->max_qual.updated = 7; /* Updated all three */
917 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
918 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
919 range->avg_qual.level = 20 + -98;
920 range->avg_qual.noise = 0;
921 range->avg_qual.updated = 7; /* Updated all three */
922 range->num_bitrates = RATE_COUNT;
923 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
924 range->bitrate[i] = rtl8180_rates[i];
925 range->min_frag = MIN_FRAG_THRESHOLD;
926 range->max_frag = MAX_FRAG_THRESHOLD;
928 range->we_version_compiled = WIRELESS_EXT;
929 range->we_version_source = 16;
930 range->num_channels = 14;
931 for (i = 0, val = 0; i < 14; i++) {
932 /* Include only legal frequencies for some countries */
933 range->freq[val].i = i + 1;
934 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
935 range->freq[val].e = 1;
937 if (val == IW_MAX_FREQUENCIES)
940 range->num_frequency = val;
941 range->enc_capa = IW_ENC_CAPA_WPA |
943 IW_ENC_CAPA_CIPHER_TKIP |
944 IW_ENC_CAPA_CIPHER_CCMP;
948 static int r8711_wx_get_rate(struct net_device *dev,
949 struct iw_request_info *info,
950 union iwreq_data *wrqu, char *extra);
952 static int r871x_wx_set_priv(struct net_device *dev,
953 struct iw_request_info *info,
954 union iwreq_data *awrq,
957 int ret = 0, len = 0;
959 struct _adapter *padapter = netdev_priv(dev);
960 struct iw_point *dwrq = (struct iw_point *)awrq;
966 if (copy_from_user(ext, dwrq->pointer, len)) {
971 if (0 == strcasecmp(ext, "RSSI")) {
972 /*Return received signal strength indicator in -db for */
975 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
976 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
978 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
979 sprintf(ext, "%s rssi %d",
980 pcur_network->network.Ssid.Ssid,
982 ((padapter->recvpriv.fw_rssi)>>1)-95
983 /*pcur_network->network.Rssi */
988 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
989 /*Return link speed in MBPS */
991 union iwreq_data wrqd;
995 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
999 mbps = wrqd.bitrate.value / 1000000;
1000 sprintf(ext, "LINKSPEED %d", mbps);
1001 } else if (0 == strcasecmp(ext, "MACADDR")) {
1002 /*Return mac address of the station */
1003 /*Macaddr = xx.xx.xx.xx.xx.xx */
1005 "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
1006 *(dev->dev_addr), *(dev->dev_addr+1),
1007 *(dev->dev_addr+2), *(dev->dev_addr+3),
1008 *(dev->dev_addr+4), *(dev->dev_addr+5));
1009 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
1010 /*Set scan type to active */
1011 /*OK if successful */
1012 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1013 pmlmepriv->passive_mode = 1;
1015 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1016 /*Set scan type to passive */
1017 /*OK if successful */
1018 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1019 pmlmepriv->passive_mode = 0;
1021 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1022 /*Set scan type to passive */
1023 /*OK if successful */
1024 r8712_disconnectCtrlEx_cmd(padapter
1025 , 1 /*u32 enableDrvCtrl */
1026 , 5 /*u32 tryPktCnt */
1027 , 100 /*u32 tryPktInterval */
1028 , 5000 /*u32 firstStageTO */
1031 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1032 /*Set scan type to passive */
1033 /*OK if successfu */
1034 r8712_disconnectCtrlEx_cmd(padapter
1035 , 0 /*u32 enableDrvCtrl */
1036 , 5 /*u32 tryPktCnt */
1037 , 100 /*u32 tryPktInterval */
1038 , 5000 /*u32 firstStageTO */
1042 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1046 if (copy_to_user(dwrq->pointer, ext,
1047 min(dwrq->length, (__u16)(strlen(ext)+1))))
1056 * s1. set_802_11_infrastructure_mode()
1057 * s2. set_802_11_authentication_mode()
1058 * s3. set_802_11_encryption_mode()
1059 * s4. set_802_11_bssid()
1061 * This function intends to handle the Set AP command, which specifies the
1062 * MAC# of a preferred Access Point.
1063 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1065 * For this operation to succeed, there is no need for the interface to be up.
1068 static int r8711_wx_set_wap(struct net_device *dev,
1069 struct iw_request_info *info,
1070 union iwreq_data *awrq,
1073 int ret = -EINPROGRESS;
1074 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1075 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1076 struct __queue *queue = &pmlmepriv->scanned_queue;
1077 struct sockaddr *temp = (struct sockaddr *)awrq;
1079 struct list_head *phead;
1081 struct wlan_network *pnetwork = NULL;
1082 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1084 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1086 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1088 if (temp->sa_family != ARPHRD_ETHER)
1090 authmode = padapter->securitypriv.ndisauthtype;
1091 spin_lock_irqsave(&queue->lock, irqL);
1092 phead = get_list_head(queue);
1093 pmlmepriv->pscanned = get_next(phead);
1095 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1097 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1098 struct wlan_network, list);
1099 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1100 dst_bssid = pnetwork->network.MacAddress;
1101 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1102 r8712_set_802_11_infrastructure_mode(padapter,
1103 pnetwork->network.InfrastructureMode);
1107 spin_unlock_irqrestore(&queue->lock, irqL);
1109 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1112 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1119 static int r8711_wx_get_wap(struct net_device *dev,
1120 struct iw_request_info *info,
1121 union iwreq_data *wrqu, char *extra)
1123 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1124 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1125 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1127 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1128 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1130 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1132 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1136 static int r871x_wx_set_mlme(struct net_device *dev,
1137 struct iw_request_info *info,
1138 union iwreq_data *wrqu, char *extra)
1142 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1143 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1147 reason = cpu_to_le16(mlme->reason_code);
1148 switch (mlme->cmd) {
1149 case IW_MLME_DEAUTH:
1150 if (!r8712_set_802_11_disassociate(padapter))
1153 case IW_MLME_DISASSOC:
1154 if (!r8712_set_802_11_disassociate(padapter))
1165 * This function intends to handle the Set Scan command.
1166 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1168 * For this operation to succeed, the interface is brought Up beforehand.
1171 static int r8711_wx_set_scan(struct net_device *dev,
1172 struct iw_request_info *a,
1173 union iwreq_data *wrqu, char *extra)
1175 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1176 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1179 if (padapter->bDriverStopped == true) {
1180 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1181 __func__, padapter->bDriverStopped);
1184 if (padapter->bup == false)
1186 if (padapter->hw_init_completed == false)
1188 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1189 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1191 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1192 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1193 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1194 struct ndis_802_11_ssid ssid;
1196 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1197 memset((unsigned char *)&ssid, 0,
1198 sizeof(struct ndis_802_11_ssid));
1199 memcpy(ssid.Ssid, req->essid, len);
1200 ssid.SsidLength = len;
1201 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1202 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1203 _FW_UNDER_LINKING)) ||
1204 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1205 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1208 status = r8712_sitesurvey_cmd(padapter, &ssid);
1209 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1212 status = r8712_set_802_11_bssid_list_scan(padapter);
1213 if (status == false)
1218 static int r8711_wx_get_scan(struct net_device *dev,
1219 struct iw_request_info *a,
1220 union iwreq_data *wrqu, char *extra)
1222 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1223 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1224 struct __queue *queue = &pmlmepriv->scanned_queue;
1225 struct wlan_network *pnetwork = NULL;
1227 struct list_head *plist, *phead;
1229 char *stop = ev + wrqu->data.length;
1230 u32 ret = 0, cnt = 0;
1232 if (padapter->bDriverStopped)
1234 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1240 spin_lock_irqsave(&queue->lock, irqL);
1241 phead = get_list_head(queue);
1242 plist = get_next(phead);
1244 if (end_of_queue_search(phead, plist) == true)
1246 if ((stop - ev) < SCAN_ITEM_SIZE) {
1250 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1251 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1252 plist = get_next(plist);
1254 spin_unlock_irqrestore(&queue->lock, irqL);
1255 wrqu->data.length = ev - extra;
1256 wrqu->data.flags = 0;
1261 * s1. set_802_11_infrastructure_mode()
1262 * s2. set_802_11_authenticaion_mode()
1263 * s3. set_802_11_encryption_mode()
1264 * s4. set_802_11_ssid()
1266 * This function intends to handle the Set ESSID command.
1267 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1269 * For this operation to succeed, there is no need for the interface to be Up.
1272 static int r8711_wx_set_essid(struct net_device *dev,
1273 struct iw_request_info *a,
1274 union iwreq_data *wrqu, char *extra)
1276 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1277 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1278 struct __queue *queue = &pmlmepriv->scanned_queue;
1279 struct wlan_network *pnetwork = NULL;
1280 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1281 struct ndis_802_11_ssid ndis_ssid;
1282 u8 *dst_ssid, *src_ssid;
1283 struct list_head *phead;
1286 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1288 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1290 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1292 authmode = padapter->securitypriv.ndisauthtype;
1293 if (wrqu->essid.flags && wrqu->essid.length) {
1294 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1295 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1296 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1297 ndis_ssid.SsidLength = len;
1298 memcpy(ndis_ssid.Ssid, extra, len);
1299 src_ssid = ndis_ssid.Ssid;
1300 phead = get_list_head(queue);
1301 pmlmepriv->pscanned = get_next(phead);
1303 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1305 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1306 struct wlan_network, list);
1307 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1308 dst_ssid = pnetwork->network.Ssid.Ssid;
1309 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1310 && (pnetwork->network.Ssid.SsidLength ==
1311 ndis_ssid.SsidLength)) {
1312 if (check_fwstate(pmlmepriv,
1313 WIFI_ADHOC_STATE)) {
1314 if (pnetwork->network.
1318 cur_network.network.
1323 r8712_set_802_11_infrastructure_mode(
1325 pnetwork->network.InfrastructureMode);
1329 r8712_set_802_11_authentication_mode(padapter, authmode);
1330 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1332 return -EINPROGRESS;
1335 static int r8711_wx_get_essid(struct net_device *dev,
1336 struct iw_request_info *a,
1337 union iwreq_data *wrqu, char *extra)
1339 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1340 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1341 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1344 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1345 len = pcur_bss->Ssid.SsidLength;
1346 wrqu->essid.length = len;
1347 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1348 wrqu->essid.flags = 1;
1355 static int r8711_wx_set_rate(struct net_device *dev,
1356 struct iw_request_info *a,
1357 union iwreq_data *wrqu, char *extra)
1359 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1360 u32 target_rate = wrqu->bitrate.value;
1361 u32 fixed = wrqu->bitrate.fixed;
1363 u8 datarates[NumRates];
1364 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1367 if (target_rate == -1) {
1371 target_rate = target_rate / 100000;
1372 switch (target_rate) {
1414 for (i = 0; i < NumRates; i++) {
1415 if (ratevalue == mpdatarate[i]) {
1416 datarates[i] = mpdatarate[i];
1420 datarates[i] = 0xff;
1422 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1427 static int r8711_wx_get_rate(struct net_device *dev,
1428 struct iw_request_info *info,
1429 union iwreq_data *wrqu, char *extra)
1431 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1432 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1433 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1434 struct ieee80211_ht_cap *pht_capie;
1435 unsigned char rf_type = padapter->registrypriv.rf_config;
1438 u16 rate, max_rate = 0, ht_cap = false;
1440 u8 bw_40MHz = 0, short_GI = 0;
1444 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1445 p = r8712_get_ie(&pcur_bss->IEs[12],
1446 _HT_CAPABILITY_IE_, &ht_ielen,
1447 pcur_bss->IELength - 12);
1448 if (p && ht_ielen > 0) {
1450 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1451 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1452 bw_40MHz = (pht_capie->cap_info &
1453 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1454 short_GI = (pht_capie->cap_info &
1455 (IEEE80211_HT_CAP_SGI_20 |
1456 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1458 while ((pcur_bss->SupportedRates[i] != 0) &&
1459 (pcur_bss->SupportedRates[i] != 0xFF)) {
1460 rate = pcur_bss->SupportedRates[i] & 0x7F;
1461 if (rate > max_rate)
1463 wrqu->bitrate.fixed = 0; /* no auto select */
1464 wrqu->bitrate.value = rate*500000;
1467 if (ht_cap == true) {
1468 if (mcs_rate & 0x8000 /* MCS15 */
1470 RTL8712_RF_2T2R == rf_type)
1471 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1472 270) : ((short_GI) ? 144 : 130);
1473 else if (mcs_rate & 0x0080) /* MCS7 */
1474 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1475 135) : ((short_GI) ? 72 : 65);
1476 else /* default MCS7 */
1477 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1478 135) : ((short_GI) ? 72 : 65);
1479 max_rate *= 2; /* Mbps/2 */
1480 wrqu->bitrate.value = max_rate * 500000;
1482 wrqu->bitrate.value = max_rate * 500000;
1489 static int r8711_wx_get_rts(struct net_device *dev,
1490 struct iw_request_info *info,
1491 union iwreq_data *wrqu, char *extra)
1493 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1495 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1496 wrqu->rts.fixed = 0; /* no auto select */
1500 static int r8711_wx_set_frag(struct net_device *dev,
1501 struct iw_request_info *info,
1502 union iwreq_data *wrqu, char *extra)
1504 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1506 if (wrqu->frag.disabled)
1507 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1509 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1510 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1512 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1517 static int r8711_wx_get_frag(struct net_device *dev,
1518 struct iw_request_info *info,
1519 union iwreq_data *wrqu, char *extra)
1521 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1523 wrqu->frag.value = padapter->xmitpriv.frag_len;
1524 wrqu->frag.fixed = 0; /* no auto select */
1528 static int r8711_wx_get_retry(struct net_device *dev,
1529 struct iw_request_info *info,
1530 union iwreq_data *wrqu, char *extra)
1532 wrqu->retry.value = 7;
1533 wrqu->retry.fixed = 0; /* no auto select */
1534 wrqu->retry.disabled = 1;
1538 static int r8711_wx_set_enc(struct net_device *dev,
1539 struct iw_request_info *info,
1540 union iwreq_data *wrqu, char *keybuf)
1543 u32 keyindex_provided;
1544 struct NDIS_802_11_WEP wep;
1545 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1546 struct iw_point *erq = &(wrqu->encoding);
1547 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1549 key = erq->flags & IW_ENCODE_INDEX;
1550 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1551 if (erq->flags & IW_ENCODE_DISABLED) {
1552 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1553 padapter->securitypriv.ndisencryptstatus =
1554 Ndis802_11EncryptionDisabled;
1555 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1556 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1557 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1558 authmode = Ndis802_11AuthModeOpen;
1559 padapter->securitypriv.ndisauthtype = authmode;
1566 keyindex_provided = 1;
1568 keyindex_provided = 0;
1569 key = padapter->securitypriv.PrivacyKeyIndex;
1571 /* set authentication mode */
1572 if (erq->flags & IW_ENCODE_OPEN) {
1573 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
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;
1581 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1582 netdev_info(dev, "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1583 padapter->securitypriv.ndisencryptstatus =
1584 Ndis802_11Encryption1Enabled;
1585 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1586 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1587 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1588 authmode = Ndis802_11AuthModeShared;
1589 padapter->securitypriv.ndisauthtype = authmode;
1591 padapter->securitypriv.ndisencryptstatus =
1592 Ndis802_11Encryption1Enabled;
1593 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1594 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1595 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1596 authmode = Ndis802_11AuthModeOpen;
1597 padapter->securitypriv.ndisauthtype = authmode;
1600 if (erq->length > 0) {
1601 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1602 wep.Length = wep.KeyLength +
1603 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1606 if (keyindex_provided == 1) { /* set key_id only, no given
1607 * KeyMaterial(erq->length==0).*/
1608 padapter->securitypriv.PrivacyKeyIndex = key;
1609 switch (padapter->securitypriv.DefKeylen[key]) {
1611 padapter->securitypriv.PrivacyAlgrthm =
1615 padapter->securitypriv.PrivacyAlgrthm =
1619 padapter->securitypriv.PrivacyAlgrthm =
1626 wep.KeyIndex |= 0x80000000; /* transmit key */
1627 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1628 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1633 static int r8711_wx_get_enc(struct net_device *dev,
1634 struct iw_request_info *info,
1635 union iwreq_data *wrqu, char *keybuf)
1638 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1639 struct iw_point *erq = &(wrqu->encoding);
1640 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1642 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1643 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1645 erq->flags |= IW_ENCODE_DISABLED;
1649 key = erq->flags & IW_ENCODE_INDEX;
1655 key = padapter->securitypriv.PrivacyKeyIndex;
1657 erq->flags = key + 1;
1658 switch (padapter->securitypriv.ndisencryptstatus) {
1659 case Ndis802_11EncryptionNotSupported:
1660 case Ndis802_11EncryptionDisabled:
1662 erq->flags |= IW_ENCODE_DISABLED;
1664 case Ndis802_11Encryption1Enabled:
1665 erq->length = padapter->securitypriv.DefKeylen[key];
1667 memcpy(keybuf, padapter->securitypriv.DefKey[
1668 key].skey, padapter->securitypriv.
1670 erq->flags |= IW_ENCODE_ENABLED;
1671 if (padapter->securitypriv.ndisauthtype ==
1672 Ndis802_11AuthModeOpen)
1673 erq->flags |= IW_ENCODE_OPEN;
1674 else if (padapter->securitypriv.ndisauthtype ==
1675 Ndis802_11AuthModeShared)
1676 erq->flags |= IW_ENCODE_RESTRICTED;
1679 erq->flags |= IW_ENCODE_DISABLED;
1682 case Ndis802_11Encryption2Enabled:
1683 case Ndis802_11Encryption3Enabled:
1685 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1690 erq->flags |= IW_ENCODE_DISABLED;
1696 static int r8711_wx_get_power(struct net_device *dev,
1697 struct iw_request_info *info,
1698 union iwreq_data *wrqu, char *extra)
1700 wrqu->power.value = 0;
1701 wrqu->power.fixed = 0; /* no auto select */
1702 wrqu->power.disabled = 1;
1706 static int r871x_wx_set_gen_ie(struct net_device *dev,
1707 struct iw_request_info *info,
1708 union iwreq_data *wrqu, char *extra)
1710 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1712 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1715 static int r871x_wx_set_auth(struct net_device *dev,
1716 struct iw_request_info *info,
1717 union iwreq_data *wrqu, char *extra)
1719 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1720 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1725 paramid = param->flags & IW_AUTH_INDEX;
1726 paramval = param->value;
1728 case IW_AUTH_WPA_VERSION:
1730 case IW_AUTH_CIPHER_PAIRWISE:
1732 case IW_AUTH_CIPHER_GROUP:
1734 case IW_AUTH_KEY_MGMT:
1736 * ??? does not use these parameters
1739 case IW_AUTH_TKIP_COUNTERMEASURES:
1741 /* wpa_supplicant is enabling tkip countermeasure. */
1742 padapter->securitypriv.btkip_countermeasure = true;
1744 /* wpa_supplicant is disabling tkip countermeasure. */
1745 padapter->securitypriv.btkip_countermeasure = false;
1748 case IW_AUTH_DROP_UNENCRYPTED:
1751 * wpa_supplicant calls set_wpa_enabled when the driver
1752 * is loaded and unloaded, regardless of if WPA is being
1753 * used. No other calls are made which can be used to
1754 * determine if encryption will be used or not prior to
1755 * association being expected. If encryption is not being
1756 * used, drop_unencrypted is set to false, else true -- we
1757 * can use this to determine if the CAP_PRIVACY_ON bit should
1760 if (padapter->securitypriv.ndisencryptstatus ==
1761 Ndis802_11Encryption1Enabled) {
1762 /* it means init value, or using wep,
1763 * ndisencryptstatus =
1764 * Ndis802_11Encryption1Enabled,
1765 * then it needn't reset it;
1771 padapter->securitypriv.ndisencryptstatus =
1772 Ndis802_11EncryptionDisabled;
1773 padapter->securitypriv.PrivacyAlgrthm =
1775 padapter->securitypriv.XGrpPrivacy =
1777 padapter->securitypriv.AuthAlgrthm = 0;
1778 padapter->securitypriv.ndisauthtype =
1779 Ndis802_11AuthModeOpen;
1782 case IW_AUTH_80211_AUTH_ALG:
1783 ret = wpa_set_auth_algs(dev, (u32)paramval);
1785 case IW_AUTH_WPA_ENABLED:
1787 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1789 case IW_AUTH_PRIVACY_INVOKED:
1798 static int r871x_wx_set_enc_ext(struct net_device *dev,
1799 struct iw_request_info *info,
1800 union iwreq_data *wrqu, char *extra)
1802 struct iw_point *pencoding = &wrqu->encoding;
1803 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1804 struct ieee_param *param = NULL;
1809 param_len = sizeof(struct ieee_param) + pext->key_len;
1810 param = (struct ieee_param *)_malloc(param_len);
1813 memset(param, 0, param_len);
1814 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1815 memset(param->sta_addr, 0xff, ETH_ALEN);
1816 switch (pext->alg) {
1817 case IW_ENCODE_ALG_NONE:
1820 case IW_ENCODE_ALG_WEP:
1823 case IW_ENCODE_ALG_TKIP:
1826 case IW_ENCODE_ALG_CCMP:
1832 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1833 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1834 param->u.crypt.set_tx = 0;
1835 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1836 param->u.crypt.set_tx = 1;
1837 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1838 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1839 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1840 if (pext->key_len) {
1841 param->u.crypt.key_len = pext->key_len;
1842 memcpy(param + 1, pext + 1, pext->key_len);
1844 ret = wpa_set_encryption(dev, param, param_len);
1849 static int r871x_wx_get_nick(struct net_device *dev,
1850 struct iw_request_info *info,
1851 union iwreq_data *wrqu, char *extra)
1854 wrqu->data.length = 8;
1855 wrqu->data.flags = 1;
1856 memcpy(extra, "rtl_wifi", 8);
1861 static int r8711_wx_read32(struct net_device *dev,
1862 struct iw_request_info *info,
1863 union iwreq_data *wrqu, char *keybuf)
1865 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1869 get_user(addr, (u32 __user *)wrqu->data.pointer);
1870 data32 = r8712_read32(padapter, addr);
1871 put_user(data32, (u32 __user *)wrqu->data.pointer);
1872 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1873 wrqu->data.flags = data32 & 0xffff;
1874 get_user(addr, (u32 __user *)wrqu->data.pointer);
1878 static int r8711_wx_write32(struct net_device *dev,
1879 struct iw_request_info *info,
1880 union iwreq_data *wrqu, char *keybuf)
1882 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1886 get_user(addr, (u32 __user *)wrqu->data.pointer);
1887 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
1888 r8712_write32(padapter, addr, data32);
1892 static int dummy(struct net_device *dev,
1893 struct iw_request_info *a,
1894 union iwreq_data *wrqu, char *b)
1899 static int r8711_drvext_hdl(struct net_device *dev,
1900 struct iw_request_info *info,
1901 union iwreq_data *wrqu, char *extra)
1906 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1907 struct iw_request_info *info,
1908 union iwreq_data *wrqu, char *extra)
1910 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1911 struct iw_point *p = &wrqu->data;
1912 struct oid_par_priv oid_par;
1913 struct mp_ioctl_handler *phandler;
1914 struct mp_ioctl_param *poidparam;
1915 unsigned long BytesRead, BytesWritten, BytesNeeded;
1916 u8 *pparmbuf = NULL, bset;
1921 if ((!p->length) || (!p->pointer)) {
1923 goto _r871x_mp_ioctl_hdl_exit;
1925 bset = (u8)(p->flags & 0xFFFF);
1928 pparmbuf = (u8 *)_malloc(len);
1929 if (pparmbuf == NULL) {
1931 goto _r871x_mp_ioctl_hdl_exit;
1933 if (copy_from_user(pparmbuf, p->pointer, len)) {
1935 goto _r871x_mp_ioctl_hdl_exit;
1937 poidparam = (struct mp_ioctl_param *)pparmbuf;
1938 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1940 goto _r871x_mp_ioctl_hdl_exit;
1942 phandler = mp_ioctl_hdl + poidparam->subcode;
1943 if ((phandler->paramsize != 0) &&
1944 (poidparam->len < phandler->paramsize)) {
1946 goto _r871x_mp_ioctl_hdl_exit;
1948 if (phandler->oid == 0 && phandler->handler)
1949 status = phandler->handler(&oid_par);
1950 else if (phandler->handler) {
1951 oid_par.adapter_context = padapter;
1952 oid_par.oid = phandler->oid;
1953 oid_par.information_buf = poidparam->data;
1954 oid_par.information_buf_len = poidparam->len;
1959 oid_par.bytes_rw = &BytesRead;
1960 oid_par.bytes_needed = &BytesNeeded;
1961 oid_par.type_of_oid = SET_OID;
1963 oid_par.bytes_rw = &BytesWritten;
1964 oid_par.bytes_needed = &BytesNeeded;
1965 oid_par.type_of_oid = QUERY_OID;
1967 status = phandler->handler(&oid_par);
1968 /* todo:check status, BytesNeeded, etc. */
1970 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1971 __func__, poidparam->subcode, phandler->oid,
1974 goto _r871x_mp_ioctl_hdl_exit;
1976 if (bset == 0x00) { /* query info */
1977 if (copy_to_user(p->pointer, pparmbuf, len))
1982 goto _r871x_mp_ioctl_hdl_exit;
1984 _r871x_mp_ioctl_hdl_exit:
1989 static int r871x_get_ap_info(struct net_device *dev,
1990 struct iw_request_info *info,
1991 union iwreq_data *wrqu, char *extra)
1993 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1994 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1995 struct __queue *queue = &pmlmepriv->scanned_queue;
1996 struct iw_point *pdata = &wrqu->data;
1997 struct wlan_network *pnetwork = NULL;
1998 u32 cnt = 0, wpa_ielen;
2000 struct list_head *plist, *phead;
2001 unsigned char *pbuf;
2005 if (padapter->bDriverStopped || (pdata == NULL))
2007 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
2014 if (pdata->length >= 32) {
2015 if (copy_from_user(data, pdata->pointer, 32))
2019 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2020 phead = get_list_head(queue);
2021 plist = get_next(phead);
2023 if (end_of_queue_search(phead, plist) == true)
2025 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2026 if (hwaddr_aton_i(data, bssid)) {
2027 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
2029 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2033 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
2034 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2035 /* BSSID match, then check if supporting wpa/wpa2 */
2036 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2037 &wpa_ielen, pnetwork->network.IELength-12);
2038 if (pbuf && (wpa_ielen > 0)) {
2042 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2043 &wpa_ielen, pnetwork->network.IELength-12);
2044 if (pbuf && (wpa_ielen > 0)) {
2049 plist = get_next(plist);
2051 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2052 if (pdata->length >= 34) {
2053 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2054 (u8 *)&pdata->flags, 1))
2060 static int r871x_set_pid(struct net_device *dev,
2061 struct iw_request_info *info,
2062 union iwreq_data *wrqu, char *extra)
2064 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2065 struct iw_point *pdata = &wrqu->data;
2067 if ((padapter->bDriverStopped) || (pdata == NULL))
2069 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2074 static int r871x_set_chplan(struct net_device *dev,
2075 struct iw_request_info *info,
2076 union iwreq_data *wrqu, char *extra)
2079 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2080 struct iw_point *pdata = &wrqu->data;
2083 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2087 ch_plan = (int)*extra;
2088 r8712_set_chplan_cmd(padapter, ch_plan);
2095 static int r871x_wps_start(struct net_device *dev,
2096 struct iw_request_info *info,
2097 union iwreq_data *wrqu, char *extra)
2099 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2100 struct iw_point *pdata = &wrqu->data;
2101 u32 u32wps_start = 0;
2103 if ((padapter->bDriverStopped) || (pdata == NULL))
2105 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2107 if (u32wps_start == 0)
2108 u32wps_start = *extra;
2109 if (u32wps_start == 1) /* WPS Start */
2110 padapter->ledpriv.LedControlHandler(padapter,
2112 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2113 padapter->ledpriv.LedControlHandler(padapter,
2115 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2116 padapter->ledpriv.LedControlHandler(padapter,
2117 LED_CTL_STOP_WPS_FAIL);
2121 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2123 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2126 case IEEE_PARAM_WPA_ENABLED:
2127 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2128 switch ((value)&0xff) {
2130 padapter->securitypriv.ndisauthtype =
2131 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2132 padapter->securitypriv.ndisencryptstatus =
2133 Ndis802_11Encryption2Enabled;
2136 padapter->securitypriv.ndisauthtype =
2137 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2138 padapter->securitypriv.ndisencryptstatus =
2139 Ndis802_11Encryption3Enabled;
2143 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2145 case IEEE_PARAM_DROP_UNENCRYPTED:
2148 * wpa_supplicant calls set_wpa_enabled when the driver
2149 * is loaded and unloaded, regardless of if WPA is being
2150 * used. No other calls are made which can be used to
2151 * determine if encryption will be used or not prior to
2152 * association being expected. If encryption is not being
2153 * used, drop_unencrypted is set to false, else true -- we
2154 * can use this to determine if the CAP_PRIVACY_ON bit should
2158 case IEEE_PARAM_PRIVACY_INVOKED:
2160 case IEEE_PARAM_AUTH_ALGS:
2161 return wpa_set_auth_algs(dev, value);
2163 case IEEE_PARAM_IEEE_802_1X:
2165 case IEEE_PARAM_WPAX_SELECT:
2166 /* added for WPA2 mixed mode */
2174 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2176 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2179 case IEEE_MLME_STA_DEAUTH:
2180 if (!r8712_set_802_11_disassociate(padapter))
2183 case IEEE_MLME_STA_DISASSOC:
2184 if (!r8712_set_802_11_disassociate(padapter))
2193 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2195 struct ieee_param *param;
2197 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2199 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2201 param = (struct ieee_param *)_malloc(p->length);
2204 if (copy_from_user(param, p->pointer, p->length)) {
2208 switch (param->cmd) {
2209 case IEEE_CMD_SET_WPA_PARAM:
2210 ret = wpa_set_param(dev, param->u.wpa_param.name,
2211 param->u.wpa_param.value);
2213 case IEEE_CMD_SET_WPA_IE:
2214 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2215 (u16)param->u.wpa_ie.len);
2217 case IEEE_CMD_SET_ENCRYPTION:
2218 ret = wpa_set_encryption(dev, param, p->length);
2221 ret = wpa_mlme(dev, param->u.mlme.command,
2222 param->u.mlme.reason_code);
2228 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2234 /* based on "driver_ipw" and for hostapd */
2235 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2237 struct iwreq *wrq = (struct iwreq *)rq;
2240 case RTL_IOCTL_WPA_SUPPLICANT:
2241 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2248 static iw_handler r8711_handlers[] = {
2249 NULL, /* SIOCSIWCOMMIT */
2250 r8711_wx_get_name, /* SIOCGIWNAME */
2251 dummy, /* SIOCSIWNWID */
2252 dummy, /* SIOCGIWNWID */
2253 r8711_wx_set_freq, /* SIOCSIWFREQ */
2254 r8711_wx_get_freq, /* SIOCGIWFREQ */
2255 r8711_wx_set_mode, /* SIOCSIWMODE */
2256 r8711_wx_get_mode, /* SIOCGIWMODE */
2257 dummy, /* SIOCSIWSENS */
2258 r8711_wx_get_sens, /* SIOCGIWSENS */
2259 NULL, /* SIOCSIWRANGE */
2260 r8711_wx_get_range, /* SIOCGIWRANGE */
2261 r871x_wx_set_priv, /* SIOCSIWPRIV */
2262 NULL, /* SIOCGIWPRIV */
2263 NULL, /* SIOCSIWSTATS */
2264 NULL, /* SIOCGIWSTATS */
2265 dummy, /* SIOCSIWSPY */
2266 dummy, /* SIOCGIWSPY */
2267 NULL, /* SIOCGIWTHRSPY */
2268 NULL, /* SIOCWIWTHRSPY */
2269 r8711_wx_set_wap, /* SIOCSIWAP */
2270 r8711_wx_get_wap, /* SIOCGIWAP */
2271 r871x_wx_set_mlme, /* request MLME operation;
2272 * uses struct iw_mlme */
2273 dummy, /* SIOCGIWAPLIST -- deprecated */
2274 r8711_wx_set_scan, /* SIOCSIWSCAN */
2275 r8711_wx_get_scan, /* SIOCGIWSCAN */
2276 r8711_wx_set_essid, /* SIOCSIWESSID */
2277 r8711_wx_get_essid, /* SIOCGIWESSID */
2278 dummy, /* SIOCSIWNICKN */
2279 r871x_wx_get_nick, /* SIOCGIWNICKN */
2280 NULL, /* -- hole -- */
2281 NULL, /* -- hole -- */
2282 r8711_wx_set_rate, /* SIOCSIWRATE */
2283 r8711_wx_get_rate, /* SIOCGIWRATE */
2284 dummy, /* SIOCSIWRTS */
2285 r8711_wx_get_rts, /* SIOCGIWRTS */
2286 r8711_wx_set_frag, /* SIOCSIWFRAG */
2287 r8711_wx_get_frag, /* SIOCGIWFRAG */
2288 dummy, /* SIOCSIWTXPOW */
2289 dummy, /* SIOCGIWTXPOW */
2290 dummy, /* SIOCSIWRETRY */
2291 r8711_wx_get_retry, /* SIOCGIWRETRY */
2292 r8711_wx_set_enc, /* SIOCSIWENCODE */
2293 r8711_wx_get_enc, /* SIOCGIWENCODE */
2294 dummy, /* SIOCSIWPOWER */
2295 r8711_wx_get_power, /* SIOCGIWPOWER */
2296 NULL, /*---hole---*/
2297 NULL, /*---hole---*/
2298 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2299 NULL, /* SIOCGIWGENIE */
2300 r871x_wx_set_auth, /* SIOCSIWAUTH */
2301 NULL, /* SIOCGIWAUTH */
2302 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2303 NULL, /* SIOCGIWENCODEEXT */
2304 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2305 NULL, /*---hole---*/
2308 static const struct iw_priv_args r8711_private_args[] = {
2310 SIOCIWFIRSTPRIV + 0x0,
2311 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2314 SIOCIWFIRSTPRIV + 0x1,
2315 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2318 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2321 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2324 SIOCIWFIRSTPRIV + 0x4,
2325 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2328 SIOCIWFIRSTPRIV + 0x5,
2329 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2332 SIOCIWFIRSTPRIV + 0x6,
2333 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2336 SIOCIWFIRSTPRIV + 0x7,
2337 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2341 static iw_handler r8711_private_handler[] = {
2346 r871x_get_ap_info, /*for MM DTV platform*/
2352 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2354 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2355 struct iw_statistics *piwstats = &padapter->iwstats;
2360 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2361 piwstats->qual.qual = 0;
2362 piwstats->qual.level = 0;
2363 piwstats->qual.noise = 0;
2365 /* show percentage, we need transfer dbm to orignal value. */
2366 tmp_level = padapter->recvpriv.fw_rssi;
2367 tmp_qual = padapter->recvpriv.signal;
2368 tmp_noise = padapter->recvpriv.noise;
2369 piwstats->qual.level = tmp_level;
2370 piwstats->qual.qual = tmp_qual;
2371 piwstats->qual.noise = tmp_noise;
2373 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2374 return &padapter->iwstats;
2377 struct iw_handler_def r871x_handlers_def = {
2378 .standard = r8711_handlers,
2379 .num_standard = ARRAY_SIZE(r8711_handlers),
2380 .private = r8711_private_handler,
2381 .private_args = (struct iw_priv_args *)r8711_private_args,
2382 .num_private = ARRAY_SIZE(r8711_private_handler),
2383 .num_private_args = sizeof(r8711_private_args) /
2384 sizeof(struct iw_priv_args),
2385 .get_wireless_stats = r871x_get_wireless_stats