/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
https://bitbucket.org/wisechild/galaxy-nexus · C · 2251 lines · 1998 code · 116 blank · 137 comment · 363 complexity · 93e715edcb86b7a79ec7c5a9857a953b MD5 · raw file
Large files are truncated click here to view the full file
- /******************************************************************************
- * rtl871x_ioctl_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
- #define _RTL871X_IOCTL_LINUX_C_
- #define _RTL871X_MP_IOCTL_C_
- #include "osdep_service.h"
- #include "drv_types.h"
- #include "wlan_bssdef.h"
- #include "rtl871x_debug.h"
- #include "wifi.h"
- #include "rtl871x_mlme.h"
- #include "rtl871x_ioctl.h"
- #include "rtl871x_ioctl_set.h"
- #include "rtl871x_mp_ioctl.h"
- #include "mlme_osdep.h"
- #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
- #define SCAN_ITEM_SIZE 768
- #define MAX_CUSTOM_LEN 64
- #define RATE_COUNT 4
- static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
- 6000000, 9000000, 12000000, 18000000,
- 24000000, 36000000, 48000000, 54000000};
- static const long ieee80211_wlan_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
- };
- static const char * const iw_operation_mode[] = {
- "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
- "Monitor"
- };
- /**
- * hwaddr_aton - Convert ASCII string to MAC address
- * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
- * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
- * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
- */
- static int hwaddr_aton_i(const char *txt, u8 *addr)
- {
- int i;
- for (i = 0; i < 6; i++) {
- int a, b;
- a = hex_to_bin(*txt++);
- if (a < 0)
- return -1;
- b = hex_to_bin(*txt++);
- if (b < 0)
- return -1;
- *addr++ = (a << 4) | b;
- if (i < 5 && *txt++ != ':')
- return -1;
- }
- return 0;
- }
- void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
- {
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
- ETH_ALEN);
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
- }
- void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
- {
- union iwreq_data wrqu;
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
- }
- static inline void handle_pairwise_key(struct sta_info *psta,
- struct ieee_param *param,
- struct _adapter *padapter)
- {
- /* pairwise key */
- memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
- (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
- if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
- key[16]), 8);
- memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
- key[24]), 8);
- padapter->securitypriv. busetkipkey = false;
- _set_timer(&padapter->securitypriv.tkip_timer, 50);
- }
- r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
- }
- static inline void handle_group_key(struct ieee_param *param,
- struct _adapter *padapter)
- {
- if (0 < param->u.crypt.idx &&
- param->u.crypt.idx < 3) {
- /* group key idx is 1 or 2 */
- memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
- idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
- > 16 ? 16 : param->u.crypt.key_len));
- memcpy(padapter->securitypriv.XGrptxmickey[param->
- u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
- memcpy(padapter->securitypriv. XGrprxmickey[param->
- u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
- padapter->securitypriv.binstallGrpkey = true;
- r8712_set_key(padapter, &padapter->securitypriv,
- param->u.crypt.idx);
- if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
- if (padapter->registrypriv.power_mgnt != padapter->
- pwrctrlpriv.pwr_mode)
- _set_timer(&(padapter->mlmepriv.dhcp_timer),
- 60000);
- }
- }
- }
- static inline char *translate_scan(struct _adapter *padapter,
- struct iw_request_info *info,
- struct wlan_network *pnetwork,
- char *start, char *stop)
- {
- struct iw_event iwe;
- struct ieee80211_ht_cap *pht_capie;
- char *current_val;
- u8 *buf = (u8 *)_malloc(pnetwork->network.IELength * 2);
- u8 *wpa_ie = (u8 *)_malloc(255);
- u8 *rsn_ie = (u8 *)_malloc(255);
- u8 *wps_ie = (u8 *)_malloc(MAX_WPS_IE_LEN);
- s8 *p;
- u32 i = 0, ht_ielen = 0;
- u16 cap, ht_cap = false, mcs_rate;
- u8 rssi, bw_40MHz = 0, short_GI = 0;
- if ((pnetwork->network.Configuration.DSConfig < 1) ||
- (pnetwork->network.Configuration.DSConfig > 14)) {
- if (pnetwork->network.Configuration.DSConfig < 1)
- pnetwork->network.Configuration.DSConfig = 1;
- else
- pnetwork->network.Configuration.DSConfig = 14;
- }
- /* AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
- /* Add the ESSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = (u16)min((u16)pnetwork->network.Ssid.SsidLength,
- (u16)32);
- start = iwe_stream_add_point(info, start, stop, &iwe,
- pnetwork->network.Ssid.Ssid);
- /* parsing HT_CAP_IE */
- p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
- &ht_ielen, pnetwork->network.IELength - 12);
- if (p && ht_ielen > 0) {
- ht_cap = true;
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
- bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
- ? 1 : 0;
- short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
- }
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
- SupportedRates)) == true) {
- if (ht_cap == true)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
- SupportedRates)) == true) {
- if (ht_cap == true)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (ht_cap == true)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
- 2);
- cap = le16_to_cpu(cap);
- if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
- if (cap & WLAN_CAPABILITY_BSS)
- iwe.u.mode = (u32)IW_MODE_MASTER;
- else
- iwe.u.mode = (u32)IW_MODE_ADHOC;
- start = iwe_stream_add_event(info, start, stop, &iwe,
- IW_EV_UINT_LEN);
- }
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- {
- /* check legel index */
- u8 dsconfig = pnetwork->network.Configuration.DSConfig;
- if (dsconfig >= 1 && dsconfig <= sizeof(
- ieee80211_wlan_frequencies) / sizeof(long))
- iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
- pnetwork->network.Configuration.
- DSConfig - 1] * 100000);
- else
- iwe.u.freq.m = 0;
- }
- iwe.u.freq.e = (s16)1;
- iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
- start = iwe_stream_add_event(info, start, stop, &iwe,
- IW_EV_FREQ_LEN);
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (cap & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
- IW_ENCODE_NOKEY);
- else
- iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
- iwe.u.data.length = (u16)0;
- start = iwe_stream_add_point(info, start, stop, &iwe,
- pnetwork->network.Ssid.Ssid);
- /*Add basic and extended rates */
- current_val = start + iwe_stream_lcp_len(info);
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = 0;
- iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = 0;
- i = 0;
- while (pnetwork->network.SupportedRates[i] != 0) {
- /* Bit rate given in 500 kb/s units */
- iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
- 0x7F) * 500000;
- current_val = iwe_stream_add_value(info, start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if ((current_val - start) > iwe_stream_lcp_len(info))
- start = current_val;
- /* parsing WPA/WPA2 IE */
- {
- u16 wpa_len = 0, rsn_len = 0;
- int n;
- sint out_len = 0;
- out_len = r8712_get_sec_ie(pnetwork->network.IEs,
- pnetwork->network.
- IELength, rsn_ie, &rsn_len,
- wpa_ie, &wpa_len);
- if (wpa_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "wpa_ie=");
- for (i = 0; i < wpa_len; i++) {
- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", wpa_ie[i]);
- if (n >= MAX_WPA_IE_LEN)
- break;
- }
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = (u16)strlen(buf);
- start = iwe_stream_add_point(info, start, stop,
- &iwe, buf);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = (u16)wpa_len;
- start = iwe_stream_add_point(info, start, stop,
- &iwe, wpa_ie);
- }
- if (rsn_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "rsn_ie=");
- for (i = 0; i < rsn_len; i++) {
- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", rsn_ie[i]);
- if (n >= MAX_WPA_IE_LEN)
- break;
- }
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop,
- &iwe, buf);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, &iwe,
- rsn_ie);
- }
- }
- { /* parsing WPS IE */
- uint wps_ielen;
- if (r8712_get_wps_ie(pnetwork->network.IEs,
- pnetwork->network.IELength,
- wps_ie, &wps_ielen) == true) {
- if (wps_ielen > 2) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop,
- &iwe, wps_ie);
- }
- }
- }
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
- /* we only update signal_level (signal strength) that is rssi. */
- iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
- IW_QUAL_NOISE_INVALID);
- iwe.u.qual.level = rssi; /* signal strength */
- iwe.u.qual.qual = 0; /* signal quality */
- iwe.u.qual.noise = 0; /* noise level */
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
- /* how to translate rssi to ?% */
- kfree(buf);
- kfree(wpa_ie);
- kfree(rsn_ie);
- kfree(wps_ie);
- return start;
- }
- static int wpa_set_auth_algs(struct net_device *dev, u32 value)
- {
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
- int ret = 0;
- if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.AuthAlgrthm = 3;
- } else if (value & AUTH_ALG_SHARED_KEY) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
- padapter->securitypriv.AuthAlgrthm = 1;
- } else if (value & AUTH_ALG_OPEN_SYSTEM) {
- if (padapter->securitypriv.ndisauthtype <
- Ndis802_11AuthModeWPAPSK) {
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeOpen;
- padapter->securitypriv.AuthAlgrthm = 0;
- }
- } else
- ret = -EINVAL;
- return ret;
- }
- static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
- u32 param_len)
- {
- int ret = 0;
- u32 wep_key_idx, wep_key_len = 0;
- struct NDIS_802_11_WEP *pwep = NULL;
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
- if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
- param->u.crypt.key_len)
- return -EINVAL;
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
- if (param->u.crypt.idx >= WEP_KEYS) {
- /* for large key indices, set the default (0) */
- param->u.crypt.idx = 0;
- }
- } else
- return -EINVAL;
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- printk(KERN_INFO "r8712u: wpa_set_encryption, crypt.alg ="
- " WEP\n");
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
- if (wep_key_idx >= WEP_KEYS)
- wep_key_idx = 0;
- if (wep_key_len > 0) {
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
- pwep = (struct NDIS_802_11_WEP *)_malloc((u32)
- (wep_key_len +
- FIELD_OFFSET(struct NDIS_802_11_WEP,
- KeyMaterial)));
- if (pwep == NULL)
- return -ENOMEM;
- memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_key_len +
- FIELD_OFFSET(struct NDIS_802_11_WEP,
- KeyMaterial);
- if (wep_key_len == 13) {
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP104_;
- padapter->securitypriv.XGrpPrivacy =
- _WEP104_;
- }
- } else
- return -EINVAL;
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
- if (param->u.crypt.set_tx) {
- if (r8712_set_802_11_add_wep(padapter, pwep) ==
- (u8)_FAIL)
- ret = -EOPNOTSUPP;
- } else {
- /* don't update "psecuritypriv->PrivacyAlgrthm" and
- * "psecuritypriv->PrivacyKeyIndex=keyid", but can
- * r8712_set_key to fw/cam
- */
- if (wep_key_idx >= WEP_KEYS) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
- memcpy(&(psecuritypriv->DefKey[wep_key_idx].
- skey[0]), pwep->KeyMaterial,
- pwep->KeyLength);
- psecuritypriv->DefKeylen[wep_key_idx] =
- pwep->KeyLength;
- r8712_set_key(padapter, psecuritypriv, wep_key_idx);
- }
- goto exit;
- }
- if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
- struct sta_info *psta, *pbcmc_sta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
- WIFI_MP_STATE) == true) { /* sta mode */
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- if (psta) {
- psta->ieee8021x_blocked = false;
- if ((padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption2Enabled) ||
- (padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption3Enabled))
- psta->XPrivacy = padapter->
- securitypriv.PrivacyAlgrthm;
- if (param->u.crypt.set_tx == 1)
- handle_pairwise_key(psta, param,
- padapter);
- else /* group key */
- handle_group_key(param, padapter);
- }
- pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
- if (pbcmc_sta) {
- pbcmc_sta->ieee8021x_blocked = false;
- if ((padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption2Enabled) ||
- (padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption3Enabled))
- pbcmc_sta->XPrivacy =
- padapter->securitypriv.
- PrivacyAlgrthm;
- }
- }
- }
- exit:
- kfree((u8 *)pwep);
- return ret;
- }
- static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
- unsigned short ielen)
- {
- u8 *buf = NULL, *pos = NULL;
- int group_cipher = 0, pairwise_cipher = 0;
- int ret = 0;
- if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
- return -EINVAL;
- if (ielen) {
- buf = _malloc(ielen);
- if (buf == NULL)
- return -ENOMEM;
- memcpy(buf, pie , ielen);
- pos = buf;
- if (ielen < RSN_HEADER_LEN) {
- ret = -1;
- goto exit;
- }
- if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
- &pairwise_cipher) == _SUCCESS) {
- padapter->securitypriv.AuthAlgrthm = 2;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPAPSK;
- }
- if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
- &pairwise_cipher) == _SUCCESS) {
- padapter->securitypriv.AuthAlgrthm = 2;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPA2PSK;
- }
- switch (group_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.XGrpPrivacy =
- _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.XGrpPrivacy = _TKIP_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.XGrpPrivacy = _AES_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.XGrpPrivacy = _WEP104_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- break;
- }
- switch (pairwise_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.PrivacyAlgrthm = _AES_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- break;
- }
- padapter->securitypriv.wps_phase = false;
- {/* set wps_ie */
- u16 cnt = 0;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
- while (cnt < ielen) {
- eid = buf[cnt];
- if ((eid == _VENDOR_SPECIFIC_IE_) &&
- (!memcmp(&buf[cnt+2], wps_oui, 4))) {
- printk(KERN_INFO "r8712u: "
- "SET WPS_IE\n");
- padapter->securitypriv.wps_ie_len =
- ((buf[cnt+1] + 2) <
- (MAX_WPA_IE_LEN << 2)) ?
- (buf[cnt + 1] + 2) :
- (MAX_WPA_IE_LEN << 2);
- memcpy(padapter->securitypriv.wps_ie,
- &buf[cnt],
- padapter->securitypriv.wps_ie_len);
- padapter->securitypriv.wps_phase =
- true;
- printk(KERN_INFO "r8712u: SET WPS_IE,"
- " wps_phase==true\n");
- cnt += buf[cnt+1]+2;
- break;
- } else
- cnt += buf[cnt + 1] + 2;
- }
- }
- }
- exit:
- kfree(buf);
- return ret;
- }
- static int r8711_wx_get_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- u32 ht_ielen = 0;
- char *p;
- u8 ht_cap = false;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- NDIS_802_11_RATES_EX *prates = NULL;
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
- true) {
- /* parsing HT_CAP_IE */
- p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
- &ht_ielen, pcur_bss->IELength - 12);
- if (p && ht_ielen > 0)
- ht_cap = true;
- prates = &pcur_bss->SupportedRates;
- if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
- if (ht_cap == true)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11b");
- } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
- if (ht_cap == true)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bgn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bg");
- } else {
- if (ht_cap == true)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11g");
- }
- } else
- snprintf(wrqu->name, IFNAMSIZ, "unassociated");
- return 0;
- }
- static const long frequency_list[] = {
- 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
- 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
- 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
- 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
- 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
- 5825
- };
- static int r8711_wx_set_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct iw_freq *fwrq = &wrqu->freq;
- int rc = 0;
- /* If setting by frequency, convert to a channel */
- if ((fwrq->e == 1) &&
- (fwrq->m >= (int) 2.412e8) &&
- (fwrq->m <= (int) 2.487e8)) {
- int f = fwrq->m / 100000;
- int c = 0;
- while ((c < 14) && (f != frequency_list[c]))
- c++;
- fwrq->e = 0;
- fwrq->m = c + 1;
- }
- /* Setting by channel number */
- if ((fwrq->m > 14) || (fwrq->e > 0))
- rc = -EOPNOTSUPP;
- else {
- int channel = fwrq->m;
- if ((channel < 1) || (channel > 14))
- rc = -EINVAL;
- else {
- /* Yes ! We can set it !!! */
- padapter->registrypriv.channel = channel;
- }
- }
- return rc;
- }
- static int r8711_wx_get_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
- wrqu->freq.m = ieee80211_wlan_frequencies[
- pcur_bss->Configuration.DSConfig-1] * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = pcur_bss->Configuration.DSConfig;
- } else
- return -1;
- return 0;
- }
- static int r8711_wx_set_mode(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
- switch (wrqu->mode) {
- case IW_MODE_AUTO:
- networkType = Ndis802_11AutoUnknown;
- break;
- case IW_MODE_ADHOC:
- networkType = Ndis802_11IBSS;
- break;
- case IW_MODE_MASTER:
- networkType = Ndis802_11APMode;
- break;
- case IW_MODE_INFRA:
- networkType = Ndis802_11Infrastructure;
- break;
- default:
- return -EINVAL;
- }
- if (Ndis802_11APMode == networkType)
- r8712_setopmode_cmd(padapter, networkType);
- else
- r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
- if (!r8712_set_802_11_infrastructure_mode(padapter, networkType))
- return -1;
- return 0;
- }
- static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
- wrqu->mode = IW_MODE_INFRA;
- else if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
- wrqu->mode = IW_MODE_ADHOC;
- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
- wrqu->mode = IW_MODE_MASTER;
- else
- wrqu->mode = IW_MODE_AUTO;
- return 0;
- }
- static int r871x_wx_set_pmkid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
- u8 strZeroMacAddress[ETH_ALEN] = {0x00};
- u8 strIssueBssid[ETH_ALEN] = {0x00};
- u8 j, blInserted = false;
- int intReturn = false;
- /*
- There are the BSSID information in the bssid.sa_data array.
- If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear
- all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
- wpa_supplicant wants to add a PMKID/BSSID to driver.
- If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
- remove a PMKID/BSSID from driver.
- */
- if (pPMK == NULL)
- return -EINVAL;
- memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
- switch (pPMK->cmd) {
- case IW_PMKSA_ADD:
- if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
- return intReturn;
- else
- intReturn = true;
- blInserted = false;
- /* overwrite PMKID */
- for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
- strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => rewrite
- * with new PMKID. */
- printk(KERN_INFO "r8712u: r871x_wx_set_pmkid:"
- " BSSID exists in the PMKList.\n");
- memcpy(psecuritypriv->PMKIDList[j].PMKID,
- pPMK->pmkid, IW_PMKID_LEN);
- psecuritypriv->PMKIDList[j].bUsed = true;
- psecuritypriv->PMKIDIndex = j + 1;
- blInserted = true;
- break;
- }
- }
- if (!blInserted) {
- /* Find a new entry */
- printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: Use the"
- " new entry index = %d for this PMKID.\n",
- psecuritypriv->PMKIDIndex);
- memcpy(psecuritypriv->PMKIDList[psecuritypriv->
- PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
- memcpy(psecuritypriv->PMKIDList[psecuritypriv->
- PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
- psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
- bUsed = true;
- psecuritypriv->PMKIDIndex++ ;
- if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
- psecuritypriv->PMKIDIndex = 0;
- }
- break;
- case IW_PMKSA_REMOVE:
- intReturn = true;
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
- strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => Remove
- * this PMKID information and reset it. */
- memset(psecuritypriv->PMKIDList[j].Bssid,
- 0x00, ETH_ALEN);
- psecuritypriv->PMKIDList[j].bUsed = false;
- break;
- }
- }
- break;
- case IW_PMKSA_FLUSH:
- memset(psecuritypriv->PMKIDList, 0,
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- psecuritypriv->PMKIDIndex = 0;
- intReturn = true;
- break;
- default:
- printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: "
- "unknown Command\n");
- intReturn = false;
- break;
- }
- return intReturn;
- }
- static int r8711_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- wrqu->sens.value = 0;
- wrqu->sens.fixed = 0; /* no auto select */
- wrqu->sens.disabled = 1;
- return 0;
- }
- static int r8711_wx_get_range(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct iw_range *range = (struct iw_range *)extra;
- u16 val;
- int i;
- wrqu->data.length = sizeof(*range);
- memset(range, 0, sizeof(*range));
- /* Let's try to keep this struct in the same order as in
- * linux/include/wireless.h
- */
- /* TODO: See what values we can set, and remove the ones we can't
- * set, or fill them with some default data.
- */
- /* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
- /* TODO: 8711 sensitivity ? */
- /* signal level threshold range */
- /* percent values between 0 and 100. */
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 100;
- range->max_qual.updated = 7; /* Updated all three */
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
- range->avg_qual.level = 20 + -98;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
- range->num_bitrates = RATE_COUNT;
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = rtl8180_rates[i];
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
- range->pm_capa = 0;
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
- range->num_channels = 14;
- for (i = 0, val = 0; i < 14; i++) {
- /* Include only legal frequencies for some countries */
- range->freq[val].i = i + 1;
- range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
- range->freq[val].e = 1;
- val++;
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
- range->num_frequency = val;
- range->enc_capa = IW_ENC_CAPA_WPA |
- IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP |
- IW_ENC_CAPA_CIPHER_CCMP;
- return 0;
- }
- static int r871x_wx_set_priv(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
- {
- int ret = 0, len = 0;
- char *ext;
- struct iw_point *dwrq = (struct iw_point *)awrq;
- len = dwrq->length;
- ext = _malloc(len);
- if (!ext)
- return -ENOMEM;
- if (copy_from_user(ext, dwrq->pointer, len)) {
- kfree(ext);
- return -EFAULT;
- }
- kfree(ext);
- return ret;
- }
- /* set bssid flow
- * s1. set_802_11_infrastructure_mode()
- * s2. set_802_11_authentication_mode()
- * s3. set_802_11_encryption_mode()
- * s4. set_802_11_bssid()
- */
- static int r8711_wx_set_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
- {
- int ret = -EINPROGRESS;
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct sockaddr *temp = (struct sockaddr *)awrq;
- unsigned long irqL;
- struct list_head *phead;
- u8 *dst_bssid;
- struct wlan_network *pnetwork = NULL;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- if (padapter->bup == false)
- return -1;
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
- return -1;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
- return ret;
- if (temp->sa_family != ARPHRD_ETHER)
- return -EINVAL;
- authmode = padapter->securitypriv.ndisauthtype;
- spin_lock_irqsave(&queue->lock, irqL);
- phead = get_list_head(queue);
- pmlmepriv->pscanned = get_next(phead);
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
- break;
- pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
- dst_bssid = pnetwork->network.MacAddress;
- if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
- if (r8712_set_802_11_infrastructure_mode(padapter,
- pnetwork->network.InfrastructureMode) == false)
- ret = -1;
- break;
- }
- }
- spin_unlock_irqrestore(&queue->lock, irqL);
- if (!ret) {
- if (!r8712_set_802_11_authentication_mode(padapter, authmode))
- ret = -1;
- else {
- if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
- ret = -1;
- }
- }
- return ret;
- }
- static int r8711_wx_get_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
- memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
- if (check_fwstate(pmlmepriv, _FW_LINKED |
- WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
- memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
- }
- return 0;
- }
- static int r871x_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- int ret = 0;
- u16 reason;
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *) extra;
- if (mlme == NULL)
- return -1;
- reason = cpu_to_le16(mlme->reason_code);
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!r8712_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- case IW_MLME_DISASSOC:
- if (!r8712_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return ret;
- }
- static int r8711_wx_set_scan(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 status = true;
- if (padapter->bDriverStopped == true) {
- printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
- "bDriverStopped=%d\n", padapter->bDriverStopped);
- return -1;
- }
- if (padapter->bup == false)
- return -1;
- if (padapter->hw_init_completed == false)
- return -1;
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy == true))
- return 0;
- if (wrqu->data.length == sizeof(struct iw_scan_req)) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- struct ndis_802_11_ssid ssid;
- unsigned long irqL;
- u32 len = (u32) min((u8)req->essid_len,
- (u8)IW_ESSID_MAX_SIZE);
- memset((unsigned char *)&ssid, 0,
- sizeof(struct ndis_802_11_ssid));
- memcpy(ssid.Ssid, req->essid, len);
- ssid.SsidLength = len;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- status = false;
- } else
- status = r8712_sitesurvey_cmd(padapter, &ssid);
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- }
- } else
- status = r8712_set_802_11_bssid_list_scan(padapter);
- if (status == false)
- return -1;
- return 0;
- }
- static int r8711_wx_get_scan(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- unsigned long irqL;
- struct list_head *plist, *phead;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- u32 ret = 0, cnt = 0;
- if (padapter->bDriverStopped)
- return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
- msleep(30);
- cnt++;
- if (cnt > 1000)
- break;
- }
- spin_lock_irqsave(&queue->lock, irqL);
- phead = get_list_head(queue);
- plist = get_next(phead);
- while (1) {
- if (end_of_queue_search(phead, plist) == true)
- break;
- if ((stop - ev) < SCAN_ITEM_SIZE) {
- ret = -E2BIG;
- break;
- }
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
- ev = translate_scan(padapter, a, pnetwork, ev, stop);
- plist = get_next(plist);
- }
- spin_unlock_irqrestore(&queue->lock, irqL);
- wrqu->data.length = ev - extra;
- wrqu->data.flags = 0;
- return ret;
- }
- /* set ssid flow
- * s1. set_802_11_infrastructure_mode()
- * s2. set_802_11_authenticaion_mode()
- * s3. set_802_11_encryption_mode()
- * s4. set_802_11_ssid()
- */
- static int r8711_wx_set_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- struct ndis_802_11_ssid ndis_ssid;
- u8 *dst_ssid, *src_ssid;
- struct list_head *phead;
- u32 len;
- if (padapter->bup == false)
- return -1;
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- return -1;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- return 0;
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
- return -E2BIG;
- authmode = padapter->securitypriv.ndisauthtype;
- if (wrqu->essid.flags && wrqu->essid.length) {
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
- wrqu->essid.length : IW_ESSID_MAX_SIZE;
- memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = len;
- memcpy(ndis_ssid.Ssid, extra, len);
- src_ssid = ndis_ssid.Ssid;
- phead = get_list_head(queue);
- pmlmepriv->pscanned = get_next(phead);
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned))
- break;
- pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
- dst_ssid = pnetwork->network.Ssid.Ssid;
- if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
- && (pnetwork->network.Ssid.SsidLength ==
- ndis_ssid.SsidLength)) {
- if (!r8712_set_802_11_infrastructure_mode(
- padapter,
- pnetwork->network.InfrastructureMode))
- return -1;
- break;
- }
- }
- r8712_set_802_11_authentication_mode(padapter, authmode);
- r8712_set_802_11_ssid(padapter, &ndis_ssid);
- }
- return -EINPROGRESS;
- }
- static int r8711_wx_get_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- u32 len, ret = 0;
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
- len = pcur_bss->Ssid.SsidLength;
- wrqu->essid.length = len;
- memcpy(extra, pcur_bss->Ssid.Ssid, len);
- wrqu->essid.flags = 1;
- } else
- ret = -1;
- return ret;
- }
- static int r8711_wx_set_rate(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- u32 target_rate = wrqu->bitrate.value;
- u32 fixed = wrqu->bitrate.fixed;
- u32 ratevalue = 0;
- u8 datarates[NumRates];
- u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
- int i, ret = 0;
- if (target_rate == -1) {
- ratevalue = 11;
- goto set_rate;
- }
- target_rate = target_rate / 100000;
- switch (target_rate) {
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
- }
- set_rate:
- for (i = 0; i < NumRates; i++) {
- if (ratevalue == mpdatarate[i]) {
- datarates[i] = mpdatarate[i];
- if (fixed == 0)
- break;
- } else
- datarates[i] = 0xff;
- }
- if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
- ret = -1;
- return ret;
- }
- static int r8711_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- struct ieee80211_ht_cap *pht_capie;
- int i;
- u8 *p;
- u16 rate, max_rate = 0, ht_cap = false;
- u32 ht_ielen = 0;
- u8 bw_40MHz = 0, short_GI = 0;
- u16 mcs_rate = 0;
- i = 0;
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
- p = r8712_get_ie(&pcur_bss->IEs[12],
- _HT_CAPABILITY_IE_, &ht_ielen,
- pcur_bss->IELength - 12);
- if (p && ht_ielen > 0) {
- ht_cap = true;
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
- bw_40MHz = (pht_capie->cap_info &
- IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
- short_GI = (pht_capie->cap_info &
- (IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
- }
- while ((pcur_bss->SupportedRates[i] != 0) &&
- (pcur_bss->SupportedRates[i] != 0xFF)) {
- rate = pcur_bss->SupportedRates[i] & 0x7F;
- if (rate > max_rate)
- max_rate = rate;
- wrqu->bitrate.fixed = 0; /* no auto select */
- wrqu->bitrate.value = rate*500000;
- i++;
- }
- if (ht_cap == true) {
- if (mcs_rate & 0x8000) /* MCS15 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
- 270) : ((short_GI) ? 144 : 130);
- else if (mcs_rate & 0x0080) /* MCS7 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
- 135) : ((short_GI) ? 72 : 65);
- else /* default MCS7 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
- 135) : ((short_GI) ? 72 : 65);
- max_rate *= 2; /* Mbps/2 */
- wrqu->bitrate.value = max_rate * 500000;
- } else {
- wrqu->bitrate.value = max_rate * 500000;
- }
- } else
- return -1;
- return 0;
- }
- static int r8711_wx_get_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- wrqu->rts.value = padapter->registrypriv.rts_thresh;
- wrqu->rts.fixed = 0; /* no auto select */
- return 0;
- }
- static int r8711_wx_set_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- if (wrqu->frag.disabled)
- padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
- padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
- }
- return 0;
- }
- static int r8711_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
- wrqu->frag.value = padapter->xmitpriv.frag_len;
- wrqu->frag.fixed = 0; /* no auto select */
- return 0;
- }
- static int r8711_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- wrqu->retry.value = 7;
- wrqu->retry.fixed = 0; /* no auto select */
- wrqu->retry.disabled = 1;
- return 0;
- }
- static int r8711_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
- {
- u32 key;
- u32 keyindex_provided;
- struct NDIS_802_11_WEP wep;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- struct iw_point *erq = &(wrqu->encoding);
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
- key = erq->flags & IW_ENCODE_INDEX;
- memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
- if (erq->flags & IW_ENCODE_DISABLED) {
- printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
- "EncryptionDisabled\n");
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- return 0;
- }
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- keyindex_provided = 1;
- } else {
- keyindex_provided = 0;
- key = padapter->securitypriv.PrivacyKeyIndex;
- }
- /* set authentication mode */
- if (erq->flags & IW_ENCODE_OPEN) {
- printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
- "IW_ENCODE_OPEN\n");
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- } else if (erq->flags & IW_ENCODE_RESTRICTED) {
- printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
- "IW_ENCODE_RESTRICTED\n");
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- authmode = Ndis802_11AuthModeShared;
- padapter->securitypriv.ndisauthtype = authmode;
- } else {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- }
- wep.KeyIndex = key;
- if (erq->length > 0) {
- wep.KeyLength = erq->length <= 5 ? 5 : 13;
- wep.Length = wep.KeyLength +
- FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
- } else {
- wep.KeyLength = 0 ;
- if (keyindex_provided == 1) { /* set key_id only, no given
- * KeyMaterial(erq->length==0).*/
- padapter->securitypriv.PrivacyKeyIndex = key;
- switch (padapter->securitypriv.DefKeylen[key]) {
- case 5:
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP40_;
- break;
- case 13:
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP104_;
- break;
- default:
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- break;
- }
- return 0;
- }
- }
- wep.KeyIndex |= 0x80000000; /* transmit key */
- memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
- if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
- return -EOPNOTSUPP;
- return 0;
- }
- static int r8711_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
- {
- uint key, ret = 0;
- struct _adapter *padapter = (struct _adapter *) _netdev_priv(dev);
- struct iw_point *erq = &(wrqu->encoding);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
- if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
- }
- key = erq->flags & IW_ENCODE_INDEX;
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else {
- key = padapter->securitypriv.PrivacyKeyIndex;
- }
- erq->flags = key + 1;
- switch (padapter->securitypriv.ndisencryptstatus) {
- case Ndis802_11EncryptionNotSupported:
- case Ndis802_11EncryptionDisabled:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- case Ndis802_11Encryption1Enabled:
- erq->length = padapter->securitypriv.DefKeylen[key];
- if (erq->length) {
- memcpy(keybuf, padapter->securitypriv.DefKey[
- key].skey, padapter->securitypriv.
- DefKeylen[key]);
- erq->flags |= IW_ENCODE_ENABLED;
- if (padapter->securitypriv.ndisauthtype ==
- Ndis802_11AuthModeOpen)
- erq->flags |= IW_ENCODE_OPEN;
- else if (padapter->securitypriv.ndisauthtype ==
- Ndis802_11AuthModeShared)
- erq->flags |= IW_ENCODE_RESTRICTED;
- } else {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- }
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption3Enabled:
- erq->length = 16;
- erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
- IW_ENCODE_NOKEY);
- break;
- default:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- }
- return ret;
- }
- static int r8711_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- wrqu->power.value = 0;
- wrqu->power.fixed = 0; /* no auto select */
- wrqu->power.disabled = 1;
- return 0;
- }
- static int r871x_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
- }
- static int r871x_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
- {
- struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
- struct iw_param *param = (struct iw_param *)&(wrqu->param);
- int paramid;
- int paramval;
- int ret = 0;
- paramid = param->flags & IW_AUTH_INDEX;
- paramval = param->value;
- switch (paramid) {
- case IW_AUTH_WPA_VERSION:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- break;
- case IW_AUTH_CIPHER_GROUP:
- break;
- case IW_AUTH_KEY_MGMT:
- /*
- * ??? does not use these parameters
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- if (paramval) {
- /* wpa_supplicant is enabling tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = true;
- } else {
- /* wpa_supplicant is disabling tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = false;
- }
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- if (padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption1Enabled) {
- /* it means init value, or using wep,
- * ndisencryptstatus =
- * Ndis802_11Encryption1Enabled,
- * then it needn't reset it;
- */
- break;
- }
- if (paramval) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy =
- _NO_PRIVACY_;
- padapter->securitypriv.AuthAlgrthm = 0;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeOpen;
- }
- break;
- case IW_AUTH_8…