/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
C | 2251 lines | 1998 code | 116 blank | 137 comment | 363 complexity | 93e715edcb86b7a79ec7c5a9857a953b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can 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
-