1554c0a3aSHans de Goede /****************************************************************************** 2554c0a3aSHans de Goede * 3554c0a3aSHans de Goede * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 4554c0a3aSHans de Goede * 5554c0a3aSHans de Goede * This program is free software; you can redistribute it and/or modify it 6554c0a3aSHans de Goede * under the terms of version 2 of the GNU General Public License as 7554c0a3aSHans de Goede * published by the Free Software Foundation. 8554c0a3aSHans de Goede * 9554c0a3aSHans de Goede * This program is distributed in the hope that it will be useful, but WITHOUT 10554c0a3aSHans de Goede * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11554c0a3aSHans de Goede * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12554c0a3aSHans de Goede * more details. 13554c0a3aSHans de Goede * 14554c0a3aSHans de Goede ******************************************************************************/ 15554c0a3aSHans de Goede #define _IOCTL_LINUX_C_ 16554c0a3aSHans de Goede 17554c0a3aSHans de Goede #include <drv_types.h> 18554c0a3aSHans de Goede #include <rtw_debug.h> 19554c0a3aSHans de Goede #include <rtw_mp.h> 20554c0a3aSHans de Goede #include <linux/jiffies.h> 21554c0a3aSHans de Goede 22554c0a3aSHans de Goede #define RTL_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 23554c0a3aSHans de Goede 24554c0a3aSHans de Goede #define SCAN_ITEM_SIZE 768 25554c0a3aSHans de Goede #define MAX_CUSTOM_LEN 64 26554c0a3aSHans de Goede #define RATE_COUNT 4 27554c0a3aSHans de Goede 28554c0a3aSHans de Goede /* combo scan */ 29554c0a3aSHans de Goede #define WEXT_CSCAN_AMOUNT 9 30554c0a3aSHans de Goede #define WEXT_CSCAN_BUF_LEN 360 31554c0a3aSHans de Goede #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" 32554c0a3aSHans de Goede #define WEXT_CSCAN_HEADER_SIZE 12 33554c0a3aSHans de Goede #define WEXT_CSCAN_SSID_SECTION 'S' 34554c0a3aSHans de Goede #define WEXT_CSCAN_CHANNEL_SECTION 'C' 35554c0a3aSHans de Goede #define WEXT_CSCAN_NPROBE_SECTION 'N' 36554c0a3aSHans de Goede #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' 37554c0a3aSHans de Goede #define WEXT_CSCAN_PASV_DWELL_SECTION 'P' 38554c0a3aSHans de Goede #define WEXT_CSCAN_HOME_DWELL_SECTION 'H' 39554c0a3aSHans de Goede #define WEXT_CSCAN_TYPE_SECTION 'T' 40554c0a3aSHans de Goede 41554c0a3aSHans de Goede 42554c0a3aSHans de Goede extern u8 key_2char2num(u8 hch, u8 lch); 43554c0a3aSHans de Goede 44554c0a3aSHans de Goede static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000, 45554c0a3aSHans de Goede 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000}; 46554c0a3aSHans de Goede 47554c0a3aSHans de Goede static const char * const iw_operation_mode[] = 48554c0a3aSHans de Goede { 49554c0a3aSHans de Goede "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor" 50554c0a3aSHans de Goede }; 51554c0a3aSHans de Goede 52554c0a3aSHans de Goede static int hex2num_i(char c) 53554c0a3aSHans de Goede { 54554c0a3aSHans de Goede if (c >= '0' && c <= '9') 55554c0a3aSHans de Goede return c - '0'; 56554c0a3aSHans de Goede if (c >= 'a' && c <= 'f') 57554c0a3aSHans de Goede return c - 'a' + 10; 58554c0a3aSHans de Goede if (c >= 'A' && c <= 'F') 59554c0a3aSHans de Goede return c - 'A' + 10; 60554c0a3aSHans de Goede return -1; 61554c0a3aSHans de Goede } 62554c0a3aSHans de Goede 63554c0a3aSHans de Goede /** 64554c0a3aSHans de Goede * hwaddr_aton - Convert ASCII string to MAC address 65554c0a3aSHans de Goede * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 66554c0a3aSHans de Goede * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 67554c0a3aSHans de Goede * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 68554c0a3aSHans de Goede */ 69554c0a3aSHans de Goede static int hwaddr_aton_i(const char *txt, u8 *addr) 70554c0a3aSHans de Goede { 71554c0a3aSHans de Goede int i; 72554c0a3aSHans de Goede 73554c0a3aSHans de Goede for (i = 0; i < 6; i++) { 74554c0a3aSHans de Goede int a, b; 75554c0a3aSHans de Goede 76554c0a3aSHans de Goede a = hex2num_i(*txt++); 77554c0a3aSHans de Goede if (a < 0) 78554c0a3aSHans de Goede return -1; 79554c0a3aSHans de Goede b = hex2num_i(*txt++); 80554c0a3aSHans de Goede if (b < 0) 81554c0a3aSHans de Goede return -1; 82554c0a3aSHans de Goede *addr++ = (a << 4) | b; 83554c0a3aSHans de Goede if (i < 5 && *txt++ != ':') 84554c0a3aSHans de Goede return -1; 85554c0a3aSHans de Goede } 86554c0a3aSHans de Goede 87554c0a3aSHans de Goede return 0; 88554c0a3aSHans de Goede } 89554c0a3aSHans de Goede 90554c0a3aSHans de Goede void indicate_wx_scan_complete_event(struct adapter *padapter) 91554c0a3aSHans de Goede { 92554c0a3aSHans de Goede union iwreq_data wrqu; 93554c0a3aSHans de Goede 94554c0a3aSHans de Goede memset(&wrqu, 0, sizeof(union iwreq_data)); 95554c0a3aSHans de Goede 96554c0a3aSHans de Goede /* DBG_871X("+rtw_indicate_wx_scan_complete_event\n"); */ 97554c0a3aSHans de Goede } 98554c0a3aSHans de Goede 99554c0a3aSHans de Goede 100554c0a3aSHans de Goede void rtw_indicate_wx_assoc_event(struct adapter *padapter) 101554c0a3aSHans de Goede { 102554c0a3aSHans de Goede union iwreq_data wrqu; 103554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 104554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 105554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 106554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex*)(&(pmlmeinfo->network)); 107554c0a3aSHans de Goede 108554c0a3aSHans de Goede memset(&wrqu, 0, sizeof(union iwreq_data)); 109554c0a3aSHans de Goede 110554c0a3aSHans de Goede wrqu.ap_addr.sa_family = ARPHRD_ETHER; 111554c0a3aSHans de Goede 112554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ==true) 113554c0a3aSHans de Goede memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN); 114554c0a3aSHans de Goede else 115554c0a3aSHans de Goede memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN); 116554c0a3aSHans de Goede 117554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "assoc success\n"); 118554c0a3aSHans de Goede } 119554c0a3aSHans de Goede 120554c0a3aSHans de Goede void rtw_indicate_wx_disassoc_event(struct adapter *padapter) 121554c0a3aSHans de Goede { 122554c0a3aSHans de Goede union iwreq_data wrqu; 123554c0a3aSHans de Goede 124554c0a3aSHans de Goede memset(&wrqu, 0, sizeof(union iwreq_data)); 125554c0a3aSHans de Goede 126554c0a3aSHans de Goede wrqu.ap_addr.sa_family = ARPHRD_ETHER; 127554c0a3aSHans de Goede memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 128554c0a3aSHans de Goede } 129554c0a3aSHans de Goede 130554c0a3aSHans de Goede /* 131554c0a3aSHans de Goede uint rtw_is_cckrates_included(u8 *rate) 132554c0a3aSHans de Goede { 133554c0a3aSHans de Goede u32 i = 0; 134554c0a3aSHans de Goede 135554c0a3aSHans de Goede while (rate[i]!= 0) 136554c0a3aSHans de Goede { 137554c0a3aSHans de Goede if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) || 138554c0a3aSHans de Goede (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22)) 139554c0a3aSHans de Goede return true; 140554c0a3aSHans de Goede i++; 141554c0a3aSHans de Goede } 142554c0a3aSHans de Goede 143554c0a3aSHans de Goede return false; 144554c0a3aSHans de Goede } 145554c0a3aSHans de Goede 146554c0a3aSHans de Goede uint rtw_is_cckratesonly_included(u8 *rate) 147554c0a3aSHans de Goede { 148554c0a3aSHans de Goede u32 i = 0; 149554c0a3aSHans de Goede 150554c0a3aSHans de Goede while (rate[i]!= 0) 151554c0a3aSHans de Goede { 152554c0a3aSHans de Goede if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) && 153554c0a3aSHans de Goede (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22)) 154554c0a3aSHans de Goede return false; 155554c0a3aSHans de Goede i++; 156554c0a3aSHans de Goede } 157554c0a3aSHans de Goede 158554c0a3aSHans de Goede return true; 159554c0a3aSHans de Goede } 160554c0a3aSHans de Goede */ 161554c0a3aSHans de Goede 162554c0a3aSHans de Goede static char *translate_scan(struct adapter *padapter, 163554c0a3aSHans de Goede struct iw_request_info* info, struct wlan_network *pnetwork, 164554c0a3aSHans de Goede char *start, char *stop) 165554c0a3aSHans de Goede { 166554c0a3aSHans de Goede struct iw_event iwe; 167554c0a3aSHans de Goede u16 cap; 168554c0a3aSHans de Goede u32 ht_ielen = 0; 169554c0a3aSHans de Goede char *custom = NULL; 170554c0a3aSHans de Goede char *p; 171554c0a3aSHans de Goede u16 max_rate = 0, rate, ht_cap =false, vht_cap = false; 172554c0a3aSHans de Goede u32 i = 0; 173554c0a3aSHans de Goede u8 bw_40MHz = 0, short_GI = 0; 174554c0a3aSHans de Goede u16 mcs_rate = 0, vht_data_rate = 0; 175554c0a3aSHans de Goede u8 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12); 176554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 177554c0a3aSHans de Goede u8 ss, sq; 178554c0a3aSHans de Goede 179554c0a3aSHans de Goede /* AP MAC address */ 180554c0a3aSHans de Goede iwe.cmd = SIOCGIWAP; 181554c0a3aSHans de Goede iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 182554c0a3aSHans de Goede 183554c0a3aSHans de Goede memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN); 184554c0a3aSHans de Goede start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); 185554c0a3aSHans de Goede 186554c0a3aSHans de Goede /* Add the ESSID */ 187554c0a3aSHans de Goede iwe.cmd = SIOCGIWESSID; 188554c0a3aSHans de Goede iwe.u.data.flags = 1; 189554c0a3aSHans de Goede iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32); 190554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); 191554c0a3aSHans de Goede 192554c0a3aSHans de Goede /* parsing HT_CAP_IE */ 193554c0a3aSHans de Goede if (pnetwork->network.Reserved[0] == 2) /* Probe Request */ 194554c0a3aSHans de Goede { 195554c0a3aSHans de Goede p = rtw_get_ie(&pnetwork->network.IEs[0], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength); 196554c0a3aSHans de Goede } 197554c0a3aSHans de Goede else 198554c0a3aSHans de Goede { 199554c0a3aSHans de Goede p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12); 200554c0a3aSHans de Goede } 201554c0a3aSHans de Goede if (p && ht_ielen>0) 202554c0a3aSHans de Goede { 203554c0a3aSHans de Goede struct rtw_ieee80211_ht_cap *pht_capie; 204554c0a3aSHans de Goede ht_cap = true; 205554c0a3aSHans de Goede pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); 206554c0a3aSHans de Goede memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2); 207554c0a3aSHans de Goede bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; 208554c0a3aSHans de Goede short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; 209554c0a3aSHans de Goede } 210554c0a3aSHans de Goede 211554c0a3aSHans de Goede /* Add the protocol name */ 212554c0a3aSHans de Goede iwe.cmd = SIOCGIWNAME; 213554c0a3aSHans de Goede if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) == true) 214554c0a3aSHans de Goede { 215554c0a3aSHans de Goede if (ht_cap == true) 216554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn"); 217554c0a3aSHans de Goede else 218554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b"); 219554c0a3aSHans de Goede } 220554c0a3aSHans de Goede else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) == true) 221554c0a3aSHans de Goede { 222554c0a3aSHans de Goede if (ht_cap == true) 223554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn"); 224554c0a3aSHans de Goede else 225554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg"); 226554c0a3aSHans de Goede } 227554c0a3aSHans de Goede else 228554c0a3aSHans de Goede { 229554c0a3aSHans de Goede if (pnetwork->network.Configuration.DSConfig > 14) 230554c0a3aSHans de Goede { 231554c0a3aSHans de Goede if (vht_cap == true) 232554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC"); 233554c0a3aSHans de Goede else if (ht_cap == true) 234554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an"); 235554c0a3aSHans de Goede else 236554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a"); 237554c0a3aSHans de Goede } 238554c0a3aSHans de Goede else 239554c0a3aSHans de Goede { 240554c0a3aSHans de Goede if (ht_cap == true) 241554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn"); 242554c0a3aSHans de Goede else 243554c0a3aSHans de Goede snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g"); 244554c0a3aSHans de Goede } 245554c0a3aSHans de Goede } 246554c0a3aSHans de Goede 247554c0a3aSHans de Goede start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); 248554c0a3aSHans de Goede 249554c0a3aSHans de Goede /* Add mode */ 250554c0a3aSHans de Goede if (pnetwork->network.Reserved[0] == 2) /* Probe Request */ 251554c0a3aSHans de Goede { 252554c0a3aSHans de Goede cap = 0; 253554c0a3aSHans de Goede } 254554c0a3aSHans de Goede else 255554c0a3aSHans de Goede { 256554c0a3aSHans de Goede __le16 le_tmp; 257554c0a3aSHans de Goede 258554c0a3aSHans de Goede iwe.cmd = SIOCGIWMODE; 259554c0a3aSHans de Goede memcpy((u8 *)&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2); 260554c0a3aSHans de Goede cap = le16_to_cpu(le_tmp); 261554c0a3aSHans de Goede } 262554c0a3aSHans de Goede 263554c0a3aSHans de Goede if (cap & (WLAN_CAPABILITY_IBSS |WLAN_CAPABILITY_BSS)) { 264554c0a3aSHans de Goede if (cap & WLAN_CAPABILITY_BSS) 265554c0a3aSHans de Goede iwe.u.mode = IW_MODE_MASTER; 266554c0a3aSHans de Goede else 267554c0a3aSHans de Goede iwe.u.mode = IW_MODE_ADHOC; 268554c0a3aSHans de Goede 269554c0a3aSHans de Goede start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); 270554c0a3aSHans de Goede } 271554c0a3aSHans de Goede 272554c0a3aSHans de Goede if (pnetwork->network.Configuration.DSConfig<1 /*|| pnetwork->network.Configuration.DSConfig>14*/) 273554c0a3aSHans de Goede pnetwork->network.Configuration.DSConfig = 1; 274554c0a3aSHans de Goede 275554c0a3aSHans de Goede /* Add frequency/channel */ 276554c0a3aSHans de Goede iwe.cmd = SIOCGIWFREQ; 277554c0a3aSHans de Goede iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000; 278554c0a3aSHans de Goede iwe.u.freq.e = 1; 279554c0a3aSHans de Goede iwe.u.freq.i = pnetwork->network.Configuration.DSConfig; 280554c0a3aSHans de Goede start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); 281554c0a3aSHans de Goede 282554c0a3aSHans de Goede /* Add encryption capability */ 283554c0a3aSHans de Goede iwe.cmd = SIOCGIWENCODE; 284554c0a3aSHans de Goede if (cap & WLAN_CAPABILITY_PRIVACY) 285554c0a3aSHans de Goede iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 286554c0a3aSHans de Goede else 287554c0a3aSHans de Goede iwe.u.data.flags = IW_ENCODE_DISABLED; 288554c0a3aSHans de Goede iwe.u.data.length = 0; 289554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); 290554c0a3aSHans de Goede 291554c0a3aSHans de Goede /*Add basic and extended rates */ 292554c0a3aSHans de Goede max_rate = 0; 293554c0a3aSHans de Goede custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC); 294554c0a3aSHans de Goede if (!custom) 295554c0a3aSHans de Goede return start; 296554c0a3aSHans de Goede p = custom; 297554c0a3aSHans de Goede p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); 298554c0a3aSHans de Goede while (pnetwork->network.SupportedRates[i]!= 0) 299554c0a3aSHans de Goede { 300554c0a3aSHans de Goede rate = pnetwork->network.SupportedRates[i]&0x7F; 301554c0a3aSHans de Goede if (rate > max_rate) 302554c0a3aSHans de Goede max_rate = rate; 303554c0a3aSHans de Goede p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), 304554c0a3aSHans de Goede "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); 305554c0a3aSHans de Goede i++; 306554c0a3aSHans de Goede } 307554c0a3aSHans de Goede 308554c0a3aSHans de Goede if (vht_cap == true) { 309554c0a3aSHans de Goede max_rate = vht_data_rate; 310554c0a3aSHans de Goede } 311554c0a3aSHans de Goede else if (ht_cap == true) 312554c0a3aSHans de Goede { 313554c0a3aSHans de Goede if (mcs_rate&0x8000)/* MCS15 */ 314554c0a3aSHans de Goede { 315554c0a3aSHans de Goede max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 316554c0a3aSHans de Goede 317554c0a3aSHans de Goede } 318554c0a3aSHans de Goede else if (mcs_rate&0x0080)/* MCS7 */ 319554c0a3aSHans de Goede { 320554c0a3aSHans de Goede max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); 321554c0a3aSHans de Goede } 322554c0a3aSHans de Goede else/* default MCS7 */ 323554c0a3aSHans de Goede { 324554c0a3aSHans de Goede /* DBG_871X("wx_get_scan, mcs_rate_bitmap = 0x%x\n", mcs_rate); */ 325554c0a3aSHans de Goede max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede 328554c0a3aSHans de Goede max_rate = max_rate*2;/* Mbps/2; */ 329554c0a3aSHans de Goede } 330554c0a3aSHans de Goede 331554c0a3aSHans de Goede iwe.cmd = SIOCGIWRATE; 332554c0a3aSHans de Goede iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 333554c0a3aSHans de Goede iwe.u.bitrate.value = max_rate * 500000; 334554c0a3aSHans de Goede start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN); 335554c0a3aSHans de Goede 336554c0a3aSHans de Goede /* parsing WPA/WPA2 IE */ 337554c0a3aSHans de Goede if (pnetwork->network.Reserved[0] != 2) /* Probe Request */ 338554c0a3aSHans de Goede { 339554c0a3aSHans de Goede u8 *buf; 340554c0a3aSHans de Goede u8 wpa_ie[255], rsn_ie[255]; 341554c0a3aSHans de Goede u16 wpa_len = 0, rsn_len = 0; 342554c0a3aSHans de Goede u8 *p; 343554c0a3aSHans de Goede sint out_len = 0; 344554c0a3aSHans de Goede out_len =rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, rsn_ie,&rsn_len, wpa_ie,&wpa_len); 345554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid)); 346554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); 347554c0a3aSHans de Goede 348554c0a3aSHans de Goede buf = kzalloc(MAX_WPA_IE_LEN*2, GFP_KERNEL); 349554c0a3aSHans de Goede if (!buf) 350554c0a3aSHans de Goede return start; 351554c0a3aSHans de Goede if (wpa_len > 0) { 352554c0a3aSHans de Goede p =buf; 353554c0a3aSHans de Goede p += sprintf(p, "wpa_ie ="); 354554c0a3aSHans de Goede for (i = 0; i < wpa_len; i++) { 355554c0a3aSHans de Goede p += sprintf(p, "%02x", wpa_ie[i]); 356554c0a3aSHans de Goede } 357554c0a3aSHans de Goede 358554c0a3aSHans de Goede if (wpa_len > 100) { 359554c0a3aSHans de Goede printk("-----------------Len %d----------------\n", wpa_len); 360554c0a3aSHans de Goede for (i = 0; i < wpa_len; i++) { 361554c0a3aSHans de Goede printk("%02x ", wpa_ie[i]); 362554c0a3aSHans de Goede } 363554c0a3aSHans de Goede printk("\n"); 364554c0a3aSHans de Goede printk("-----------------Len %d----------------\n", wpa_len); 365554c0a3aSHans de Goede } 366554c0a3aSHans de Goede 367554c0a3aSHans de Goede memset(&iwe, 0, sizeof(iwe)); 368554c0a3aSHans de Goede iwe.cmd = IWEVCUSTOM; 369554c0a3aSHans de Goede iwe.u.data.length = strlen(buf); 370554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, buf); 371554c0a3aSHans de Goede 372554c0a3aSHans de Goede memset(&iwe, 0, sizeof(iwe)); 373554c0a3aSHans de Goede iwe.cmd =IWEVGENIE; 374554c0a3aSHans de Goede iwe.u.data.length = wpa_len; 375554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie); 376554c0a3aSHans de Goede } 377554c0a3aSHans de Goede if (rsn_len > 0) { 378554c0a3aSHans de Goede p = buf; 379554c0a3aSHans de Goede memset(buf, 0, MAX_WPA_IE_LEN*2); 380554c0a3aSHans de Goede p += sprintf(p, "rsn_ie ="); 381554c0a3aSHans de Goede for (i = 0; i < rsn_len; i++) 382554c0a3aSHans de Goede p += sprintf(p, "%02x", rsn_ie[i]); 383554c0a3aSHans de Goede memset(&iwe, 0, sizeof(iwe)); 384554c0a3aSHans de Goede iwe.cmd = IWEVCUSTOM; 385554c0a3aSHans de Goede iwe.u.data.length = strlen(buf); 386554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, buf); 387554c0a3aSHans de Goede 388554c0a3aSHans de Goede memset(&iwe, 0, sizeof(iwe)); 389554c0a3aSHans de Goede iwe.cmd =IWEVGENIE; 390554c0a3aSHans de Goede iwe.u.data.length = rsn_len; 391554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie); 392554c0a3aSHans de Goede } 393554c0a3aSHans de Goede kfree(buf); 394554c0a3aSHans de Goede } 395554c0a3aSHans de Goede 396554c0a3aSHans de Goede { /* parsing WPS IE */ 397554c0a3aSHans de Goede uint cnt = 0, total_ielen; 398554c0a3aSHans de Goede u8 *wpsie_ptr = NULL; 399554c0a3aSHans de Goede uint wps_ielen = 0; 400554c0a3aSHans de Goede 401554c0a3aSHans de Goede u8 *ie_ptr = pnetwork->network.IEs + ie_offset; 402554c0a3aSHans de Goede total_ielen = pnetwork->network.IELength - ie_offset; 403554c0a3aSHans de Goede 404554c0a3aSHans de Goede if (pnetwork->network.Reserved[0] == 2) /* Probe Request */ 405554c0a3aSHans de Goede { 406554c0a3aSHans de Goede ie_ptr = pnetwork->network.IEs; 407554c0a3aSHans de Goede total_ielen = pnetwork->network.IELength; 408554c0a3aSHans de Goede } 409554c0a3aSHans de Goede else /* Beacon or Probe Respones */ 410554c0a3aSHans de Goede { 411554c0a3aSHans de Goede ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_; 412554c0a3aSHans de Goede total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_; 413554c0a3aSHans de Goede } 414554c0a3aSHans de Goede 415554c0a3aSHans de Goede while (cnt < total_ielen) 416554c0a3aSHans de Goede { 417554c0a3aSHans de Goede if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen>2)) 418554c0a3aSHans de Goede { 419554c0a3aSHans de Goede wpsie_ptr = &ie_ptr[cnt]; 420554c0a3aSHans de Goede iwe.cmd =IWEVGENIE; 421554c0a3aSHans de Goede iwe.u.data.length = (u16)wps_ielen; 422554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr); 423554c0a3aSHans de Goede } 424554c0a3aSHans de Goede cnt+=ie_ptr[cnt+1]+2; /* goto next */ 425554c0a3aSHans de Goede } 426554c0a3aSHans de Goede } 427554c0a3aSHans de Goede 428554c0a3aSHans de Goede /* Add quality statistics */ 429554c0a3aSHans de Goede iwe.cmd = IWEVQUAL; 430554c0a3aSHans de Goede iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED 431554c0a3aSHans de Goede #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) 432554c0a3aSHans de Goede | IW_QUAL_NOISE_UPDATED 433554c0a3aSHans de Goede #else 434554c0a3aSHans de Goede | IW_QUAL_NOISE_INVALID 435554c0a3aSHans de Goede #endif 436554c0a3aSHans de Goede #ifdef CONFIG_SIGNAL_DISPLAY_DBM 437554c0a3aSHans de Goede | IW_QUAL_DBM 438554c0a3aSHans de Goede #endif 439554c0a3aSHans de Goede ; 440554c0a3aSHans de Goede 441554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == true && 442554c0a3aSHans de Goede is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) { 443554c0a3aSHans de Goede ss = padapter->recvpriv.signal_strength; 444554c0a3aSHans de Goede sq = padapter->recvpriv.signal_qual; 445554c0a3aSHans de Goede } else { 446554c0a3aSHans de Goede ss = pnetwork->network.PhyInfo.SignalStrength; 447554c0a3aSHans de Goede sq = pnetwork->network.PhyInfo.SignalQuality; 448554c0a3aSHans de Goede } 449554c0a3aSHans de Goede 450554c0a3aSHans de Goede 451554c0a3aSHans de Goede #ifdef CONFIG_SIGNAL_DISPLAY_DBM 452554c0a3aSHans de Goede iwe.u.qual.level = (u8) translate_percentage_to_dbm(ss);/* dbm */ 453554c0a3aSHans de Goede #else 454554c0a3aSHans de Goede #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING 455554c0a3aSHans de Goede { 456554c0a3aSHans de Goede /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */ 457554c0a3aSHans de Goede 458554c0a3aSHans de Goede struct hal_com_data *pHal = GET_HAL_DATA(padapter); 459554c0a3aSHans de Goede 460554c0a3aSHans de Goede iwe.u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss); 461554c0a3aSHans de Goede } 462554c0a3aSHans de Goede #else 463554c0a3aSHans de Goede iwe.u.qual.level = (u8)ss;/* */ 464554c0a3aSHans de Goede #endif 465554c0a3aSHans de Goede #endif 466554c0a3aSHans de Goede 467554c0a3aSHans de Goede iwe.u.qual.qual = (u8)sq; /* signal quality */ 468554c0a3aSHans de Goede 469554c0a3aSHans de Goede #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) 470554c0a3aSHans de Goede { 471554c0a3aSHans de Goede s16 tmp_noise = 0; 472554c0a3aSHans de Goede rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(pnetwork->network.Configuration.DSConfig), &(tmp_noise)); 473554c0a3aSHans de Goede iwe.u.qual.noise = tmp_noise ; 474554c0a3aSHans de Goede } 475554c0a3aSHans de Goede #else 476554c0a3aSHans de Goede iwe.u.qual.noise = 0; /* noise level */ 477554c0a3aSHans de Goede #endif 478554c0a3aSHans de Goede 479554c0a3aSHans de Goede /* DBG_871X("iqual =%d, ilevel =%d, inoise =%d, iupdated =%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated); */ 480554c0a3aSHans de Goede 481554c0a3aSHans de Goede start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); 482554c0a3aSHans de Goede 483554c0a3aSHans de Goede { 484554c0a3aSHans de Goede u8 *buf; 485554c0a3aSHans de Goede u8 *p, *pos; 486554c0a3aSHans de Goede 487554c0a3aSHans de Goede buf = kzalloc(MAX_WPA_IE_LEN, GFP_KERNEL); 488554c0a3aSHans de Goede if (!buf) 489554c0a3aSHans de Goede goto exit; 490554c0a3aSHans de Goede p = buf; 491554c0a3aSHans de Goede pos = pnetwork->network.Reserved; 492554c0a3aSHans de Goede p += sprintf(p, "fm =%02X%02X", pos[1], pos[0]); 493554c0a3aSHans de Goede memset(&iwe, 0, sizeof(iwe)); 494554c0a3aSHans de Goede iwe.cmd = IWEVCUSTOM; 495554c0a3aSHans de Goede iwe.u.data.length = strlen(buf); 496554c0a3aSHans de Goede start = iwe_stream_add_point(info, start, stop, &iwe, buf); 497554c0a3aSHans de Goede kfree(buf); 498554c0a3aSHans de Goede } 499554c0a3aSHans de Goede exit: 500554c0a3aSHans de Goede kfree(custom); 501554c0a3aSHans de Goede 502554c0a3aSHans de Goede return start; 503554c0a3aSHans de Goede } 504554c0a3aSHans de Goede 505554c0a3aSHans de Goede static int wpa_set_auth_algs(struct net_device *dev, u32 value) 506554c0a3aSHans de Goede { 507554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *) rtw_netdev_priv(dev); 508554c0a3aSHans de Goede int ret = 0; 509554c0a3aSHans de Goede 510554c0a3aSHans de Goede if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) 511554c0a3aSHans de Goede { 512554c0a3aSHans de Goede DBG_871X("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value); 513554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 514554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch; 515554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; 516554c0a3aSHans de Goede } 517554c0a3aSHans de Goede else if (value & AUTH_ALG_SHARED_KEY) 518554c0a3aSHans de Goede { 519554c0a3aSHans de Goede DBG_871X("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n", value); 520554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 521554c0a3aSHans de Goede 522554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared; 523554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; 524554c0a3aSHans de Goede } 525554c0a3aSHans de Goede else if (value & AUTH_ALG_OPEN_SYSTEM) 526554c0a3aSHans de Goede { 527554c0a3aSHans de Goede DBG_871X("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n"); 528554c0a3aSHans de Goede /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */ 529554c0a3aSHans de Goede if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) 530554c0a3aSHans de Goede { 531554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; 532554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; 533554c0a3aSHans de Goede } 534554c0a3aSHans de Goede 535554c0a3aSHans de Goede } 536554c0a3aSHans de Goede else if (value & AUTH_ALG_LEAP) 537554c0a3aSHans de Goede { 538554c0a3aSHans de Goede DBG_871X("wpa_set_auth_algs, AUTH_ALG_LEAP\n"); 539554c0a3aSHans de Goede } 540554c0a3aSHans de Goede else 541554c0a3aSHans de Goede { 542554c0a3aSHans de Goede DBG_871X("wpa_set_auth_algs, error!\n"); 543554c0a3aSHans de Goede ret = -EINVAL; 544554c0a3aSHans de Goede } 545554c0a3aSHans de Goede 546554c0a3aSHans de Goede return ret; 547554c0a3aSHans de Goede 548554c0a3aSHans de Goede } 549554c0a3aSHans de Goede 550554c0a3aSHans de Goede static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) 551554c0a3aSHans de Goede { 552554c0a3aSHans de Goede int ret = 0; 553554c0a3aSHans de Goede u32 wep_key_idx, wep_key_len, wep_total_len; 554554c0a3aSHans de Goede struct ndis_802_11_wep *pwep = NULL; 555554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 556554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 557554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 558554c0a3aSHans de Goede 559554c0a3aSHans de Goede param->u.crypt.err = 0; 560554c0a3aSHans de Goede param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; 561554c0a3aSHans de Goede 562554c0a3aSHans de Goede if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) 563554c0a3aSHans de Goede { 564554c0a3aSHans de Goede ret = -EINVAL; 565554c0a3aSHans de Goede goto exit; 566554c0a3aSHans de Goede } 567554c0a3aSHans de Goede 568554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 569554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 570554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 571554c0a3aSHans de Goede { 572554c0a3aSHans de Goede 5736557ddfeSLarry Finger if (param->u.crypt.idx >= WEP_KEYS || 574554c0a3aSHans de Goede param->u.crypt.idx >= BIP_MAX_KEYID) { 575554c0a3aSHans de Goede ret = -EINVAL; 576554c0a3aSHans de Goede goto exit; 577554c0a3aSHans de Goede } 578554c0a3aSHans de Goede } 579554c0a3aSHans de Goede else 580554c0a3aSHans de Goede { 581554c0a3aSHans de Goede { 582554c0a3aSHans de Goede ret = -EINVAL; 583554c0a3aSHans de Goede goto exit; 584554c0a3aSHans de Goede } 585554c0a3aSHans de Goede } 586554c0a3aSHans de Goede 587554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "WEP") == 0) 588554c0a3aSHans de Goede { 589554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n")); 590554c0a3aSHans de Goede DBG_871X("wpa_set_encryption, crypt.alg = WEP\n"); 591554c0a3aSHans de Goede 592554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 593554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 594554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; 595554c0a3aSHans de Goede 596554c0a3aSHans de Goede wep_key_idx = param->u.crypt.idx; 597554c0a3aSHans de Goede wep_key_len = param->u.crypt.key_len; 598554c0a3aSHans de Goede 599554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx)); 600554c0a3aSHans de Goede DBG_871X("(1)wep_key_idx =%d\n", wep_key_idx); 601554c0a3aSHans de Goede 602554c0a3aSHans de Goede if (wep_key_idx > WEP_KEYS) 603554c0a3aSHans de Goede return -EINVAL; 604554c0a3aSHans de Goede 605554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx)); 606554c0a3aSHans de Goede 607554c0a3aSHans de Goede if (wep_key_len > 0) 608554c0a3aSHans de Goede { 609554c0a3aSHans de Goede wep_key_len = wep_key_len <= 5 ? 5 : 13; 610554c0a3aSHans de Goede wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); 611554c0a3aSHans de Goede pwep =(struct ndis_802_11_wep *) rtw_malloc(wep_total_len); 612554c0a3aSHans de Goede if (pwep == NULL) { 613554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n")); 614554c0a3aSHans de Goede goto exit; 615554c0a3aSHans de Goede } 616554c0a3aSHans de Goede 617554c0a3aSHans de Goede memset(pwep, 0, wep_total_len); 618554c0a3aSHans de Goede 619554c0a3aSHans de Goede pwep->KeyLength = wep_key_len; 620554c0a3aSHans de Goede pwep->Length = wep_total_len; 621554c0a3aSHans de Goede 622554c0a3aSHans de Goede if (wep_key_len == 13) 623554c0a3aSHans de Goede { 624554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; 625554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_; 626554c0a3aSHans de Goede } 627554c0a3aSHans de Goede } 628554c0a3aSHans de Goede else { 629554c0a3aSHans de Goede ret = -EINVAL; 630554c0a3aSHans de Goede goto exit; 631554c0a3aSHans de Goede } 632554c0a3aSHans de Goede 633554c0a3aSHans de Goede pwep->KeyIndex = wep_key_idx; 634554c0a3aSHans de Goede pwep->KeyIndex |= 0x80000000; 635554c0a3aSHans de Goede 636554c0a3aSHans de Goede memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); 637554c0a3aSHans de Goede 638554c0a3aSHans de Goede if (param->u.crypt.set_tx) 639554c0a3aSHans de Goede { 640554c0a3aSHans de Goede DBG_871X("wep, set_tx = 1\n"); 641554c0a3aSHans de Goede 642554c0a3aSHans de Goede if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL) 643554c0a3aSHans de Goede { 644554c0a3aSHans de Goede ret = -EOPNOTSUPP ; 645554c0a3aSHans de Goede } 646554c0a3aSHans de Goede } 647554c0a3aSHans de Goede else 648554c0a3aSHans de Goede { 649554c0a3aSHans de Goede DBG_871X("wep, set_tx = 0\n"); 650554c0a3aSHans de Goede 651554c0a3aSHans de Goede /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */ 652554c0a3aSHans de Goede /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */ 653554c0a3aSHans de Goede 654554c0a3aSHans de Goede if (wep_key_idx >= WEP_KEYS) { 655554c0a3aSHans de Goede ret = -EOPNOTSUPP ; 656554c0a3aSHans de Goede goto exit; 657554c0a3aSHans de Goede } 658554c0a3aSHans de Goede 659554c0a3aSHans de Goede memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength); 660554c0a3aSHans de Goede psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength; 661554c0a3aSHans de Goede rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true); 662554c0a3aSHans de Goede } 663554c0a3aSHans de Goede 664554c0a3aSHans de Goede goto exit; 665554c0a3aSHans de Goede } 666554c0a3aSHans de Goede 667554c0a3aSHans de Goede if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) /* 802_1x */ 668554c0a3aSHans de Goede { 669554c0a3aSHans de Goede struct sta_info * psta,*pbcmc_sta; 670554c0a3aSHans de Goede struct sta_priv * pstapriv = &padapter->stapriv; 671554c0a3aSHans de Goede 672554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) /* sta mode */ 673554c0a3aSHans de Goede { 674554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); 675554c0a3aSHans de Goede if (psta == NULL) { 676554c0a3aSHans de Goede /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */ 677554c0a3aSHans de Goede } 678554c0a3aSHans de Goede else 679554c0a3aSHans de Goede { 680554c0a3aSHans de Goede /* Jeff: don't disable ieee8021x_blocked while clearing key */ 681554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "none") != 0) 682554c0a3aSHans de Goede psta->ieee8021x_blocked = false; 683554c0a3aSHans de Goede 684554c0a3aSHans de Goede if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)|| 685554c0a3aSHans de Goede (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) 686554c0a3aSHans de Goede { 687554c0a3aSHans de Goede psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; 688554c0a3aSHans de Goede } 689554c0a3aSHans de Goede 690554c0a3aSHans de Goede if (param->u.crypt.set_tx == 1)/* pairwise key */ 691554c0a3aSHans de Goede { 692554c0a3aSHans de Goede memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 693554c0a3aSHans de Goede 694554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "TKIP") == 0)/* set mic key */ 695554c0a3aSHans de Goede { 696554c0a3aSHans de Goede /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */ 697554c0a3aSHans de Goede memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8); 698554c0a3aSHans de Goede memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8); 699554c0a3aSHans de Goede 700554c0a3aSHans de Goede padapter->securitypriv.busetkipkey =false; 701554c0a3aSHans de Goede /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */ 702554c0a3aSHans de Goede } 703554c0a3aSHans de Goede 704554c0a3aSHans de Goede /* DEBUG_ERR((" param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */ 705554c0a3aSHans de Goede DBG_871X(" ~~~~set sta key:unicastkey\n"); 706554c0a3aSHans de Goede 707554c0a3aSHans de Goede rtw_setstakey_cmd(padapter, psta, true, true); 708554c0a3aSHans de Goede } 709554c0a3aSHans de Goede else/* group key */ 710554c0a3aSHans de Goede { 711554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) 712554c0a3aSHans de Goede { 713554c0a3aSHans de Goede memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 714554c0a3aSHans de Goede /* only TKIP group key need to install this */ 715554c0a3aSHans de Goede if (param->u.crypt.key_len > 16) 716554c0a3aSHans de Goede { 717554c0a3aSHans de Goede memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[16]), 8); 718554c0a3aSHans de Goede memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[24]), 8); 719554c0a3aSHans de Goede } 720554c0a3aSHans de Goede padapter->securitypriv.binstallGrpkey = true; 721554c0a3aSHans de Goede /* DEBUG_ERR((" param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */ 722554c0a3aSHans de Goede DBG_871X(" ~~~~set sta key:groupkey\n"); 723554c0a3aSHans de Goede 724554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx; 725554c0a3aSHans de Goede 726554c0a3aSHans de Goede rtw_set_key(padapter,&padapter->securitypriv, param->u.crypt.idx, 1, true); 727554c0a3aSHans de Goede } 728554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "BIP") == 0) 729554c0a3aSHans de Goede { 730554c0a3aSHans de Goede /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */ 731554c0a3aSHans de Goede /* save the IGTK key, length 16 bytes */ 732554c0a3aSHans de Goede memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 733554c0a3aSHans de Goede /*printk("IGTK key below:\n"); 734554c0a3aSHans de Goede for (no = 0;no<16;no++) 735554c0a3aSHans de Goede printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]); 736554c0a3aSHans de Goede printk("\n");*/ 737554c0a3aSHans de Goede padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx; 738554c0a3aSHans de Goede padapter->securitypriv.binstallBIPkey = true; 739554c0a3aSHans de Goede DBG_871X(" ~~~~set sta key:IGKT\n"); 740554c0a3aSHans de Goede } 741554c0a3aSHans de Goede } 742554c0a3aSHans de Goede } 743554c0a3aSHans de Goede 744554c0a3aSHans de Goede pbcmc_sta =rtw_get_bcmc_stainfo(padapter); 745554c0a3aSHans de Goede if (pbcmc_sta == NULL) 746554c0a3aSHans de Goede { 747554c0a3aSHans de Goede /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */ 748554c0a3aSHans de Goede } 749554c0a3aSHans de Goede else 750554c0a3aSHans de Goede { 751554c0a3aSHans de Goede /* Jeff: don't disable ieee8021x_blocked while clearing key */ 752554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "none") != 0) 753554c0a3aSHans de Goede pbcmc_sta->ieee8021x_blocked = false; 754554c0a3aSHans de Goede 755554c0a3aSHans de Goede if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)|| 756554c0a3aSHans de Goede (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) 757554c0a3aSHans de Goede { 758554c0a3aSHans de Goede pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; 759554c0a3aSHans de Goede } 760554c0a3aSHans de Goede } 761554c0a3aSHans de Goede } 762554c0a3aSHans de Goede else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) /* adhoc mode */ 763554c0a3aSHans de Goede { 764554c0a3aSHans de Goede } 765554c0a3aSHans de Goede } 766554c0a3aSHans de Goede 767554c0a3aSHans de Goede exit: 768554c0a3aSHans de Goede 769554c0a3aSHans de Goede kfree((u8 *)pwep); 770554c0a3aSHans de Goede return ret; 771554c0a3aSHans de Goede } 772554c0a3aSHans de Goede 773554c0a3aSHans de Goede static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen) 774554c0a3aSHans de Goede { 775554c0a3aSHans de Goede u8 *buf = NULL, *pos = NULL; 776554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 777554c0a3aSHans de Goede int ret = 0; 778554c0a3aSHans de Goede u8 null_addr[]= {0, 0, 0, 0, 0, 0}; 779554c0a3aSHans de Goede 780554c0a3aSHans de Goede if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) { 781554c0a3aSHans de Goede _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); 782554c0a3aSHans de Goede if (pie == NULL) 783554c0a3aSHans de Goede return ret; 784554c0a3aSHans de Goede else 785554c0a3aSHans de Goede return -EINVAL; 786554c0a3aSHans de Goede } 787554c0a3aSHans de Goede 788554c0a3aSHans de Goede if (ielen) 789554c0a3aSHans de Goede { 790554c0a3aSHans de Goede buf = rtw_zmalloc(ielen); 791554c0a3aSHans de Goede if (buf == NULL) { 792554c0a3aSHans de Goede ret = -ENOMEM; 793554c0a3aSHans de Goede goto exit; 794554c0a3aSHans de Goede } 795554c0a3aSHans de Goede 796554c0a3aSHans de Goede memcpy(buf, pie , ielen); 797554c0a3aSHans de Goede 798554c0a3aSHans de Goede /* dump */ 799554c0a3aSHans de Goede { 800554c0a3aSHans de Goede int i; 801554c0a3aSHans de Goede DBG_871X("\n wpa_ie(length:%d):\n", ielen); 802554c0a3aSHans de Goede for (i = 0;i<ielen;i =i+8) 803554c0a3aSHans de Goede DBG_871X("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]); 804554c0a3aSHans de Goede } 805554c0a3aSHans de Goede 806554c0a3aSHans de Goede pos = buf; 807554c0a3aSHans de Goede if (ielen < RSN_HEADER_LEN) { 808554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen)); 809554c0a3aSHans de Goede ret = -1; 810554c0a3aSHans de Goede goto exit; 811554c0a3aSHans de Goede } 812554c0a3aSHans de Goede 813554c0a3aSHans de Goede if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) 814554c0a3aSHans de Goede { 815554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; 816554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =Ndis802_11AuthModeWPAPSK; 817554c0a3aSHans de Goede memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen); 818554c0a3aSHans de Goede } 819554c0a3aSHans de Goede 820554c0a3aSHans de Goede if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) 821554c0a3aSHans de Goede { 822554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; 823554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =Ndis802_11AuthModeWPA2PSK; 824554c0a3aSHans de Goede memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen); 825554c0a3aSHans de Goede } 826554c0a3aSHans de Goede 827554c0a3aSHans de Goede if (group_cipher == 0) 828554c0a3aSHans de Goede { 829554c0a3aSHans de Goede group_cipher = WPA_CIPHER_NONE; 830554c0a3aSHans de Goede } 831554c0a3aSHans de Goede if (pairwise_cipher == 0) 832554c0a3aSHans de Goede { 833554c0a3aSHans de Goede pairwise_cipher = WPA_CIPHER_NONE; 834554c0a3aSHans de Goede } 835554c0a3aSHans de Goede 836554c0a3aSHans de Goede switch (group_cipher) 837554c0a3aSHans de Goede { 838554c0a3aSHans de Goede case WPA_CIPHER_NONE: 839554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 840554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus =Ndis802_11EncryptionDisabled; 841554c0a3aSHans de Goede break; 842554c0a3aSHans de Goede case WPA_CIPHER_WEP40: 843554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; 844554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 845554c0a3aSHans de Goede break; 846554c0a3aSHans de Goede case WPA_CIPHER_TKIP: 847554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_; 848554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; 849554c0a3aSHans de Goede break; 850554c0a3aSHans de Goede case WPA_CIPHER_CCMP: 851554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _AES_; 852554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; 853554c0a3aSHans de Goede break; 854554c0a3aSHans de Goede case WPA_CIPHER_WEP104: 855554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_; 856554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 857554c0a3aSHans de Goede break; 858554c0a3aSHans de Goede } 859554c0a3aSHans de Goede 860554c0a3aSHans de Goede switch (pairwise_cipher) 861554c0a3aSHans de Goede { 862554c0a3aSHans de Goede case WPA_CIPHER_NONE: 863554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 864554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus =Ndis802_11EncryptionDisabled; 865554c0a3aSHans de Goede break; 866554c0a3aSHans de Goede case WPA_CIPHER_WEP40: 867554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 868554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 869554c0a3aSHans de Goede break; 870554c0a3aSHans de Goede case WPA_CIPHER_TKIP: 871554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_; 872554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; 873554c0a3aSHans de Goede break; 874554c0a3aSHans de Goede case WPA_CIPHER_CCMP: 875554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _AES_; 876554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; 877554c0a3aSHans de Goede break; 878554c0a3aSHans de Goede case WPA_CIPHER_WEP104: 879554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; 880554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 881554c0a3aSHans de Goede break; 882554c0a3aSHans de Goede } 883554c0a3aSHans de Goede 884554c0a3aSHans de Goede _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); 885554c0a3aSHans de Goede {/* set wps_ie */ 886554c0a3aSHans de Goede u16 cnt = 0; 887554c0a3aSHans de Goede u8 eid, wps_oui[4]={0x0, 0x50, 0xf2, 0x04}; 888554c0a3aSHans de Goede 889554c0a3aSHans de Goede while (cnt < ielen) 890554c0a3aSHans de Goede { 891554c0a3aSHans de Goede eid = buf[cnt]; 892554c0a3aSHans de Goede 893554c0a3aSHans de Goede if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) 894554c0a3aSHans de Goede { 895554c0a3aSHans de Goede DBG_871X("SET WPS_IE\n"); 896554c0a3aSHans de Goede 897554c0a3aSHans de Goede padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN; 898554c0a3aSHans de Goede 899554c0a3aSHans de Goede memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len); 900554c0a3aSHans de Goede 901554c0a3aSHans de Goede set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); 902554c0a3aSHans de Goede 903554c0a3aSHans de Goede cnt += buf[cnt+1]+2; 904554c0a3aSHans de Goede 905554c0a3aSHans de Goede break; 906554c0a3aSHans de Goede } else { 907554c0a3aSHans de Goede cnt += buf[cnt+1]+2; /* goto next */ 908554c0a3aSHans de Goede } 909554c0a3aSHans de Goede } 910554c0a3aSHans de Goede } 911554c0a3aSHans de Goede } 912554c0a3aSHans de Goede 913554c0a3aSHans de Goede /* TKIP and AES disallow multicast packets until installing group key */ 914554c0a3aSHans de Goede if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ 915554c0a3aSHans de Goede || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ 916554c0a3aSHans de Goede || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_) 917554c0a3aSHans de Goede /* WPS open need to enable multicast */ 918554c0a3aSHans de Goede /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */ 919554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr); 920554c0a3aSHans de Goede 921554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 922554c0a3aSHans de Goede ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n", 923554c0a3aSHans de Goede pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype)); 924554c0a3aSHans de Goede 925554c0a3aSHans de Goede exit: 926554c0a3aSHans de Goede 9277ad61a38SAishwarya Pant kfree(buf); 928554c0a3aSHans de Goede 929554c0a3aSHans de Goede return ret; 930554c0a3aSHans de Goede } 931554c0a3aSHans de Goede 932554c0a3aSHans de Goede static int rtw_wx_get_name(struct net_device *dev, 933554c0a3aSHans de Goede struct iw_request_info *info, 934554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 935554c0a3aSHans de Goede { 936554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 937554c0a3aSHans de Goede u32 ht_ielen = 0; 938554c0a3aSHans de Goede char *p; 939554c0a3aSHans de Goede u8 ht_cap =false, vht_cap =false; 940554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 941554c0a3aSHans de Goede struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 942554c0a3aSHans de Goede NDIS_802_11_RATES_EX* prates = NULL; 943554c0a3aSHans de Goede 944554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd)); 945554c0a3aSHans de Goede 946554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) { 947554c0a3aSHans de Goede /* parsing HT_CAP_IE */ 948554c0a3aSHans de Goede p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12); 949554c0a3aSHans de Goede if (p && ht_ielen>0) 950554c0a3aSHans de Goede { 951554c0a3aSHans de Goede ht_cap = true; 952554c0a3aSHans de Goede } 953554c0a3aSHans de Goede 954554c0a3aSHans de Goede prates = &pcur_bss->SupportedRates; 955554c0a3aSHans de Goede 956554c0a3aSHans de Goede if (rtw_is_cckratesonly_included((u8 *)prates) == true) 957554c0a3aSHans de Goede { 958554c0a3aSHans de Goede if (ht_cap == true) 959554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn"); 960554c0a3aSHans de Goede else 961554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b"); 962554c0a3aSHans de Goede } 963554c0a3aSHans de Goede else if ((rtw_is_cckrates_included((u8 *)prates)) == true) 964554c0a3aSHans de Goede { 965554c0a3aSHans de Goede if (ht_cap == true) 966554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn"); 967554c0a3aSHans de Goede else 968554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg"); 969554c0a3aSHans de Goede } 970554c0a3aSHans de Goede else 971554c0a3aSHans de Goede { 972554c0a3aSHans de Goede if (pcur_bss->Configuration.DSConfig > 14) 973554c0a3aSHans de Goede { 974554c0a3aSHans de Goede if (vht_cap == true) 975554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC"); 976554c0a3aSHans de Goede else if (ht_cap == true) 977554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an"); 978554c0a3aSHans de Goede else 979554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a"); 980554c0a3aSHans de Goede } 981554c0a3aSHans de Goede else 982554c0a3aSHans de Goede { 983554c0a3aSHans de Goede if (ht_cap == true) 984554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn"); 985554c0a3aSHans de Goede else 986554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); 987554c0a3aSHans de Goede } 988554c0a3aSHans de Goede } 989554c0a3aSHans de Goede } 990554c0a3aSHans de Goede else 991554c0a3aSHans de Goede { 992554c0a3aSHans de Goede /* prates = &padapter->registrypriv.dev_network.SupportedRates; */ 993554c0a3aSHans de Goede /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */ 994554c0a3aSHans de Goede snprintf(wrqu->name, IFNAMSIZ, "unassociated"); 995554c0a3aSHans de Goede } 996554c0a3aSHans de Goede return 0; 997554c0a3aSHans de Goede } 998554c0a3aSHans de Goede 999554c0a3aSHans de Goede static int rtw_wx_set_freq(struct net_device *dev, 1000554c0a3aSHans de Goede struct iw_request_info *info, 1001554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1002554c0a3aSHans de Goede { 1003554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n")); 1004554c0a3aSHans de Goede 1005554c0a3aSHans de Goede return 0; 1006554c0a3aSHans de Goede } 1007554c0a3aSHans de Goede 1008554c0a3aSHans de Goede static int rtw_wx_get_freq(struct net_device *dev, 1009554c0a3aSHans de Goede struct iw_request_info *info, 1010554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1011554c0a3aSHans de Goede { 1012554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1013554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1014554c0a3aSHans de Goede struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 1015554c0a3aSHans de Goede 1016554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 1017554c0a3aSHans de Goede { 1018554c0a3aSHans de Goede /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */ 1019554c0a3aSHans de Goede wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000; 1020554c0a3aSHans de Goede wrqu->freq.e = 1; 1021554c0a3aSHans de Goede wrqu->freq.i = pcur_bss->Configuration.DSConfig; 1022554c0a3aSHans de Goede 1023554c0a3aSHans de Goede } 1024554c0a3aSHans de Goede else { 1025554c0a3aSHans de Goede wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000; 1026554c0a3aSHans de Goede wrqu->freq.e = 1; 1027554c0a3aSHans de Goede wrqu->freq.i = padapter->mlmeextpriv.cur_channel; 1028554c0a3aSHans de Goede } 1029554c0a3aSHans de Goede 1030554c0a3aSHans de Goede return 0; 1031554c0a3aSHans de Goede } 1032554c0a3aSHans de Goede 1033554c0a3aSHans de Goede static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a, 1034554c0a3aSHans de Goede union iwreq_data *wrqu, char *b) 1035554c0a3aSHans de Goede { 1036554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1037554c0a3aSHans de Goede enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ; 1038554c0a3aSHans de Goede int ret = 0; 1039554c0a3aSHans de Goede 1040554c0a3aSHans de Goede if (_FAIL == rtw_pwr_wakeup(padapter)) { 1041554c0a3aSHans de Goede ret = -EPERM; 1042554c0a3aSHans de Goede goto exit; 1043554c0a3aSHans de Goede } 1044554c0a3aSHans de Goede 1045554c0a3aSHans de Goede if (padapter->hw_init_completed ==false) { 1046554c0a3aSHans de Goede ret = -EPERM; 1047554c0a3aSHans de Goede goto exit; 1048554c0a3aSHans de Goede } 1049554c0a3aSHans de Goede 1050554c0a3aSHans de Goede switch (wrqu->mode) 1051554c0a3aSHans de Goede { 1052554c0a3aSHans de Goede case IW_MODE_AUTO: 1053554c0a3aSHans de Goede networkType = Ndis802_11AutoUnknown; 1054554c0a3aSHans de Goede DBG_871X("set_mode = IW_MODE_AUTO\n"); 1055554c0a3aSHans de Goede break; 1056554c0a3aSHans de Goede case IW_MODE_ADHOC: 1057554c0a3aSHans de Goede networkType = Ndis802_11IBSS; 1058554c0a3aSHans de Goede DBG_871X("set_mode = IW_MODE_ADHOC\n"); 1059554c0a3aSHans de Goede break; 1060554c0a3aSHans de Goede case IW_MODE_MASTER: 1061554c0a3aSHans de Goede networkType = Ndis802_11APMode; 1062554c0a3aSHans de Goede DBG_871X("set_mode = IW_MODE_MASTER\n"); 1063554c0a3aSHans de Goede /* rtw_setopmode_cmd(padapter, networkType, true); */ 1064554c0a3aSHans de Goede break; 1065554c0a3aSHans de Goede case IW_MODE_INFRA: 1066554c0a3aSHans de Goede networkType = Ndis802_11Infrastructure; 1067554c0a3aSHans de Goede DBG_871X("set_mode = IW_MODE_INFRA\n"); 1068554c0a3aSHans de Goede break; 1069554c0a3aSHans de Goede 1070554c0a3aSHans de Goede default : 1071554c0a3aSHans de Goede ret = -EINVAL;; 1072554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported \n", iw_operation_mode[wrqu->mode])); 1073554c0a3aSHans de Goede goto exit; 1074554c0a3aSHans de Goede } 1075554c0a3aSHans de Goede 1076554c0a3aSHans de Goede /* 1077554c0a3aSHans de Goede if (Ndis802_11APMode == networkType) 1078554c0a3aSHans de Goede { 1079554c0a3aSHans de Goede rtw_setopmode_cmd(padapter, networkType, true); 1080554c0a3aSHans de Goede } 1081554c0a3aSHans de Goede else 1082554c0a3aSHans de Goede { 1083554c0a3aSHans de Goede rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown, true); 1084554c0a3aSHans de Goede } 1085554c0a3aSHans de Goede */ 1086554c0a3aSHans de Goede 1087554c0a3aSHans de Goede if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==false) { 1088554c0a3aSHans de Goede 1089554c0a3aSHans de Goede ret = -EPERM; 1090554c0a3aSHans de Goede goto exit; 1091554c0a3aSHans de Goede 1092554c0a3aSHans de Goede } 1093554c0a3aSHans de Goede 1094554c0a3aSHans de Goede rtw_setopmode_cmd(padapter, networkType, true); 1095554c0a3aSHans de Goede 1096554c0a3aSHans de Goede exit: 1097554c0a3aSHans de Goede return ret; 1098554c0a3aSHans de Goede } 1099554c0a3aSHans de Goede 1100554c0a3aSHans de Goede static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a, 1101554c0a3aSHans de Goede union iwreq_data *wrqu, char *b) 1102554c0a3aSHans de Goede { 1103554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1104554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1105554c0a3aSHans de Goede 1106554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n")); 1107554c0a3aSHans de Goede 1108554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) 1109554c0a3aSHans de Goede { 1110554c0a3aSHans de Goede wrqu->mode = IW_MODE_INFRA; 1111554c0a3aSHans de Goede } 1112554c0a3aSHans de Goede else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) || 1113554c0a3aSHans de Goede (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) 1114554c0a3aSHans de Goede 1115554c0a3aSHans de Goede { 1116554c0a3aSHans de Goede wrqu->mode = IW_MODE_ADHOC; 1117554c0a3aSHans de Goede } 1118554c0a3aSHans de Goede else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) 1119554c0a3aSHans de Goede { 1120554c0a3aSHans de Goede wrqu->mode = IW_MODE_MASTER; 1121554c0a3aSHans de Goede } 1122554c0a3aSHans de Goede else 1123554c0a3aSHans de Goede { 1124554c0a3aSHans de Goede wrqu->mode = IW_MODE_AUTO; 1125554c0a3aSHans de Goede } 1126554c0a3aSHans de Goede return 0; 1127554c0a3aSHans de Goede } 1128554c0a3aSHans de Goede 1129554c0a3aSHans de Goede 1130554c0a3aSHans de Goede static int rtw_wx_set_pmkid(struct net_device *dev, 1131554c0a3aSHans de Goede struct iw_request_info *a, 1132554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1133554c0a3aSHans de Goede { 1134554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1135554c0a3aSHans de Goede u8 j, blInserted = false; 1136554c0a3aSHans de Goede int intReturn = false; 1137554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 1138554c0a3aSHans de Goede struct iw_pmksa* pPMK = (struct iw_pmksa*) extra; 1139554c0a3aSHans de Goede u8 strZeroMacAddress[ ETH_ALEN ] = { 0x00 }; 1140554c0a3aSHans de Goede u8 strIssueBssid[ ETH_ALEN ] = { 0x00 }; 1141554c0a3aSHans de Goede 1142554c0a3aSHans de Goede /* 1143554c0a3aSHans de Goede There are the BSSID information in the bssid.sa_data array. 1144554c0a3aSHans de Goede If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information. 1145554c0a3aSHans de Goede If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver. 1146554c0a3aSHans de Goede If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver. 1147554c0a3aSHans de Goede */ 1148554c0a3aSHans de Goede 1149554c0a3aSHans de Goede memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN); 1150554c0a3aSHans de Goede if (pPMK->cmd == IW_PMKSA_ADD) 1151554c0a3aSHans de Goede { 1152554c0a3aSHans de Goede DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n"); 1153554c0a3aSHans de Goede if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN)) 1154554c0a3aSHans de Goede { 1155554c0a3aSHans de Goede return(intReturn); 1156554c0a3aSHans de Goede } 1157554c0a3aSHans de Goede else 1158554c0a3aSHans de Goede { 1159554c0a3aSHans de Goede intReturn = true; 1160554c0a3aSHans de Goede } 1161554c0a3aSHans de Goede blInserted = false; 1162554c0a3aSHans de Goede 1163554c0a3aSHans de Goede /* overwrite PMKID */ 1164554c0a3aSHans de Goede for (j = 0 ; j<NUM_PMKID_CACHE; j++) 1165554c0a3aSHans de Goede { 1166554c0a3aSHans de Goede if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) 1167554c0a3aSHans de Goede { /* BSSID is matched, the same AP => rewrite with new PMKID. */ 1168554c0a3aSHans de Goede 1169554c0a3aSHans de Goede DBG_871X("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n"); 1170554c0a3aSHans de Goede 1171554c0a3aSHans de Goede memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); 1172554c0a3aSHans de Goede psecuritypriv->PMKIDList[ j ].bUsed = true; 1173554c0a3aSHans de Goede psecuritypriv->PMKIDIndex = j+1; 1174554c0a3aSHans de Goede blInserted = true; 1175554c0a3aSHans de Goede break; 1176554c0a3aSHans de Goede } 1177554c0a3aSHans de Goede } 1178554c0a3aSHans de Goede 1179554c0a3aSHans de Goede if (!blInserted) 1180554c0a3aSHans de Goede { 1181554c0a3aSHans de Goede /* Find a new entry */ 1182554c0a3aSHans de Goede DBG_871X("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n", 1183554c0a3aSHans de Goede psecuritypriv->PMKIDIndex); 1184554c0a3aSHans de Goede 1185554c0a3aSHans de Goede memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN); 1186554c0a3aSHans de Goede memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN); 1187554c0a3aSHans de Goede 1188554c0a3aSHans de Goede psecuritypriv->PMKIDList[ psecuritypriv->PMKIDIndex ].bUsed = true; 1189554c0a3aSHans de Goede psecuritypriv->PMKIDIndex++ ; 1190554c0a3aSHans de Goede if (psecuritypriv->PMKIDIndex == 16) 1191554c0a3aSHans de Goede { 1192554c0a3aSHans de Goede psecuritypriv->PMKIDIndex = 0; 1193554c0a3aSHans de Goede } 1194554c0a3aSHans de Goede } 1195554c0a3aSHans de Goede } 1196554c0a3aSHans de Goede else if (pPMK->cmd == IW_PMKSA_REMOVE) 1197554c0a3aSHans de Goede { 1198554c0a3aSHans de Goede DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n"); 1199554c0a3aSHans de Goede intReturn = true; 1200554c0a3aSHans de Goede for (j = 0 ; j<NUM_PMKID_CACHE; j++) 1201554c0a3aSHans de Goede { 1202554c0a3aSHans de Goede if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) 1203554c0a3aSHans de Goede { /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */ 1204554c0a3aSHans de Goede memset(psecuritypriv->PMKIDList[ j ].Bssid, 0x00, ETH_ALEN); 1205554c0a3aSHans de Goede psecuritypriv->PMKIDList[ j ].bUsed = false; 1206554c0a3aSHans de Goede break; 1207554c0a3aSHans de Goede } 1208554c0a3aSHans de Goede } 1209554c0a3aSHans de Goede } 1210554c0a3aSHans de Goede else if (pPMK->cmd == IW_PMKSA_FLUSH) 1211554c0a3aSHans de Goede { 1212554c0a3aSHans de Goede DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n"); 1213554c0a3aSHans de Goede memset(&psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE); 1214554c0a3aSHans de Goede psecuritypriv->PMKIDIndex = 0; 1215554c0a3aSHans de Goede intReturn = true; 1216554c0a3aSHans de Goede } 1217554c0a3aSHans de Goede return intReturn; 1218554c0a3aSHans de Goede } 1219554c0a3aSHans de Goede 1220554c0a3aSHans de Goede static int rtw_wx_get_sens(struct net_device *dev, 1221554c0a3aSHans de Goede struct iw_request_info *info, 1222554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1223554c0a3aSHans de Goede { 1224554c0a3aSHans de Goede { 1225554c0a3aSHans de Goede wrqu->sens.value = 0; 1226554c0a3aSHans de Goede wrqu->sens.fixed = 0; /* no auto select */ 1227554c0a3aSHans de Goede wrqu->sens.disabled = 1; 1228554c0a3aSHans de Goede } 1229554c0a3aSHans de Goede return 0; 1230554c0a3aSHans de Goede } 1231554c0a3aSHans de Goede 1232554c0a3aSHans de Goede static int rtw_wx_get_range(struct net_device *dev, 1233554c0a3aSHans de Goede struct iw_request_info *info, 1234554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1235554c0a3aSHans de Goede { 1236554c0a3aSHans de Goede struct iw_range *range = (struct iw_range *)extra; 1237554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1238554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1239554c0a3aSHans de Goede 1240554c0a3aSHans de Goede u16 val; 1241554c0a3aSHans de Goede int i; 1242554c0a3aSHans de Goede 1243554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd)); 1244554c0a3aSHans de Goede 1245554c0a3aSHans de Goede wrqu->data.length = sizeof(*range); 1246554c0a3aSHans de Goede memset(range, 0, sizeof(*range)); 1247554c0a3aSHans de Goede 1248554c0a3aSHans de Goede /* Let's try to keep this struct in the same order as in 1249554c0a3aSHans de Goede * linux/include/wireless.h 1250554c0a3aSHans de Goede */ 1251554c0a3aSHans de Goede 1252554c0a3aSHans de Goede /* TODO: See what values we can set, and remove the ones we can't 1253554c0a3aSHans de Goede * set, or fill them with some default data. 1254554c0a3aSHans de Goede */ 1255554c0a3aSHans de Goede 1256554c0a3aSHans de Goede /* ~5 Mb/s real (802.11b) */ 1257554c0a3aSHans de Goede range->throughput = 5 * 1000 * 1000; 1258554c0a3aSHans de Goede 1259554c0a3aSHans de Goede /* signal level threshold range */ 1260554c0a3aSHans de Goede 1261554c0a3aSHans de Goede /* percent values between 0 and 100. */ 1262554c0a3aSHans de Goede range->max_qual.qual = 100; 1263554c0a3aSHans de Goede range->max_qual.level = 100; 1264554c0a3aSHans de Goede range->max_qual.noise = 100; 1265554c0a3aSHans de Goede range->max_qual.updated = 7; /* Updated all three */ 1266554c0a3aSHans de Goede 1267554c0a3aSHans de Goede 1268554c0a3aSHans de Goede range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ 1269554c0a3aSHans de Goede /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ 1270554c0a3aSHans de Goede range->avg_qual.level = 256 - 78; 1271554c0a3aSHans de Goede range->avg_qual.noise = 0; 1272554c0a3aSHans de Goede range->avg_qual.updated = 7; /* Updated all three */ 1273554c0a3aSHans de Goede 1274554c0a3aSHans de Goede range->num_bitrates = RATE_COUNT; 1275554c0a3aSHans de Goede 1276554c0a3aSHans de Goede for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) { 1277554c0a3aSHans de Goede range->bitrate[i] = rtw_rates[i]; 1278554c0a3aSHans de Goede } 1279554c0a3aSHans de Goede 1280554c0a3aSHans de Goede range->min_frag = MIN_FRAG_THRESHOLD; 1281554c0a3aSHans de Goede range->max_frag = MAX_FRAG_THRESHOLD; 1282554c0a3aSHans de Goede 1283554c0a3aSHans de Goede range->pm_capa = 0; 1284554c0a3aSHans de Goede 1285554c0a3aSHans de Goede range->we_version_compiled = WIRELESS_EXT; 1286554c0a3aSHans de Goede range->we_version_source = 16; 1287554c0a3aSHans de Goede 1288554c0a3aSHans de Goede for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) { 1289554c0a3aSHans de Goede 1290554c0a3aSHans de Goede /* Include only legal frequencies for some countries */ 1291554c0a3aSHans de Goede if (pmlmeext->channel_set[i].ChannelNum != 0) 1292554c0a3aSHans de Goede { 1293554c0a3aSHans de Goede range->freq[val].i = pmlmeext->channel_set[i].ChannelNum; 1294554c0a3aSHans de Goede range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000; 1295554c0a3aSHans de Goede range->freq[val].e = 1; 1296554c0a3aSHans de Goede val++; 1297554c0a3aSHans de Goede } 1298554c0a3aSHans de Goede 1299554c0a3aSHans de Goede if (val == IW_MAX_FREQUENCIES) 1300554c0a3aSHans de Goede break; 1301554c0a3aSHans de Goede } 1302554c0a3aSHans de Goede 1303554c0a3aSHans de Goede range->num_channels = val; 1304554c0a3aSHans de Goede range->num_frequency = val; 1305554c0a3aSHans de Goede 1306554c0a3aSHans de Goede /* Commented by Albert 2009/10/13 */ 1307554c0a3aSHans de Goede /* The following code will proivde the security capability to network manager. */ 1308554c0a3aSHans de Goede /* If the driver doesn't provide this capability to network manager, */ 1309554c0a3aSHans de Goede /* the WPA/WPA2 routers can't be choosen in the network manager. */ 1310554c0a3aSHans de Goede 1311554c0a3aSHans de Goede /* 1312554c0a3aSHans de Goede #define IW_SCAN_CAPA_NONE 0x00 1313554c0a3aSHans de Goede #define IW_SCAN_CAPA_ESSID 0x01 1314554c0a3aSHans de Goede #define IW_SCAN_CAPA_BSSID 0x02 1315554c0a3aSHans de Goede #define IW_SCAN_CAPA_CHANNEL 0x04 1316554c0a3aSHans de Goede #define IW_SCAN_CAPA_MODE 0x08 1317554c0a3aSHans de Goede #define IW_SCAN_CAPA_RATE 0x10 1318554c0a3aSHans de Goede #define IW_SCAN_CAPA_TYPE 0x20 1319554c0a3aSHans de Goede #define IW_SCAN_CAPA_TIME 0x40 1320554c0a3aSHans de Goede */ 1321554c0a3aSHans de Goede 1322554c0a3aSHans de Goede range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| 1323554c0a3aSHans de Goede IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; 1324554c0a3aSHans de Goede 1325554c0a3aSHans de Goede range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |IW_SCAN_CAPA_BSSID| 1326554c0a3aSHans de Goede IW_SCAN_CAPA_CHANNEL|IW_SCAN_CAPA_MODE|IW_SCAN_CAPA_RATE; 1327554c0a3aSHans de Goede 1328554c0a3aSHans de Goede return 0; 1329554c0a3aSHans de Goede } 1330554c0a3aSHans de Goede 1331554c0a3aSHans de Goede /* set bssid flow */ 1332554c0a3aSHans de Goede /* s1. rtw_set_802_11_infrastructure_mode() */ 1333554c0a3aSHans de Goede /* s2. rtw_set_802_11_authentication_mode() */ 1334554c0a3aSHans de Goede /* s3. set_802_11_encryption_mode() */ 1335554c0a3aSHans de Goede /* s4. rtw_set_802_11_bssid() */ 1336554c0a3aSHans de Goede static int rtw_wx_set_wap(struct net_device *dev, 1337554c0a3aSHans de Goede struct iw_request_info *info, 1338554c0a3aSHans de Goede union iwreq_data *awrq, 1339554c0a3aSHans de Goede char *extra) 1340554c0a3aSHans de Goede { 1341554c0a3aSHans de Goede uint ret = 0; 1342554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1343554c0a3aSHans de Goede struct sockaddr *temp = (struct sockaddr *)awrq; 1344554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1345554c0a3aSHans de Goede struct list_head *phead; 1346554c0a3aSHans de Goede u8 *dst_bssid, *src_bssid; 1347554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 1348554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 1349554c0a3aSHans de Goede enum NDIS_802_11_AUTHENTICATION_MODE authmode; 1350554c0a3aSHans de Goede 1351554c0a3aSHans de Goede rtw_ps_deny(padapter, PS_DENY_JOIN); 1352554c0a3aSHans de Goede if (_FAIL == rtw_pwr_wakeup(padapter)) 1353554c0a3aSHans de Goede { 1354554c0a3aSHans de Goede ret = -1; 1355554c0a3aSHans de Goede goto exit; 1356554c0a3aSHans de Goede } 1357554c0a3aSHans de Goede 1358554c0a3aSHans de Goede if (!padapter->bup) { 1359554c0a3aSHans de Goede ret = -1; 1360554c0a3aSHans de Goede goto exit; 1361554c0a3aSHans de Goede } 1362554c0a3aSHans de Goede 1363554c0a3aSHans de Goede 1364554c0a3aSHans de Goede if (temp->sa_family != ARPHRD_ETHER) { 1365554c0a3aSHans de Goede ret = -EINVAL; 1366554c0a3aSHans de Goede goto exit; 1367554c0a3aSHans de Goede } 1368554c0a3aSHans de Goede 1369554c0a3aSHans de Goede authmode = padapter->securitypriv.ndisauthtype; 1370554c0a3aSHans de Goede spin_lock_bh(&queue->lock); 1371554c0a3aSHans de Goede phead = get_list_head(queue); 1372554c0a3aSHans de Goede pmlmepriv->pscanned = get_next(phead); 1373554c0a3aSHans de Goede 1374554c0a3aSHans de Goede while (1) { 1375554c0a3aSHans de Goede if (phead == pmlmepriv->pscanned) 1376554c0a3aSHans de Goede break; 1377554c0a3aSHans de Goede 1378554c0a3aSHans de Goede pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list); 1379554c0a3aSHans de Goede 1380554c0a3aSHans de Goede pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); 1381554c0a3aSHans de Goede 1382554c0a3aSHans de Goede dst_bssid = pnetwork->network.MacAddress; 1383554c0a3aSHans de Goede 1384554c0a3aSHans de Goede src_bssid = temp->sa_data; 1385554c0a3aSHans de Goede 1386554c0a3aSHans de Goede if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) 1387554c0a3aSHans de Goede { 1388554c0a3aSHans de Goede if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) 1389554c0a3aSHans de Goede { 1390554c0a3aSHans de Goede ret = -1; 1391554c0a3aSHans de Goede spin_unlock_bh(&queue->lock); 1392554c0a3aSHans de Goede goto exit; 1393554c0a3aSHans de Goede } 1394554c0a3aSHans de Goede 1395554c0a3aSHans de Goede break; 1396554c0a3aSHans de Goede } 1397554c0a3aSHans de Goede 1398554c0a3aSHans de Goede } 1399554c0a3aSHans de Goede spin_unlock_bh(&queue->lock); 1400554c0a3aSHans de Goede 1401554c0a3aSHans de Goede rtw_set_802_11_authentication_mode(padapter, authmode); 1402554c0a3aSHans de Goede /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */ 1403554c0a3aSHans de Goede if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) { 1404554c0a3aSHans de Goede ret = -1; 1405554c0a3aSHans de Goede goto exit; 1406554c0a3aSHans de Goede } 1407554c0a3aSHans de Goede 1408554c0a3aSHans de Goede exit: 1409554c0a3aSHans de Goede 1410554c0a3aSHans de Goede rtw_ps_deny_cancel(padapter, PS_DENY_JOIN); 1411554c0a3aSHans de Goede 1412554c0a3aSHans de Goede return ret; 1413554c0a3aSHans de Goede } 1414554c0a3aSHans de Goede 1415554c0a3aSHans de Goede static int rtw_wx_get_wap(struct net_device *dev, 1416554c0a3aSHans de Goede struct iw_request_info *info, 1417554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1418554c0a3aSHans de Goede { 1419554c0a3aSHans de Goede 1420554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1421554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1422554c0a3aSHans de Goede struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 1423554c0a3aSHans de Goede 1424554c0a3aSHans de Goede wrqu->ap_addr.sa_family = ARPHRD_ETHER; 1425554c0a3aSHans de Goede 1426554c0a3aSHans de Goede memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); 1427554c0a3aSHans de Goede 1428554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n")); 1429554c0a3aSHans de Goede 1430554c0a3aSHans de Goede if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) || 1431554c0a3aSHans de Goede ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) || 1432554c0a3aSHans de Goede ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true)) 1433554c0a3aSHans de Goede { 1434554c0a3aSHans de Goede 1435554c0a3aSHans de Goede memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN); 1436554c0a3aSHans de Goede } 1437554c0a3aSHans de Goede else 1438554c0a3aSHans de Goede { 1439554c0a3aSHans de Goede memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); 1440554c0a3aSHans de Goede } 1441554c0a3aSHans de Goede 1442554c0a3aSHans de Goede return 0; 1443554c0a3aSHans de Goede } 1444554c0a3aSHans de Goede 1445554c0a3aSHans de Goede static int rtw_wx_set_mlme(struct net_device *dev, 1446554c0a3aSHans de Goede struct iw_request_info *info, 1447554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1448554c0a3aSHans de Goede { 1449554c0a3aSHans de Goede int ret = 0; 1450554c0a3aSHans de Goede u16 reason; 1451554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1452554c0a3aSHans de Goede struct iw_mlme *mlme = (struct iw_mlme *) extra; 1453554c0a3aSHans de Goede 1454554c0a3aSHans de Goede 1455554c0a3aSHans de Goede if (mlme == NULL) 1456554c0a3aSHans de Goede return -1; 1457554c0a3aSHans de Goede 1458554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1459554c0a3aSHans de Goede 1460554c0a3aSHans de Goede reason = mlme->reason_code; 1461554c0a3aSHans de Goede 1462554c0a3aSHans de Goede DBG_871X("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason); 1463554c0a3aSHans de Goede 1464554c0a3aSHans de Goede switch (mlme->cmd) 1465554c0a3aSHans de Goede { 1466554c0a3aSHans de Goede case IW_MLME_DEAUTH: 1467554c0a3aSHans de Goede if (!rtw_set_802_11_disassociate(padapter)) 1468554c0a3aSHans de Goede ret = -1; 1469554c0a3aSHans de Goede break; 1470554c0a3aSHans de Goede case IW_MLME_DISASSOC: 1471554c0a3aSHans de Goede if (!rtw_set_802_11_disassociate(padapter)) 1472554c0a3aSHans de Goede ret = -1; 1473554c0a3aSHans de Goede break; 1474554c0a3aSHans de Goede default: 1475554c0a3aSHans de Goede return -EOPNOTSUPP; 1476554c0a3aSHans de Goede } 1477554c0a3aSHans de Goede 1478554c0a3aSHans de Goede return ret; 1479554c0a3aSHans de Goede } 1480554c0a3aSHans de Goede 1481554c0a3aSHans de Goede static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, 1482554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1483554c0a3aSHans de Goede { 1484554c0a3aSHans de Goede u8 _status = false; 1485554c0a3aSHans de Goede int ret = 0; 1486554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1487554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1488554c0a3aSHans de Goede struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT]; 1489554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n")); 1490554c0a3aSHans de Goede 1491554c0a3aSHans de Goede #ifdef DBG_IOCTL 1492554c0a3aSHans de Goede DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__); 1493554c0a3aSHans de Goede #endif 1494554c0a3aSHans de Goede 1495554c0a3aSHans de Goede rtw_ps_deny(padapter, PS_DENY_SCAN); 1496554c0a3aSHans de Goede if (_FAIL == rtw_pwr_wakeup(padapter)) 1497554c0a3aSHans de Goede { 1498554c0a3aSHans de Goede ret = -1; 1499554c0a3aSHans de Goede goto exit; 1500554c0a3aSHans de Goede } 1501554c0a3aSHans de Goede 1502554c0a3aSHans de Goede if (padapter->bDriverStopped) { 1503554c0a3aSHans de Goede DBG_871X("bDriverStopped =%d\n", padapter->bDriverStopped); 1504554c0a3aSHans de Goede ret = -1; 1505554c0a3aSHans de Goede goto exit; 1506554c0a3aSHans de Goede } 1507554c0a3aSHans de Goede 1508554c0a3aSHans de Goede if (!padapter->bup) { 1509554c0a3aSHans de Goede ret = -1; 1510554c0a3aSHans de Goede goto exit; 1511554c0a3aSHans de Goede } 1512554c0a3aSHans de Goede 1513554c0a3aSHans de Goede if (padapter->hw_init_completed ==false) { 1514554c0a3aSHans de Goede ret = -1; 1515554c0a3aSHans de Goede goto exit; 1516554c0a3aSHans de Goede } 1517554c0a3aSHans de Goede 1518554c0a3aSHans de Goede /* When Busy Traffic, driver do not site survey. So driver return success. */ 1519554c0a3aSHans de Goede /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */ 1520554c0a3aSHans de Goede /* modify by thomas 2011-02-22. */ 1521554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) 1522554c0a3aSHans de Goede { 1523554c0a3aSHans de Goede indicate_wx_scan_complete_event(padapter); 1524554c0a3aSHans de Goede goto exit; 1525554c0a3aSHans de Goede } 1526554c0a3aSHans de Goede 1527554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) 1528554c0a3aSHans de Goede { 1529554c0a3aSHans de Goede indicate_wx_scan_complete_event(padapter); 1530554c0a3aSHans de Goede goto exit; 1531554c0a3aSHans de Goede } 1532554c0a3aSHans de Goede 1533554c0a3aSHans de Goede memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT); 1534554c0a3aSHans de Goede 1535554c0a3aSHans de Goede if (wrqu->data.length == sizeof(struct iw_scan_req)) 1536554c0a3aSHans de Goede { 1537554c0a3aSHans de Goede struct iw_scan_req *req = (struct iw_scan_req *)extra; 1538554c0a3aSHans de Goede 1539554c0a3aSHans de Goede if (wrqu->data.flags & IW_SCAN_THIS_ESSID) 1540554c0a3aSHans de Goede { 1541554c0a3aSHans de Goede int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE); 1542554c0a3aSHans de Goede 1543554c0a3aSHans de Goede memcpy(ssid[0].Ssid, req->essid, len); 1544554c0a3aSHans de Goede ssid[0].SsidLength = len; 1545554c0a3aSHans de Goede 1546554c0a3aSHans de Goede DBG_871X("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len); 1547554c0a3aSHans de Goede 1548554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 1549554c0a3aSHans de Goede 1550554c0a3aSHans de Goede _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0); 1551554c0a3aSHans de Goede 1552554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 1553554c0a3aSHans de Goede 1554554c0a3aSHans de Goede } 1555554c0a3aSHans de Goede else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) 1556554c0a3aSHans de Goede { 1557554c0a3aSHans de Goede DBG_871X("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n"); 1558554c0a3aSHans de Goede } 1559554c0a3aSHans de Goede 1560554c0a3aSHans de Goede } 1561554c0a3aSHans de Goede else if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE 1562554c0a3aSHans de Goede && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) 1563554c0a3aSHans de Goede ) 1564554c0a3aSHans de Goede { 1565554c0a3aSHans de Goede int len = wrqu->data.length -WEXT_CSCAN_HEADER_SIZE; 1566554c0a3aSHans de Goede char *pos = extra+WEXT_CSCAN_HEADER_SIZE; 1567554c0a3aSHans de Goede char section; 1568554c0a3aSHans de Goede char sec_len; 1569554c0a3aSHans de Goede int ssid_index = 0; 1570554c0a3aSHans de Goede 1571554c0a3aSHans de Goede /* DBG_871X("%s COMBO_SCAN header is recognized\n", __func__); */ 1572554c0a3aSHans de Goede 1573554c0a3aSHans de Goede while (len >= 1) { 1574554c0a3aSHans de Goede section = *(pos++); len-= 1; 1575554c0a3aSHans de Goede 1576554c0a3aSHans de Goede switch (section) { 1577554c0a3aSHans de Goede case WEXT_CSCAN_SSID_SECTION: 1578554c0a3aSHans de Goede /* DBG_871X("WEXT_CSCAN_SSID_SECTION\n"); */ 1579554c0a3aSHans de Goede if (len < 1) { 1580554c0a3aSHans de Goede len = 0; 1581554c0a3aSHans de Goede break; 1582554c0a3aSHans de Goede } 1583554c0a3aSHans de Goede 1584554c0a3aSHans de Goede sec_len = *(pos++); len-= 1; 1585554c0a3aSHans de Goede 1586554c0a3aSHans de Goede if (sec_len>0 && sec_len<=len) { 1587554c0a3aSHans de Goede ssid[ssid_index].SsidLength = sec_len; 1588554c0a3aSHans de Goede memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength); 1589554c0a3aSHans de Goede /* DBG_871X("%s COMBO_SCAN with specific ssid:%s, %d\n", __func__ */ 1590554c0a3aSHans de Goede /* , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength); */ 1591554c0a3aSHans de Goede ssid_index++; 1592554c0a3aSHans de Goede } 1593554c0a3aSHans de Goede 1594554c0a3aSHans de Goede pos+=sec_len; len-=sec_len; 1595554c0a3aSHans de Goede break; 1596554c0a3aSHans de Goede 1597554c0a3aSHans de Goede 1598554c0a3aSHans de Goede case WEXT_CSCAN_CHANNEL_SECTION: 1599554c0a3aSHans de Goede /* DBG_871X("WEXT_CSCAN_CHANNEL_SECTION\n"); */ 1600554c0a3aSHans de Goede pos+= 1; len-= 1; 1601554c0a3aSHans de Goede break; 1602554c0a3aSHans de Goede case WEXT_CSCAN_ACTV_DWELL_SECTION: 1603554c0a3aSHans de Goede /* DBG_871X("WEXT_CSCAN_ACTV_DWELL_SECTION\n"); */ 1604554c0a3aSHans de Goede pos+=2; len-=2; 1605554c0a3aSHans de Goede break; 1606554c0a3aSHans de Goede case WEXT_CSCAN_PASV_DWELL_SECTION: 1607554c0a3aSHans de Goede /* DBG_871X("WEXT_CSCAN_PASV_DWELL_SECTION\n"); */ 1608554c0a3aSHans de Goede pos+=2; len-=2; 1609554c0a3aSHans de Goede break; 1610554c0a3aSHans de Goede case WEXT_CSCAN_HOME_DWELL_SECTION: 1611554c0a3aSHans de Goede /* DBG_871X("WEXT_CSCAN_HOME_DWELL_SECTION\n"); */ 1612554c0a3aSHans de Goede pos+=2; len-=2; 1613554c0a3aSHans de Goede break; 1614554c0a3aSHans de Goede case WEXT_CSCAN_TYPE_SECTION: 1615554c0a3aSHans de Goede /* DBG_871X("WEXT_CSCAN_TYPE_SECTION\n"); */ 1616554c0a3aSHans de Goede pos+= 1; len-= 1; 1617554c0a3aSHans de Goede break; 1618554c0a3aSHans de Goede default: 1619554c0a3aSHans de Goede /* DBG_871X("Unknown CSCAN section %c\n", section); */ 1620554c0a3aSHans de Goede len = 0; /* stop parsing */ 1621554c0a3aSHans de Goede } 1622554c0a3aSHans de Goede /* DBG_871X("len:%d\n", len); */ 1623554c0a3aSHans de Goede 1624554c0a3aSHans de Goede } 1625554c0a3aSHans de Goede 1626554c0a3aSHans de Goede /* jeff: it has still some scan paramater to parse, we only do this now... */ 1627554c0a3aSHans de Goede _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT); 1628554c0a3aSHans de Goede 1629554c0a3aSHans de Goede } else 1630554c0a3aSHans de Goede 1631554c0a3aSHans de Goede { 1632554c0a3aSHans de Goede _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0); 1633554c0a3aSHans de Goede } 1634554c0a3aSHans de Goede 1635554c0a3aSHans de Goede if (_status == false) 1636554c0a3aSHans de Goede ret = -1; 1637554c0a3aSHans de Goede 1638554c0a3aSHans de Goede exit: 1639554c0a3aSHans de Goede 1640554c0a3aSHans de Goede rtw_ps_deny_cancel(padapter, PS_DENY_SCAN); 1641554c0a3aSHans de Goede 1642554c0a3aSHans de Goede #ifdef DBG_IOCTL 1643554c0a3aSHans de Goede DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret); 1644554c0a3aSHans de Goede #endif 1645554c0a3aSHans de Goede 1646554c0a3aSHans de Goede return ret; 1647554c0a3aSHans de Goede } 1648554c0a3aSHans de Goede 1649554c0a3aSHans de Goede static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 1650554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1651554c0a3aSHans de Goede { 1652554c0a3aSHans de Goede struct list_head *plist, *phead; 1653554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1654554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1655554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 1656554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 1657554c0a3aSHans de Goede char *ev = extra; 1658554c0a3aSHans de Goede char *stop = ev + wrqu->data.length; 1659554c0a3aSHans de Goede u32 ret = 0; 1660554c0a3aSHans de Goede sint wait_status; 1661554c0a3aSHans de Goede 1662554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n")); 1663554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n")); 1664554c0a3aSHans de Goede 1665554c0a3aSHans de Goede #ifdef DBG_IOCTL 1666554c0a3aSHans de Goede DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__); 1667554c0a3aSHans de Goede #endif 1668554c0a3aSHans de Goede 1669554c0a3aSHans de Goede if (adapter_to_pwrctl(padapter)->brfoffbyhw && padapter->bDriverStopped) 1670554c0a3aSHans de Goede { 1671554c0a3aSHans de Goede ret = -EINVAL; 1672554c0a3aSHans de Goede goto exit; 1673554c0a3aSHans de Goede } 1674554c0a3aSHans de Goede 1675554c0a3aSHans de Goede wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING; 1676554c0a3aSHans de Goede 1677554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, wait_status)) 1678554c0a3aSHans de Goede return -EAGAIN; 1679554c0a3aSHans de Goede 1680554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 1681554c0a3aSHans de Goede 1682554c0a3aSHans de Goede phead = get_list_head(queue); 1683554c0a3aSHans de Goede plist = get_next(phead); 1684554c0a3aSHans de Goede 1685554c0a3aSHans de Goede while (1) 1686554c0a3aSHans de Goede { 1687554c0a3aSHans de Goede if (phead == plist) 1688554c0a3aSHans de Goede break; 1689554c0a3aSHans de Goede 1690554c0a3aSHans de Goede if ((stop - ev) < SCAN_ITEM_SIZE) { 1691554c0a3aSHans de Goede ret = -E2BIG; 1692554c0a3aSHans de Goede break; 1693554c0a3aSHans de Goede } 1694554c0a3aSHans de Goede 1695554c0a3aSHans de Goede pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 1696554c0a3aSHans de Goede 1697554c0a3aSHans de Goede /* report network only if the current channel set contains the channel to which this network belongs */ 1698554c0a3aSHans de Goede if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0 1699554c0a3aSHans de Goede && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true 1700554c0a3aSHans de Goede && true == rtw_validate_ssid(&(pnetwork->network.Ssid)) 1701554c0a3aSHans de Goede ) 1702554c0a3aSHans de Goede { 1703554c0a3aSHans de Goede ev =translate_scan(padapter, a, pnetwork, ev, stop); 1704554c0a3aSHans de Goede } 1705554c0a3aSHans de Goede 1706554c0a3aSHans de Goede plist = get_next(plist); 1707554c0a3aSHans de Goede 1708554c0a3aSHans de Goede } 1709554c0a3aSHans de Goede 1710554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 1711554c0a3aSHans de Goede 1712554c0a3aSHans de Goede wrqu->data.length = ev-extra; 1713554c0a3aSHans de Goede wrqu->data.flags = 0; 1714554c0a3aSHans de Goede 1715554c0a3aSHans de Goede exit: 1716554c0a3aSHans de Goede 1717554c0a3aSHans de Goede #ifdef DBG_IOCTL 1718554c0a3aSHans de Goede DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret); 1719554c0a3aSHans de Goede #endif 1720554c0a3aSHans de Goede 1721554c0a3aSHans de Goede return ret ; 1722554c0a3aSHans de Goede 1723554c0a3aSHans de Goede } 1724554c0a3aSHans de Goede 1725554c0a3aSHans de Goede /* set ssid flow */ 1726554c0a3aSHans de Goede /* s1. rtw_set_802_11_infrastructure_mode() */ 1727554c0a3aSHans de Goede /* s2. set_802_11_authenticaion_mode() */ 1728554c0a3aSHans de Goede /* s3. set_802_11_encryption_mode() */ 1729554c0a3aSHans de Goede /* s4. rtw_set_802_11_ssid() */ 1730554c0a3aSHans de Goede static int rtw_wx_set_essid(struct net_device *dev, 1731554c0a3aSHans de Goede struct iw_request_info *a, 1732554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1733554c0a3aSHans de Goede { 1734554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1735554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1736554c0a3aSHans de Goede struct __queue *queue = &pmlmepriv->scanned_queue; 1737554c0a3aSHans de Goede struct list_head *phead; 1738554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 1739554c0a3aSHans de Goede enum NDIS_802_11_AUTHENTICATION_MODE authmode; 1740554c0a3aSHans de Goede struct ndis_802_11_ssid ndis_ssid; 1741554c0a3aSHans de Goede u8 *dst_ssid, *src_ssid; 1742554c0a3aSHans de Goede 1743554c0a3aSHans de Goede uint ret = 0, len; 1744554c0a3aSHans de Goede 1745554c0a3aSHans de Goede #ifdef DBG_IOCTL 1746554c0a3aSHans de Goede DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__); 1747554c0a3aSHans de Goede #endif 1748554c0a3aSHans de Goede 1749554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1750554c0a3aSHans de Goede ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv))); 1751554c0a3aSHans de Goede 1752554c0a3aSHans de Goede rtw_ps_deny(padapter, PS_DENY_JOIN); 1753554c0a3aSHans de Goede if (_FAIL == rtw_pwr_wakeup(padapter)) 1754554c0a3aSHans de Goede { 1755554c0a3aSHans de Goede ret = -1; 1756554c0a3aSHans de Goede goto exit; 1757554c0a3aSHans de Goede } 1758554c0a3aSHans de Goede 1759554c0a3aSHans de Goede if (!padapter->bup) { 1760554c0a3aSHans de Goede ret = -1; 1761554c0a3aSHans de Goede goto exit; 1762554c0a3aSHans de Goede } 1763554c0a3aSHans de Goede 1764554c0a3aSHans de Goede if (wrqu->essid.length > IW_ESSID_MAX_SIZE) { 1765554c0a3aSHans de Goede ret = -E2BIG; 1766554c0a3aSHans de Goede goto exit; 1767554c0a3aSHans de Goede } 1768554c0a3aSHans de Goede 1769554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1770554c0a3aSHans de Goede ret = -1; 1771554c0a3aSHans de Goede goto exit; 1772554c0a3aSHans de Goede } 1773554c0a3aSHans de Goede 1774554c0a3aSHans de Goede authmode = padapter->securitypriv.ndisauthtype; 1775554c0a3aSHans de Goede DBG_871X("=>%s\n", __func__); 1776554c0a3aSHans de Goede if (wrqu->essid.flags && wrqu->essid.length) 1777554c0a3aSHans de Goede { 1778554c0a3aSHans de Goede len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE; 1779554c0a3aSHans de Goede 1780554c0a3aSHans de Goede if (wrqu->essid.length != 33) 1781554c0a3aSHans de Goede DBG_871X("ssid =%s, len =%d\n", extra, wrqu->essid.length); 1782554c0a3aSHans de Goede 1783554c0a3aSHans de Goede memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid)); 1784554c0a3aSHans de Goede ndis_ssid.SsidLength = len; 1785554c0a3aSHans de Goede memcpy(ndis_ssid.Ssid, extra, len); 1786554c0a3aSHans de Goede src_ssid = ndis_ssid.Ssid; 1787554c0a3aSHans de Goede 1788554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid)); 1789554c0a3aSHans de Goede spin_lock_bh(&queue->lock); 1790554c0a3aSHans de Goede phead = get_list_head(queue); 1791554c0a3aSHans de Goede pmlmepriv->pscanned = get_next(phead); 1792554c0a3aSHans de Goede 1793554c0a3aSHans de Goede while (1) { 1794554c0a3aSHans de Goede if (phead == pmlmepriv->pscanned) 1795554c0a3aSHans de Goede { 1796554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_, 1797554c0a3aSHans de Goede ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n")); 1798554c0a3aSHans de Goede 1799554c0a3aSHans de Goede break; 1800554c0a3aSHans de Goede } 1801554c0a3aSHans de Goede 1802554c0a3aSHans de Goede pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list); 1803554c0a3aSHans de Goede 1804554c0a3aSHans de Goede pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); 1805554c0a3aSHans de Goede 1806554c0a3aSHans de Goede dst_ssid = pnetwork->network.Ssid.Ssid; 1807554c0a3aSHans de Goede 1808554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1809554c0a3aSHans de Goede ("rtw_wx_set_essid: dst_ssid =%s\n", 1810554c0a3aSHans de Goede pnetwork->network.Ssid.Ssid)); 1811554c0a3aSHans de Goede 1812554c0a3aSHans de Goede if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) && 1813554c0a3aSHans de Goede (pnetwork->network.Ssid.SsidLength ==ndis_ssid.SsidLength)) 1814554c0a3aSHans de Goede { 1815554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1816554c0a3aSHans de Goede ("rtw_wx_set_essid: find match, set infra mode\n")); 1817554c0a3aSHans de Goede 1818554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) 1819554c0a3aSHans de Goede { 1820554c0a3aSHans de Goede if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode) 1821554c0a3aSHans de Goede continue; 1822554c0a3aSHans de Goede } 1823554c0a3aSHans de Goede 1824554c0a3aSHans de Goede if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == false) 1825554c0a3aSHans de Goede { 1826554c0a3aSHans de Goede ret = -1; 1827554c0a3aSHans de Goede spin_unlock_bh(&queue->lock); 1828554c0a3aSHans de Goede goto exit; 1829554c0a3aSHans de Goede } 1830554c0a3aSHans de Goede 1831554c0a3aSHans de Goede break; 1832554c0a3aSHans de Goede } 1833554c0a3aSHans de Goede } 1834554c0a3aSHans de Goede spin_unlock_bh(&queue->lock); 1835554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1836554c0a3aSHans de Goede ("set ssid: set_802_11_auth. mode =%d\n", authmode)); 1837554c0a3aSHans de Goede rtw_set_802_11_authentication_mode(padapter, authmode); 1838554c0a3aSHans de Goede /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */ 1839554c0a3aSHans de Goede if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) { 1840554c0a3aSHans de Goede ret = -1; 1841554c0a3aSHans de Goede goto exit; 1842554c0a3aSHans de Goede } 1843554c0a3aSHans de Goede } 1844554c0a3aSHans de Goede 1845554c0a3aSHans de Goede exit: 1846554c0a3aSHans de Goede 1847554c0a3aSHans de Goede rtw_ps_deny_cancel(padapter, PS_DENY_JOIN); 1848554c0a3aSHans de Goede 1849554c0a3aSHans de Goede DBG_871X("<=%s, ret %d\n", __func__, ret); 1850554c0a3aSHans de Goede 1851554c0a3aSHans de Goede #ifdef DBG_IOCTL 1852554c0a3aSHans de Goede DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret); 1853554c0a3aSHans de Goede #endif 1854554c0a3aSHans de Goede 1855554c0a3aSHans de Goede return ret; 1856554c0a3aSHans de Goede } 1857554c0a3aSHans de Goede 1858554c0a3aSHans de Goede static int rtw_wx_get_essid(struct net_device *dev, 1859554c0a3aSHans de Goede struct iw_request_info *a, 1860554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1861554c0a3aSHans de Goede { 1862554c0a3aSHans de Goede u32 len, ret = 0; 1863554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1864554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1865554c0a3aSHans de Goede struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 1866554c0a3aSHans de Goede 1867554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n")); 1868554c0a3aSHans de Goede 1869554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || 1870554c0a3aSHans de Goede (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) 1871554c0a3aSHans de Goede { 1872554c0a3aSHans de Goede len = pcur_bss->Ssid.SsidLength; 1873554c0a3aSHans de Goede 1874554c0a3aSHans de Goede wrqu->essid.length = len; 1875554c0a3aSHans de Goede 1876554c0a3aSHans de Goede memcpy(extra, pcur_bss->Ssid.Ssid, len); 1877554c0a3aSHans de Goede 1878554c0a3aSHans de Goede wrqu->essid.flags = 1; 1879554c0a3aSHans de Goede } 1880554c0a3aSHans de Goede else 1881554c0a3aSHans de Goede { 1882554c0a3aSHans de Goede ret = -1; 1883554c0a3aSHans de Goede goto exit; 1884554c0a3aSHans de Goede } 1885554c0a3aSHans de Goede 1886554c0a3aSHans de Goede exit: 1887554c0a3aSHans de Goede return ret; 1888554c0a3aSHans de Goede } 1889554c0a3aSHans de Goede 1890554c0a3aSHans de Goede static int rtw_wx_set_rate(struct net_device *dev, 1891554c0a3aSHans de Goede struct iw_request_info *a, 1892554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1893554c0a3aSHans de Goede { 1894554c0a3aSHans de Goede int i, ret = 0; 1895554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1896554c0a3aSHans de Goede u8 datarates[NumRates]; 1897554c0a3aSHans de Goede u32 target_rate = wrqu->bitrate.value; 1898554c0a3aSHans de Goede u32 fixed = wrqu->bitrate.fixed; 1899554c0a3aSHans de Goede u32 ratevalue = 0; 1900554c0a3aSHans de Goede u8 mpdatarate[NumRates]={11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; 1901554c0a3aSHans de Goede 1902554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n")); 1903554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed)); 1904554c0a3aSHans de Goede 1905554c0a3aSHans de Goede if (target_rate == -1) { 1906554c0a3aSHans de Goede ratevalue = 11; 1907554c0a3aSHans de Goede goto set_rate; 1908554c0a3aSHans de Goede } 1909554c0a3aSHans de Goede target_rate = target_rate/100000; 1910554c0a3aSHans de Goede 1911554c0a3aSHans de Goede switch (target_rate) { 1912554c0a3aSHans de Goede case 10: 1913554c0a3aSHans de Goede ratevalue = 0; 1914554c0a3aSHans de Goede break; 1915554c0a3aSHans de Goede case 20: 1916554c0a3aSHans de Goede ratevalue = 1; 1917554c0a3aSHans de Goede break; 1918554c0a3aSHans de Goede case 55: 1919554c0a3aSHans de Goede ratevalue = 2; 1920554c0a3aSHans de Goede break; 1921554c0a3aSHans de Goede case 60: 1922554c0a3aSHans de Goede ratevalue = 3; 1923554c0a3aSHans de Goede break; 1924554c0a3aSHans de Goede case 90: 1925554c0a3aSHans de Goede ratevalue = 4; 1926554c0a3aSHans de Goede break; 1927554c0a3aSHans de Goede case 110: 1928554c0a3aSHans de Goede ratevalue = 5; 1929554c0a3aSHans de Goede break; 1930554c0a3aSHans de Goede case 120: 1931554c0a3aSHans de Goede ratevalue = 6; 1932554c0a3aSHans de Goede break; 1933554c0a3aSHans de Goede case 180: 1934554c0a3aSHans de Goede ratevalue = 7; 1935554c0a3aSHans de Goede break; 1936554c0a3aSHans de Goede case 240: 1937554c0a3aSHans de Goede ratevalue = 8; 1938554c0a3aSHans de Goede break; 1939554c0a3aSHans de Goede case 360: 1940554c0a3aSHans de Goede ratevalue = 9; 1941554c0a3aSHans de Goede break; 1942554c0a3aSHans de Goede case 480: 1943554c0a3aSHans de Goede ratevalue = 10; 1944554c0a3aSHans de Goede break; 1945554c0a3aSHans de Goede case 540: 1946554c0a3aSHans de Goede ratevalue = 11; 1947554c0a3aSHans de Goede break; 1948554c0a3aSHans de Goede default: 1949554c0a3aSHans de Goede ratevalue = 11; 1950554c0a3aSHans de Goede break; 1951554c0a3aSHans de Goede } 1952554c0a3aSHans de Goede 1953554c0a3aSHans de Goede set_rate: 1954554c0a3aSHans de Goede 1955554c0a3aSHans de Goede for (i = 0; i<NumRates; i++) 1956554c0a3aSHans de Goede { 1957554c0a3aSHans de Goede if (ratevalue ==mpdatarate[i]) 1958554c0a3aSHans de Goede { 1959554c0a3aSHans de Goede datarates[i] = mpdatarate[i]; 1960554c0a3aSHans de Goede if (fixed == 0) 1961554c0a3aSHans de Goede break; 1962554c0a3aSHans de Goede } 1963554c0a3aSHans de Goede else { 1964554c0a3aSHans de Goede datarates[i] = 0xff; 1965554c0a3aSHans de Goede } 1966554c0a3aSHans de Goede 1967554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i])); 1968554c0a3aSHans de Goede } 1969554c0a3aSHans de Goede 1970554c0a3aSHans de Goede if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) { 1971554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n")); 1972554c0a3aSHans de Goede ret = -1; 1973554c0a3aSHans de Goede } 1974554c0a3aSHans de Goede return ret; 1975554c0a3aSHans de Goede } 1976554c0a3aSHans de Goede 1977554c0a3aSHans de Goede static int rtw_wx_get_rate(struct net_device *dev, 1978554c0a3aSHans de Goede struct iw_request_info *info, 1979554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1980554c0a3aSHans de Goede { 1981554c0a3aSHans de Goede u16 max_rate = 0; 1982554c0a3aSHans de Goede 1983554c0a3aSHans de Goede max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev)); 1984554c0a3aSHans de Goede 1985554c0a3aSHans de Goede if (max_rate == 0) 1986554c0a3aSHans de Goede return -EPERM; 1987554c0a3aSHans de Goede 1988554c0a3aSHans de Goede wrqu->bitrate.fixed = 0; /* no auto select */ 1989554c0a3aSHans de Goede wrqu->bitrate.value = max_rate * 100000; 1990554c0a3aSHans de Goede 1991554c0a3aSHans de Goede return 0; 1992554c0a3aSHans de Goede } 1993554c0a3aSHans de Goede 1994554c0a3aSHans de Goede static int rtw_wx_set_rts(struct net_device *dev, 1995554c0a3aSHans de Goede struct iw_request_info *info, 1996554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 1997554c0a3aSHans de Goede { 1998554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1999554c0a3aSHans de Goede 2000554c0a3aSHans de Goede if (wrqu->rts.disabled) 2001554c0a3aSHans de Goede padapter->registrypriv.rts_thresh = 2347; 2002554c0a3aSHans de Goede else { 2003554c0a3aSHans de Goede if (wrqu->rts.value < 0 || 2004554c0a3aSHans de Goede wrqu->rts.value > 2347) 2005554c0a3aSHans de Goede return -EINVAL; 2006554c0a3aSHans de Goede 2007554c0a3aSHans de Goede padapter->registrypriv.rts_thresh = wrqu->rts.value; 2008554c0a3aSHans de Goede } 2009554c0a3aSHans de Goede 2010554c0a3aSHans de Goede DBG_871X("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh); 2011554c0a3aSHans de Goede 2012554c0a3aSHans de Goede return 0; 2013554c0a3aSHans de Goede } 2014554c0a3aSHans de Goede 2015554c0a3aSHans de Goede static int rtw_wx_get_rts(struct net_device *dev, 2016554c0a3aSHans de Goede struct iw_request_info *info, 2017554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2018554c0a3aSHans de Goede { 2019554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2020554c0a3aSHans de Goede 2021554c0a3aSHans de Goede DBG_871X("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh); 2022554c0a3aSHans de Goede 2023554c0a3aSHans de Goede wrqu->rts.value = padapter->registrypriv.rts_thresh; 2024554c0a3aSHans de Goede wrqu->rts.fixed = 0; /* no auto select */ 2025554c0a3aSHans de Goede /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */ 2026554c0a3aSHans de Goede 2027554c0a3aSHans de Goede return 0; 2028554c0a3aSHans de Goede } 2029554c0a3aSHans de Goede 2030554c0a3aSHans de Goede static int rtw_wx_set_frag(struct net_device *dev, 2031554c0a3aSHans de Goede struct iw_request_info *info, 2032554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2033554c0a3aSHans de Goede { 2034554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2035554c0a3aSHans de Goede 2036554c0a3aSHans de Goede if (wrqu->frag.disabled) 2037554c0a3aSHans de Goede padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD; 2038554c0a3aSHans de Goede else { 2039554c0a3aSHans de Goede if (wrqu->frag.value < MIN_FRAG_THRESHOLD || 2040554c0a3aSHans de Goede wrqu->frag.value > MAX_FRAG_THRESHOLD) 2041554c0a3aSHans de Goede return -EINVAL; 2042554c0a3aSHans de Goede 2043554c0a3aSHans de Goede padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1; 2044554c0a3aSHans de Goede } 2045554c0a3aSHans de Goede 2046554c0a3aSHans de Goede DBG_871X("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len); 2047554c0a3aSHans de Goede 2048554c0a3aSHans de Goede return 0; 2049554c0a3aSHans de Goede 2050554c0a3aSHans de Goede } 2051554c0a3aSHans de Goede 2052554c0a3aSHans de Goede static int rtw_wx_get_frag(struct net_device *dev, 2053554c0a3aSHans de Goede struct iw_request_info *info, 2054554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2055554c0a3aSHans de Goede { 2056554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2057554c0a3aSHans de Goede 2058554c0a3aSHans de Goede DBG_871X("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len); 2059554c0a3aSHans de Goede 2060554c0a3aSHans de Goede wrqu->frag.value = padapter->xmitpriv.frag_len; 2061554c0a3aSHans de Goede wrqu->frag.fixed = 0; /* no auto select */ 2062554c0a3aSHans de Goede /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */ 2063554c0a3aSHans de Goede 2064554c0a3aSHans de Goede return 0; 2065554c0a3aSHans de Goede } 2066554c0a3aSHans de Goede 2067554c0a3aSHans de Goede static int rtw_wx_get_retry(struct net_device *dev, 2068554c0a3aSHans de Goede struct iw_request_info *info, 2069554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2070554c0a3aSHans de Goede { 2071554c0a3aSHans de Goede /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */ 2072554c0a3aSHans de Goede 2073554c0a3aSHans de Goede 2074554c0a3aSHans de Goede wrqu->retry.value = 7; 2075554c0a3aSHans de Goede wrqu->retry.fixed = 0; /* no auto select */ 2076554c0a3aSHans de Goede wrqu->retry.disabled = 1; 2077554c0a3aSHans de Goede 2078554c0a3aSHans de Goede return 0; 2079554c0a3aSHans de Goede 2080554c0a3aSHans de Goede } 2081554c0a3aSHans de Goede 2082554c0a3aSHans de Goede static int rtw_wx_set_enc(struct net_device *dev, 2083554c0a3aSHans de Goede struct iw_request_info *info, 2084554c0a3aSHans de Goede union iwreq_data *wrqu, char *keybuf) 2085554c0a3aSHans de Goede { 2086554c0a3aSHans de Goede u32 key, ret = 0; 2087554c0a3aSHans de Goede u32 keyindex_provided; 2088554c0a3aSHans de Goede struct ndis_802_11_wep wep; 2089554c0a3aSHans de Goede enum NDIS_802_11_AUTHENTICATION_MODE authmode; 2090554c0a3aSHans de Goede 2091554c0a3aSHans de Goede struct iw_point *erq = &(wrqu->encoding); 2092554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2093554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 2094554c0a3aSHans de Goede DBG_871X("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags); 2095554c0a3aSHans de Goede 2096554c0a3aSHans de Goede memset(&wep, 0, sizeof(struct ndis_802_11_wep)); 2097554c0a3aSHans de Goede 2098554c0a3aSHans de Goede key = erq->flags & IW_ENCODE_INDEX; 2099554c0a3aSHans de Goede 2100554c0a3aSHans de Goede if (erq->flags & IW_ENCODE_DISABLED) 2101554c0a3aSHans de Goede { 2102554c0a3aSHans de Goede DBG_871X("EncryptionDisabled\n"); 2103554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; 2104554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 2105554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 2106554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ 2107554c0a3aSHans de Goede authmode = Ndis802_11AuthModeOpen; 2108554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =authmode; 2109554c0a3aSHans de Goede 2110554c0a3aSHans de Goede goto exit; 2111554c0a3aSHans de Goede } 2112554c0a3aSHans de Goede 2113554c0a3aSHans de Goede if (key) { 2114554c0a3aSHans de Goede if (key > WEP_KEYS) 2115554c0a3aSHans de Goede return -EINVAL; 2116554c0a3aSHans de Goede key--; 2117554c0a3aSHans de Goede keyindex_provided = 1; 2118554c0a3aSHans de Goede } 2119554c0a3aSHans de Goede else 2120554c0a3aSHans de Goede { 2121554c0a3aSHans de Goede keyindex_provided = 0; 2122554c0a3aSHans de Goede key = padapter->securitypriv.dot11PrivacyKeyIndex; 2123554c0a3aSHans de Goede DBG_871X("rtw_wx_set_enc, key =%d\n", key); 2124554c0a3aSHans de Goede } 2125554c0a3aSHans de Goede 2126554c0a3aSHans de Goede /* set authentication mode */ 2127554c0a3aSHans de Goede if (erq->flags & IW_ENCODE_OPEN) 2128554c0a3aSHans de Goede { 2129554c0a3aSHans de Goede DBG_871X("rtw_wx_set_enc():IW_ENCODE_OPEN\n"); 2130554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ 2131554c0a3aSHans de Goede 2132554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; 2133554c0a3aSHans de Goede 2134554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 2135554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 2136554c0a3aSHans de Goede authmode = Ndis802_11AuthModeOpen; 2137554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =authmode; 2138554c0a3aSHans de Goede } 2139554c0a3aSHans de Goede else if (erq->flags & IW_ENCODE_RESTRICTED) 2140554c0a3aSHans de Goede { 2141554c0a3aSHans de Goede DBG_871X("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n"); 2142554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 2143554c0a3aSHans de Goede 2144554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; 2145554c0a3aSHans de Goede 2146554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 2147554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; 2148554c0a3aSHans de Goede authmode = Ndis802_11AuthModeShared; 2149554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =authmode; 2150554c0a3aSHans de Goede } 2151554c0a3aSHans de Goede else 2152554c0a3aSHans de Goede { 2153554c0a3aSHans de Goede DBG_871X("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags); 2154554c0a3aSHans de Goede 2155554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ 2156554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ 2157554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 2158554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 2159554c0a3aSHans de Goede authmode = Ndis802_11AuthModeOpen; 2160554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =authmode; 2161554c0a3aSHans de Goede } 2162554c0a3aSHans de Goede 2163554c0a3aSHans de Goede wep.KeyIndex = key; 2164554c0a3aSHans de Goede if (erq->length > 0) 2165554c0a3aSHans de Goede { 2166554c0a3aSHans de Goede wep.KeyLength = erq->length <= 5 ? 5 : 13; 2167554c0a3aSHans de Goede 2168554c0a3aSHans de Goede wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); 2169554c0a3aSHans de Goede } 2170554c0a3aSHans de Goede else 2171554c0a3aSHans de Goede { 2172554c0a3aSHans de Goede wep.KeyLength = 0 ; 2173554c0a3aSHans de Goede 2174554c0a3aSHans de Goede if (keyindex_provided == 1)/* set key_id only, no given KeyMaterial(erq->length == 0). */ 2175554c0a3aSHans de Goede { 2176554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyKeyIndex = key; 2177554c0a3aSHans de Goede 2178554c0a3aSHans de Goede DBG_871X("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]); 2179554c0a3aSHans de Goede 2180554c0a3aSHans de Goede switch (padapter->securitypriv.dot11DefKeylen[key]) 2181554c0a3aSHans de Goede { 2182554c0a3aSHans de Goede case 5: 2183554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 2184554c0a3aSHans de Goede break; 2185554c0a3aSHans de Goede case 13: 2186554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; 2187554c0a3aSHans de Goede break; 2188554c0a3aSHans de Goede default: 2189554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 2190554c0a3aSHans de Goede break; 2191554c0a3aSHans de Goede } 2192554c0a3aSHans de Goede 2193554c0a3aSHans de Goede goto exit; 2194554c0a3aSHans de Goede 2195554c0a3aSHans de Goede } 2196554c0a3aSHans de Goede 2197554c0a3aSHans de Goede } 2198554c0a3aSHans de Goede 2199554c0a3aSHans de Goede wep.KeyIndex |= 0x80000000; 2200554c0a3aSHans de Goede 2201554c0a3aSHans de Goede memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); 2202554c0a3aSHans de Goede 2203554c0a3aSHans de Goede if (rtw_set_802_11_add_wep(padapter, &wep) == false) { 2204554c0a3aSHans de Goede if (rf_on == pwrpriv->rf_pwrstate) 2205554c0a3aSHans de Goede ret = -EOPNOTSUPP; 2206554c0a3aSHans de Goede goto exit; 2207554c0a3aSHans de Goede } 2208554c0a3aSHans de Goede 2209554c0a3aSHans de Goede exit: 2210554c0a3aSHans de Goede return ret; 2211554c0a3aSHans de Goede } 2212554c0a3aSHans de Goede 2213554c0a3aSHans de Goede static int rtw_wx_get_enc(struct net_device *dev, 2214554c0a3aSHans de Goede struct iw_request_info *info, 2215554c0a3aSHans de Goede union iwreq_data *wrqu, char *keybuf) 2216554c0a3aSHans de Goede { 2217554c0a3aSHans de Goede uint key, ret = 0; 2218554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2219554c0a3aSHans de Goede struct iw_point *erq = &(wrqu->encoding); 2220554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2221554c0a3aSHans de Goede 2222554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) != true) 2223554c0a3aSHans de Goede { 2224554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true) 2225554c0a3aSHans de Goede { 2226554c0a3aSHans de Goede erq->length = 0; 2227554c0a3aSHans de Goede erq->flags |= IW_ENCODE_DISABLED; 2228554c0a3aSHans de Goede return 0; 2229554c0a3aSHans de Goede } 2230554c0a3aSHans de Goede } 2231554c0a3aSHans de Goede 2232554c0a3aSHans de Goede 2233554c0a3aSHans de Goede key = erq->flags & IW_ENCODE_INDEX; 2234554c0a3aSHans de Goede 2235554c0a3aSHans de Goede if (key) { 2236554c0a3aSHans de Goede if (key > WEP_KEYS) 2237554c0a3aSHans de Goede return -EINVAL; 2238554c0a3aSHans de Goede key--; 2239554c0a3aSHans de Goede } else 2240554c0a3aSHans de Goede { 2241554c0a3aSHans de Goede key = padapter->securitypriv.dot11PrivacyKeyIndex; 2242554c0a3aSHans de Goede } 2243554c0a3aSHans de Goede 2244554c0a3aSHans de Goede erq->flags = key + 1; 2245554c0a3aSHans de Goede 2246554c0a3aSHans de Goede /* if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */ 2247554c0a3aSHans de Goede /* */ 2248554c0a3aSHans de Goede /* erq->flags |= IW_ENCODE_OPEN; */ 2249554c0a3aSHans de Goede /* */ 2250554c0a3aSHans de Goede 2251554c0a3aSHans de Goede switch (padapter->securitypriv.ndisencryptstatus) 2252554c0a3aSHans de Goede { 2253554c0a3aSHans de Goede case Ndis802_11EncryptionNotSupported: 2254554c0a3aSHans de Goede case Ndis802_11EncryptionDisabled: 2255554c0a3aSHans de Goede erq->length = 0; 2256554c0a3aSHans de Goede erq->flags |= IW_ENCODE_DISABLED; 2257554c0a3aSHans de Goede break; 2258554c0a3aSHans de Goede case Ndis802_11Encryption1Enabled: 2259554c0a3aSHans de Goede erq->length = padapter->securitypriv.dot11DefKeylen[key]; 2260554c0a3aSHans de Goede 2261554c0a3aSHans de Goede if (erq->length) 2262554c0a3aSHans de Goede { 2263554c0a3aSHans de Goede memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]); 2264554c0a3aSHans de Goede 2265554c0a3aSHans de Goede erq->flags |= IW_ENCODE_ENABLED; 2266554c0a3aSHans de Goede 2267554c0a3aSHans de Goede if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) 2268554c0a3aSHans de Goede { 2269554c0a3aSHans de Goede erq->flags |= IW_ENCODE_OPEN; 2270554c0a3aSHans de Goede } 2271554c0a3aSHans de Goede else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared) 2272554c0a3aSHans de Goede { 2273554c0a3aSHans de Goede erq->flags |= IW_ENCODE_RESTRICTED; 2274554c0a3aSHans de Goede } 2275554c0a3aSHans de Goede } 2276554c0a3aSHans de Goede else 2277554c0a3aSHans de Goede { 2278554c0a3aSHans de Goede erq->length = 0; 2279554c0a3aSHans de Goede erq->flags |= IW_ENCODE_DISABLED; 2280554c0a3aSHans de Goede } 2281554c0a3aSHans de Goede break; 2282554c0a3aSHans de Goede case Ndis802_11Encryption2Enabled: 2283554c0a3aSHans de Goede case Ndis802_11Encryption3Enabled: 2284554c0a3aSHans de Goede erq->length = 16; 2285554c0a3aSHans de Goede erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY); 2286554c0a3aSHans de Goede break; 2287554c0a3aSHans de Goede default: 2288554c0a3aSHans de Goede erq->length = 0; 2289554c0a3aSHans de Goede erq->flags |= IW_ENCODE_DISABLED; 2290554c0a3aSHans de Goede break; 2291554c0a3aSHans de Goede } 2292554c0a3aSHans de Goede return ret; 2293554c0a3aSHans de Goede } 2294554c0a3aSHans de Goede 2295554c0a3aSHans de Goede static int rtw_wx_get_power(struct net_device *dev, 2296554c0a3aSHans de Goede struct iw_request_info *info, 2297554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2298554c0a3aSHans de Goede { 2299554c0a3aSHans de Goede /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */ 2300554c0a3aSHans de Goede 2301554c0a3aSHans de Goede wrqu->power.value = 0; 2302554c0a3aSHans de Goede wrqu->power.fixed = 0; /* no auto select */ 2303554c0a3aSHans de Goede wrqu->power.disabled = 1; 2304554c0a3aSHans de Goede 2305554c0a3aSHans de Goede return 0; 2306554c0a3aSHans de Goede } 2307554c0a3aSHans de Goede 2308554c0a3aSHans de Goede static int rtw_wx_set_gen_ie(struct net_device *dev, 2309554c0a3aSHans de Goede struct iw_request_info *info, 2310554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2311554c0a3aSHans de Goede { 2312554c0a3aSHans de Goede int ret; 2313554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2314554c0a3aSHans de Goede 2315554c0a3aSHans de Goede ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length); 2316554c0a3aSHans de Goede 2317554c0a3aSHans de Goede return ret; 2318554c0a3aSHans de Goede } 2319554c0a3aSHans de Goede 2320554c0a3aSHans de Goede static int rtw_wx_set_auth(struct net_device *dev, 2321554c0a3aSHans de Goede struct iw_request_info *info, 2322554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2323554c0a3aSHans de Goede { 2324554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2325554c0a3aSHans de Goede struct iw_param *param = (struct iw_param*)&(wrqu->param); 2326554c0a3aSHans de Goede int ret = 0; 2327554c0a3aSHans de Goede 2328554c0a3aSHans de Goede switch (param->flags & IW_AUTH_INDEX) { 2329554c0a3aSHans de Goede 2330554c0a3aSHans de Goede case IW_AUTH_WPA_VERSION: 2331554c0a3aSHans de Goede break; 2332554c0a3aSHans de Goede case IW_AUTH_CIPHER_PAIRWISE: 2333554c0a3aSHans de Goede 2334554c0a3aSHans de Goede break; 2335554c0a3aSHans de Goede case IW_AUTH_CIPHER_GROUP: 2336554c0a3aSHans de Goede 2337554c0a3aSHans de Goede break; 2338554c0a3aSHans de Goede case IW_AUTH_KEY_MGMT: 2339554c0a3aSHans de Goede /* 2340554c0a3aSHans de Goede * ??? does not use these parameters 2341554c0a3aSHans de Goede */ 2342554c0a3aSHans de Goede break; 2343554c0a3aSHans de Goede 2344554c0a3aSHans de Goede case IW_AUTH_TKIP_COUNTERMEASURES: 2345554c0a3aSHans de Goede { 2346554c0a3aSHans de Goede if (param->value) 2347554c0a3aSHans de Goede { /* wpa_supplicant is enabling the tkip countermeasure. */ 2348554c0a3aSHans de Goede padapter->securitypriv.btkip_countermeasure = true; 2349554c0a3aSHans de Goede } 2350554c0a3aSHans de Goede else 2351554c0a3aSHans de Goede { /* wpa_supplicant is disabling the tkip countermeasure. */ 2352554c0a3aSHans de Goede padapter->securitypriv.btkip_countermeasure = false; 2353554c0a3aSHans de Goede } 2354554c0a3aSHans de Goede break; 2355554c0a3aSHans de Goede } 2356554c0a3aSHans de Goede case IW_AUTH_DROP_UNENCRYPTED: 2357554c0a3aSHans de Goede { 2358554c0a3aSHans de Goede /* HACK: 2359554c0a3aSHans de Goede * 2360554c0a3aSHans de Goede * wpa_supplicant calls set_wpa_enabled when the driver 2361554c0a3aSHans de Goede * is loaded and unloaded, regardless of if WPA is being 2362554c0a3aSHans de Goede * used. No other calls are made which can be used to 2363554c0a3aSHans de Goede * determine if encryption will be used or not prior to 2364554c0a3aSHans de Goede * association being expected. If encryption is not being 2365554c0a3aSHans de Goede * used, drop_unencrypted is set to false, else true -- we 2366554c0a3aSHans de Goede * can use this to determine if the CAP_PRIVACY_ON bit should 2367554c0a3aSHans de Goede * be set. 2368554c0a3aSHans de Goede */ 2369554c0a3aSHans de Goede 2370554c0a3aSHans de Goede if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled) 2371554c0a3aSHans de Goede { 2372554c0a3aSHans de Goede break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */ 2373554c0a3aSHans de Goede /* then it needn't reset it; */ 2374554c0a3aSHans de Goede } 2375554c0a3aSHans de Goede 2376554c0a3aSHans de Goede if (param->value) { 2377554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; 2378554c0a3aSHans de Goede padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 2379554c0a3aSHans de Goede padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 2380554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ 2381554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype =Ndis802_11AuthModeOpen; 2382554c0a3aSHans de Goede } 2383554c0a3aSHans de Goede 2384554c0a3aSHans de Goede break; 2385554c0a3aSHans de Goede } 2386554c0a3aSHans de Goede 2387554c0a3aSHans de Goede case IW_AUTH_80211_AUTH_ALG: 2388554c0a3aSHans de Goede 2389554c0a3aSHans de Goede /* 2390554c0a3aSHans de Goede * It's the starting point of a link layer connection using wpa_supplicant 2391554c0a3aSHans de Goede */ 2392554c0a3aSHans de Goede if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { 2393554c0a3aSHans de Goede LeaveAllPowerSaveMode(padapter); 2394554c0a3aSHans de Goede rtw_disassoc_cmd(padapter, 500, false); 2395554c0a3aSHans de Goede DBG_871X("%s...call rtw_indicate_disconnect\n ", __func__); 2396554c0a3aSHans de Goede rtw_indicate_disconnect(padapter); 2397554c0a3aSHans de Goede rtw_free_assoc_resources(padapter, 1); 2398554c0a3aSHans de Goede } 2399554c0a3aSHans de Goede 2400554c0a3aSHans de Goede 2401554c0a3aSHans de Goede ret = wpa_set_auth_algs(dev, (u32)param->value); 2402554c0a3aSHans de Goede 2403554c0a3aSHans de Goede break; 2404554c0a3aSHans de Goede 2405554c0a3aSHans de Goede case IW_AUTH_WPA_ENABLED: 2406554c0a3aSHans de Goede break; 2407554c0a3aSHans de Goede case IW_AUTH_RX_UNENCRYPTED_EAPOL: 2408554c0a3aSHans de Goede break; 2409554c0a3aSHans de Goede case IW_AUTH_PRIVACY_INVOKED: 2410554c0a3aSHans de Goede break; 2411554c0a3aSHans de Goede default: 2412554c0a3aSHans de Goede return -EOPNOTSUPP; 2413554c0a3aSHans de Goede } 2414554c0a3aSHans de Goede return ret; 2415554c0a3aSHans de Goede } 2416554c0a3aSHans de Goede 2417554c0a3aSHans de Goede static int rtw_wx_set_enc_ext(struct net_device *dev, 2418554c0a3aSHans de Goede struct iw_request_info *info, 2419554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2420554c0a3aSHans de Goede { 2421554c0a3aSHans de Goede char *alg_name; 2422554c0a3aSHans de Goede u32 param_len; 2423554c0a3aSHans de Goede struct ieee_param *param = NULL; 2424554c0a3aSHans de Goede struct iw_point *pencoding = &wrqu->encoding; 2425554c0a3aSHans de Goede struct iw_encode_ext *pext = (struct iw_encode_ext *)extra; 2426554c0a3aSHans de Goede int ret = 0; 2427554c0a3aSHans de Goede 2428554c0a3aSHans de Goede param_len = sizeof(struct ieee_param) + pext->key_len; 2429554c0a3aSHans de Goede param = (struct ieee_param *)rtw_malloc(param_len); 2430554c0a3aSHans de Goede if (param == NULL) 2431554c0a3aSHans de Goede return -1; 2432554c0a3aSHans de Goede 2433554c0a3aSHans de Goede memset(param, 0, param_len); 2434554c0a3aSHans de Goede 2435554c0a3aSHans de Goede param->cmd = IEEE_CMD_SET_ENCRYPTION; 2436554c0a3aSHans de Goede memset(param->sta_addr, 0xff, ETH_ALEN); 2437554c0a3aSHans de Goede 2438554c0a3aSHans de Goede 2439554c0a3aSHans de Goede switch (pext->alg) { 2440554c0a3aSHans de Goede case IW_ENCODE_ALG_NONE: 2441554c0a3aSHans de Goede /* todo: remove key */ 2442554c0a3aSHans de Goede /* remove = 1; */ 2443554c0a3aSHans de Goede alg_name = "none"; 2444554c0a3aSHans de Goede break; 2445554c0a3aSHans de Goede case IW_ENCODE_ALG_WEP: 2446554c0a3aSHans de Goede alg_name = "WEP"; 2447554c0a3aSHans de Goede break; 2448554c0a3aSHans de Goede case IW_ENCODE_ALG_TKIP: 2449554c0a3aSHans de Goede alg_name = "TKIP"; 2450554c0a3aSHans de Goede break; 2451554c0a3aSHans de Goede case IW_ENCODE_ALG_CCMP: 2452554c0a3aSHans de Goede alg_name = "CCMP"; 2453554c0a3aSHans de Goede break; 2454554c0a3aSHans de Goede case IW_ENCODE_ALG_AES_CMAC: 2455554c0a3aSHans de Goede alg_name = "BIP"; 2456554c0a3aSHans de Goede break; 2457554c0a3aSHans de Goede default: 2458554c0a3aSHans de Goede ret = -1; 2459554c0a3aSHans de Goede goto exit; 2460554c0a3aSHans de Goede } 2461554c0a3aSHans de Goede 2462554c0a3aSHans de Goede strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); 2463554c0a3aSHans de Goede 2464554c0a3aSHans de Goede if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 2465554c0a3aSHans de Goede { 2466554c0a3aSHans de Goede param->u.crypt.set_tx = 1; 2467554c0a3aSHans de Goede } 2468554c0a3aSHans de Goede 2469554c0a3aSHans de Goede /* cliW: WEP does not have group key 2470554c0a3aSHans de Goede * just not checking GROUP key setting 2471554c0a3aSHans de Goede */ 2472554c0a3aSHans de Goede if ((pext->alg != IW_ENCODE_ALG_WEP) && 2473554c0a3aSHans de Goede ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) 2474554c0a3aSHans de Goede || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC) 2475554c0a3aSHans de Goede )) 2476554c0a3aSHans de Goede { 2477554c0a3aSHans de Goede param->u.crypt.set_tx = 0; 2478554c0a3aSHans de Goede } 2479554c0a3aSHans de Goede 2480554c0a3aSHans de Goede param->u.crypt.idx = (pencoding->flags&0x00FF) -1 ; 2481554c0a3aSHans de Goede 2482554c0a3aSHans de Goede if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) 2483554c0a3aSHans de Goede { 2484554c0a3aSHans de Goede memcpy(param->u.crypt.seq, pext->rx_seq, 8); 2485554c0a3aSHans de Goede } 2486554c0a3aSHans de Goede 2487554c0a3aSHans de Goede if (pext->key_len) 2488554c0a3aSHans de Goede { 2489554c0a3aSHans de Goede param->u.crypt.key_len = pext->key_len; 2490554c0a3aSHans de Goede /* memcpy(param + 1, pext + 1, pext->key_len); */ 2491554c0a3aSHans de Goede memcpy(param->u.crypt.key, pext + 1, pext->key_len); 2492554c0a3aSHans de Goede } 2493554c0a3aSHans de Goede 2494554c0a3aSHans de Goede if (pencoding->flags & IW_ENCODE_DISABLED) 2495554c0a3aSHans de Goede { 2496554c0a3aSHans de Goede /* todo: remove key */ 2497554c0a3aSHans de Goede /* remove = 1; */ 2498554c0a3aSHans de Goede } 2499554c0a3aSHans de Goede 2500554c0a3aSHans de Goede ret = wpa_set_encryption(dev, param, param_len); 2501554c0a3aSHans de Goede 2502554c0a3aSHans de Goede exit: 2503554c0a3aSHans de Goede kfree((u8 *)param); 2504554c0a3aSHans de Goede 2505554c0a3aSHans de Goede return ret; 2506554c0a3aSHans de Goede } 2507554c0a3aSHans de Goede 2508554c0a3aSHans de Goede 2509554c0a3aSHans de Goede static int rtw_wx_get_nick(struct net_device *dev, 2510554c0a3aSHans de Goede struct iw_request_info *info, 2511554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2512554c0a3aSHans de Goede { 2513554c0a3aSHans de Goede /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */ 2514554c0a3aSHans de Goede /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */ 2515554c0a3aSHans de Goede /* struct security_priv *psecuritypriv = &padapter->securitypriv; */ 2516554c0a3aSHans de Goede 2517554c0a3aSHans de Goede if (extra) 2518554c0a3aSHans de Goede { 2519554c0a3aSHans de Goede wrqu->data.length = 14; 2520554c0a3aSHans de Goede wrqu->data.flags = 1; 2521554c0a3aSHans de Goede memcpy(extra, "<WIFI@REALTEK>", 14); 2522554c0a3aSHans de Goede } 2523554c0a3aSHans de Goede return 0; 2524554c0a3aSHans de Goede } 2525554c0a3aSHans de Goede 2526554c0a3aSHans de Goede static int rtw_wx_read32(struct net_device *dev, 2527554c0a3aSHans de Goede struct iw_request_info *info, 2528554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2529554c0a3aSHans de Goede { 2530554c0a3aSHans de Goede struct adapter *padapter; 2531554c0a3aSHans de Goede struct iw_point *p; 2532554c0a3aSHans de Goede u16 len; 2533554c0a3aSHans de Goede u32 addr; 2534554c0a3aSHans de Goede u32 data32; 2535554c0a3aSHans de Goede u32 bytes; 2536554c0a3aSHans de Goede u8 *ptmp; 2537554c0a3aSHans de Goede int ret; 2538554c0a3aSHans de Goede 2539554c0a3aSHans de Goede 2540554c0a3aSHans de Goede ret = 0; 2541554c0a3aSHans de Goede padapter = (struct adapter *)rtw_netdev_priv(dev); 2542554c0a3aSHans de Goede p = &wrqu->data; 2543554c0a3aSHans de Goede len = p->length; 2544554c0a3aSHans de Goede if (0 == len) 2545554c0a3aSHans de Goede return -EINVAL; 2546554c0a3aSHans de Goede 2547554c0a3aSHans de Goede ptmp = (u8 *)rtw_malloc(len); 2548554c0a3aSHans de Goede if (NULL == ptmp) 2549554c0a3aSHans de Goede return -ENOMEM; 2550554c0a3aSHans de Goede 2551554c0a3aSHans de Goede if (copy_from_user(ptmp, p->pointer, len)) { 2552554c0a3aSHans de Goede ret = -EFAULT; 2553554c0a3aSHans de Goede goto exit; 2554554c0a3aSHans de Goede } 2555554c0a3aSHans de Goede 2556554c0a3aSHans de Goede bytes = 0; 2557554c0a3aSHans de Goede addr = 0; 2558554c0a3aSHans de Goede sscanf(ptmp, "%d,%x", &bytes, &addr); 2559554c0a3aSHans de Goede 2560554c0a3aSHans de Goede switch (bytes) { 2561554c0a3aSHans de Goede case 1: 2562554c0a3aSHans de Goede data32 = rtw_read8(padapter, addr); 2563554c0a3aSHans de Goede sprintf(extra, "0x%02X", data32); 2564554c0a3aSHans de Goede break; 2565554c0a3aSHans de Goede case 2: 2566554c0a3aSHans de Goede data32 = rtw_read16(padapter, addr); 2567554c0a3aSHans de Goede sprintf(extra, "0x%04X", data32); 2568554c0a3aSHans de Goede break; 2569554c0a3aSHans de Goede case 4: 2570554c0a3aSHans de Goede data32 = rtw_read32(padapter, addr); 2571554c0a3aSHans de Goede sprintf(extra, "0x%08X", data32); 2572554c0a3aSHans de Goede break; 2573554c0a3aSHans de Goede default: 2574554c0a3aSHans de Goede DBG_871X(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__); 2575554c0a3aSHans de Goede ret = -EINVAL; 2576554c0a3aSHans de Goede goto exit; 2577554c0a3aSHans de Goede } 2578554c0a3aSHans de Goede DBG_871X(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra); 2579554c0a3aSHans de Goede 2580554c0a3aSHans de Goede exit: 2581554c0a3aSHans de Goede kfree(ptmp); 2582554c0a3aSHans de Goede 2583554c0a3aSHans de Goede return 0; 2584554c0a3aSHans de Goede } 2585554c0a3aSHans de Goede 2586554c0a3aSHans de Goede static int rtw_wx_write32(struct net_device *dev, 2587554c0a3aSHans de Goede struct iw_request_info *info, 2588554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2589554c0a3aSHans de Goede { 2590554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2591554c0a3aSHans de Goede 2592554c0a3aSHans de Goede u32 addr; 2593554c0a3aSHans de Goede u32 data32; 2594554c0a3aSHans de Goede u32 bytes; 2595554c0a3aSHans de Goede 2596554c0a3aSHans de Goede 2597554c0a3aSHans de Goede bytes = 0; 2598554c0a3aSHans de Goede addr = 0; 2599554c0a3aSHans de Goede data32 = 0; 2600554c0a3aSHans de Goede sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32); 2601554c0a3aSHans de Goede 2602554c0a3aSHans de Goede switch (bytes) { 2603554c0a3aSHans de Goede case 1: 2604554c0a3aSHans de Goede rtw_write8(padapter, addr, (u8)data32); 2605554c0a3aSHans de Goede DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32); 2606554c0a3aSHans de Goede break; 2607554c0a3aSHans de Goede case 2: 2608554c0a3aSHans de Goede rtw_write16(padapter, addr, (u16)data32); 2609554c0a3aSHans de Goede DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32); 2610554c0a3aSHans de Goede break; 2611554c0a3aSHans de Goede case 4: 2612554c0a3aSHans de Goede rtw_write32(padapter, addr, data32); 2613554c0a3aSHans de Goede DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32); 2614554c0a3aSHans de Goede break; 2615554c0a3aSHans de Goede default: 2616554c0a3aSHans de Goede DBG_871X(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__); 2617554c0a3aSHans de Goede return -EINVAL; 2618554c0a3aSHans de Goede } 2619554c0a3aSHans de Goede 2620554c0a3aSHans de Goede return 0; 2621554c0a3aSHans de Goede } 2622554c0a3aSHans de Goede 2623554c0a3aSHans de Goede static int rtw_wx_read_rf(struct net_device *dev, 2624554c0a3aSHans de Goede struct iw_request_info *info, 2625554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2626554c0a3aSHans de Goede { 2627554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2628554c0a3aSHans de Goede u32 path, addr, data32; 2629554c0a3aSHans de Goede 2630554c0a3aSHans de Goede 2631554c0a3aSHans de Goede path = *(u32*)extra; 2632554c0a3aSHans de Goede addr = *((u32*)extra + 1); 2633554c0a3aSHans de Goede data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF); 2634554c0a3aSHans de Goede /* 2635554c0a3aSHans de Goede * IMPORTANT!! 2636554c0a3aSHans de Goede * Only when wireless private ioctl is at odd order, 2637554c0a3aSHans de Goede * "extra" would be copied to user space. 2638554c0a3aSHans de Goede */ 2639554c0a3aSHans de Goede sprintf(extra, "0x%05x", data32); 2640554c0a3aSHans de Goede 2641554c0a3aSHans de Goede return 0; 2642554c0a3aSHans de Goede } 2643554c0a3aSHans de Goede 2644554c0a3aSHans de Goede static int rtw_wx_write_rf(struct net_device *dev, 2645554c0a3aSHans de Goede struct iw_request_info *info, 2646554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2647554c0a3aSHans de Goede { 2648554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2649554c0a3aSHans de Goede u32 path, addr, data32; 2650554c0a3aSHans de Goede 2651554c0a3aSHans de Goede 2652554c0a3aSHans de Goede path = *(u32*)extra; 2653554c0a3aSHans de Goede addr = *((u32*)extra + 1); 2654554c0a3aSHans de Goede data32 = *((u32*)extra + 2); 2655554c0a3aSHans de Goede /* DBG_871X("%s: path =%d addr = 0x%02x data = 0x%05x\n", __func__, path, addr, data32); */ 2656554c0a3aSHans de Goede rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32); 2657554c0a3aSHans de Goede 2658554c0a3aSHans de Goede return 0; 2659554c0a3aSHans de Goede } 2660554c0a3aSHans de Goede 2661554c0a3aSHans de Goede static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a, 2662554c0a3aSHans de Goede union iwreq_data *wrqu, char *b) 2663554c0a3aSHans de Goede { 2664554c0a3aSHans de Goede return -1; 2665554c0a3aSHans de Goede } 2666554c0a3aSHans de Goede 2667554c0a3aSHans de Goede static int dummy(struct net_device *dev, struct iw_request_info *a, 2668554c0a3aSHans de Goede union iwreq_data *wrqu, char *b) 2669554c0a3aSHans de Goede { 2670554c0a3aSHans de Goede /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */ 2671554c0a3aSHans de Goede /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */ 2672554c0a3aSHans de Goede 2673554c0a3aSHans de Goede /* DBG_871X("cmd_code =%x, fwstate = 0x%x\n", a->cmd, get_fwstate(pmlmepriv)); */ 2674554c0a3aSHans de Goede 2675554c0a3aSHans de Goede return -1; 2676554c0a3aSHans de Goede 2677554c0a3aSHans de Goede } 2678554c0a3aSHans de Goede 2679554c0a3aSHans de Goede static int rtw_wx_set_channel_plan(struct net_device *dev, 2680554c0a3aSHans de Goede struct iw_request_info *info, 2681554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2682554c0a3aSHans de Goede { 2683554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2684554c0a3aSHans de Goede u8 channel_plan_req = (u8) (*((int *)wrqu)); 2685554c0a3aSHans de Goede 2686554c0a3aSHans de Goede if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1, 1)) { 2687554c0a3aSHans de Goede DBG_871X("%s set channel_plan = 0x%02X\n", __func__, channel_plan_req); 2688554c0a3aSHans de Goede } else 2689554c0a3aSHans de Goede return -EPERM; 2690554c0a3aSHans de Goede 2691554c0a3aSHans de Goede return 0; 2692554c0a3aSHans de Goede } 2693554c0a3aSHans de Goede 2694554c0a3aSHans de Goede static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev, 2695554c0a3aSHans de Goede struct iw_request_info *a, 2696554c0a3aSHans de Goede union iwreq_data *wrqu, char *b) 2697554c0a3aSHans de Goede { 2698554c0a3aSHans de Goede return 0; 2699554c0a3aSHans de Goede } 2700554c0a3aSHans de Goede 2701554c0a3aSHans de Goede static int rtw_wx_get_sensitivity(struct net_device *dev, 2702554c0a3aSHans de Goede struct iw_request_info *info, 2703554c0a3aSHans de Goede union iwreq_data *wrqu, char *buf) 2704554c0a3aSHans de Goede { 2705554c0a3aSHans de Goede return 0; 2706554c0a3aSHans de Goede } 2707554c0a3aSHans de Goede 2708554c0a3aSHans de Goede static int rtw_wx_set_mtk_wps_ie(struct net_device *dev, 2709554c0a3aSHans de Goede struct iw_request_info *info, 2710554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2711554c0a3aSHans de Goede { 2712554c0a3aSHans de Goede return 0; 2713554c0a3aSHans de Goede } 2714554c0a3aSHans de Goede 2715554c0a3aSHans de Goede /* 2716554c0a3aSHans de Goede typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, 2717554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra); 2718554c0a3aSHans de Goede */ 2719554c0a3aSHans de Goede /* 2720554c0a3aSHans de Goede *For all data larger than 16 octets, we need to use a 2721554c0a3aSHans de Goede *pointer to memory allocated in user space. 2722554c0a3aSHans de Goede */ 2723554c0a3aSHans de Goede static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info, 2724554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2725554c0a3aSHans de Goede { 2726554c0a3aSHans de Goede return 0; 2727554c0a3aSHans de Goede } 2728554c0a3aSHans de Goede 2729554c0a3aSHans de Goede static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info, 2730554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2731554c0a3aSHans de Goede { 2732554c0a3aSHans de Goede int ret = 0; 2733554c0a3aSHans de Goede return ret; 2734554c0a3aSHans de Goede } 2735554c0a3aSHans de Goede 2736554c0a3aSHans de Goede static int rtw_get_ap_info(struct net_device *dev, 2737554c0a3aSHans de Goede struct iw_request_info *info, 2738554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2739554c0a3aSHans de Goede { 2740554c0a3aSHans de Goede int ret = 0; 2741554c0a3aSHans de Goede u32 cnt = 0, wpa_ielen; 2742554c0a3aSHans de Goede struct list_head *plist, *phead; 2743554c0a3aSHans de Goede unsigned char *pbuf; 2744554c0a3aSHans de Goede u8 bssid[ETH_ALEN]; 2745554c0a3aSHans de Goede char data[32]; 2746554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 2747554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2748554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2749554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 2750554c0a3aSHans de Goede struct iw_point *pdata = &wrqu->data; 2751554c0a3aSHans de Goede 2752554c0a3aSHans de Goede DBG_871X("+rtw_get_aplist_info\n"); 2753554c0a3aSHans de Goede 2754554c0a3aSHans de Goede if ((padapter->bDriverStopped) || (pdata == NULL)) 2755554c0a3aSHans de Goede { 2756554c0a3aSHans de Goede ret = -EINVAL; 2757554c0a3aSHans de Goede goto exit; 2758554c0a3aSHans de Goede } 2759554c0a3aSHans de Goede 2760554c0a3aSHans de Goede while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == true) 2761554c0a3aSHans de Goede { 2762554c0a3aSHans de Goede msleep(30); 2763554c0a3aSHans de Goede cnt++; 2764554c0a3aSHans de Goede if (cnt > 100) 2765554c0a3aSHans de Goede break; 2766554c0a3aSHans de Goede } 2767554c0a3aSHans de Goede 2768554c0a3aSHans de Goede 2769554c0a3aSHans de Goede /* pdata->length = 0;? */ 2770554c0a3aSHans de Goede pdata->flags = 0; 2771554c0a3aSHans de Goede if (pdata->length>=32) 2772554c0a3aSHans de Goede { 2773554c0a3aSHans de Goede if (copy_from_user(data, pdata->pointer, 32)) 2774554c0a3aSHans de Goede { 2775554c0a3aSHans de Goede ret = -EINVAL; 2776554c0a3aSHans de Goede goto exit; 2777554c0a3aSHans de Goede } 2778554c0a3aSHans de Goede } 2779554c0a3aSHans de Goede else 2780554c0a3aSHans de Goede { 2781554c0a3aSHans de Goede ret = -EINVAL; 2782554c0a3aSHans de Goede goto exit; 2783554c0a3aSHans de Goede } 2784554c0a3aSHans de Goede 2785554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 2786554c0a3aSHans de Goede 2787554c0a3aSHans de Goede phead = get_list_head(queue); 2788554c0a3aSHans de Goede plist = get_next(phead); 2789554c0a3aSHans de Goede 2790554c0a3aSHans de Goede while (1) 2791554c0a3aSHans de Goede { 2792554c0a3aSHans de Goede if (phead == plist) 2793554c0a3aSHans de Goede break; 2794554c0a3aSHans de Goede 2795554c0a3aSHans de Goede 2796554c0a3aSHans de Goede pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 2797554c0a3aSHans de Goede 2798554c0a3aSHans de Goede /* if (hwaddr_aton_i(pdata->pointer, bssid)) */ 2799554c0a3aSHans de Goede if (hwaddr_aton_i(data, bssid)) 2800554c0a3aSHans de Goede { 2801554c0a3aSHans de Goede DBG_871X("Invalid BSSID '%s'.\n", (u8 *)data); 2802554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2803554c0a3aSHans de Goede return -EINVAL; 2804554c0a3aSHans de Goede } 2805554c0a3aSHans de Goede 2806554c0a3aSHans de Goede 2807554c0a3aSHans de Goede if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN))/* BSSID match, then check if supporting wpa/wpa2 */ 2808554c0a3aSHans de Goede { 2809554c0a3aSHans de Goede DBG_871X("BSSID:" MAC_FMT "\n", MAC_ARG(bssid)); 2810554c0a3aSHans de Goede 2811554c0a3aSHans de Goede pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 2812554c0a3aSHans de Goede if (pbuf && (wpa_ielen>0)) 2813554c0a3aSHans de Goede { 2814554c0a3aSHans de Goede pdata->flags = 1; 2815554c0a3aSHans de Goede break; 2816554c0a3aSHans de Goede } 2817554c0a3aSHans de Goede 2818554c0a3aSHans de Goede pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 2819554c0a3aSHans de Goede if (pbuf && (wpa_ielen>0)) 2820554c0a3aSHans de Goede { 2821554c0a3aSHans de Goede pdata->flags = 2; 2822554c0a3aSHans de Goede break; 2823554c0a3aSHans de Goede } 2824554c0a3aSHans de Goede 2825554c0a3aSHans de Goede } 2826554c0a3aSHans de Goede 2827554c0a3aSHans de Goede plist = get_next(plist); 2828554c0a3aSHans de Goede 2829554c0a3aSHans de Goede } 2830554c0a3aSHans de Goede 2831554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2832554c0a3aSHans de Goede 2833554c0a3aSHans de Goede if (pdata->length>=34) 2834554c0a3aSHans de Goede { 2835554c0a3aSHans de Goede if (copy_to_user((u8 __force __user *)pdata->pointer+32, (u8 *)&pdata->flags, 1)) 2836554c0a3aSHans de Goede { 2837554c0a3aSHans de Goede ret = -EINVAL; 2838554c0a3aSHans de Goede goto exit; 2839554c0a3aSHans de Goede } 2840554c0a3aSHans de Goede } 2841554c0a3aSHans de Goede 2842554c0a3aSHans de Goede exit: 2843554c0a3aSHans de Goede 2844554c0a3aSHans de Goede return ret; 2845554c0a3aSHans de Goede 2846554c0a3aSHans de Goede } 2847554c0a3aSHans de Goede 2848554c0a3aSHans de Goede static int rtw_set_pid(struct net_device *dev, 2849554c0a3aSHans de Goede struct iw_request_info *info, 2850554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2851554c0a3aSHans de Goede { 2852554c0a3aSHans de Goede 2853554c0a3aSHans de Goede int ret = 0; 2854554c0a3aSHans de Goede struct adapter *padapter = rtw_netdev_priv(dev); 2855554c0a3aSHans de Goede int *pdata = (int *)wrqu; 2856554c0a3aSHans de Goede int selector; 2857554c0a3aSHans de Goede 2858554c0a3aSHans de Goede if ((padapter->bDriverStopped) || (pdata == NULL)) 2859554c0a3aSHans de Goede { 2860554c0a3aSHans de Goede ret = -EINVAL; 2861554c0a3aSHans de Goede goto exit; 2862554c0a3aSHans de Goede } 2863554c0a3aSHans de Goede 2864554c0a3aSHans de Goede selector = *pdata; 2865554c0a3aSHans de Goede if (selector < 3 && selector >= 0) { 2866554c0a3aSHans de Goede padapter->pid[selector] = *(pdata+1); 2867554c0a3aSHans de Goede DBG_871X("%s set pid[%d]=%d\n", __func__, selector , padapter->pid[selector]); 2868554c0a3aSHans de Goede } 2869554c0a3aSHans de Goede else 2870554c0a3aSHans de Goede DBG_871X("%s selector %d error\n", __func__, selector); 2871554c0a3aSHans de Goede 2872554c0a3aSHans de Goede exit: 2873554c0a3aSHans de Goede 2874554c0a3aSHans de Goede return ret; 2875554c0a3aSHans de Goede 2876554c0a3aSHans de Goede } 2877554c0a3aSHans de Goede 2878554c0a3aSHans de Goede static int rtw_wps_start(struct net_device *dev, 2879554c0a3aSHans de Goede struct iw_request_info *info, 2880554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2881554c0a3aSHans de Goede { 2882554c0a3aSHans de Goede 2883554c0a3aSHans de Goede int ret = 0; 2884554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2885554c0a3aSHans de Goede struct iw_point *pdata = &wrqu->data; 2886554c0a3aSHans de Goede u32 u32wps_start = 0; 2887554c0a3aSHans de Goede unsigned int uintRet = 0; 2888554c0a3aSHans de Goede 2889554c0a3aSHans de Goede if ((true == padapter->bDriverStopped) ||(true ==padapter->bSurpriseRemoved) || (NULL == pdata)) 2890554c0a3aSHans de Goede { 2891554c0a3aSHans de Goede ret = -EINVAL; 2892554c0a3aSHans de Goede goto exit; 2893554c0a3aSHans de Goede } 2894554c0a3aSHans de Goede 2895554c0a3aSHans de Goede uintRet = copy_from_user((void*) &u32wps_start, pdata->pointer, 4); 2896554c0a3aSHans de Goede if (u32wps_start == 0) 2897554c0a3aSHans de Goede { 2898554c0a3aSHans de Goede u32wps_start = *extra; 2899554c0a3aSHans de Goede } 2900554c0a3aSHans de Goede 2901554c0a3aSHans de Goede DBG_871X("[%s] wps_start = %d\n", __func__, u32wps_start); 2902554c0a3aSHans de Goede 2903554c0a3aSHans de Goede #ifdef CONFIG_INTEL_WIDI 2904554c0a3aSHans de Goede process_intel_widi_wps_status(padapter, u32wps_start); 2905554c0a3aSHans de Goede #endif /* CONFIG_INTEL_WIDI */ 2906554c0a3aSHans de Goede 2907554c0a3aSHans de Goede exit: 2908554c0a3aSHans de Goede 2909554c0a3aSHans de Goede return ret; 2910554c0a3aSHans de Goede 2911554c0a3aSHans de Goede } 2912554c0a3aSHans de Goede 2913554c0a3aSHans de Goede static int rtw_p2p_set(struct net_device *dev, 2914554c0a3aSHans de Goede struct iw_request_info *info, 2915554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2916554c0a3aSHans de Goede { 2917554c0a3aSHans de Goede 2918554c0a3aSHans de Goede int ret = 0; 2919554c0a3aSHans de Goede 2920554c0a3aSHans de Goede return ret; 2921554c0a3aSHans de Goede 2922554c0a3aSHans de Goede } 2923554c0a3aSHans de Goede 2924554c0a3aSHans de Goede static int rtw_p2p_get(struct net_device *dev, 2925554c0a3aSHans de Goede struct iw_request_info *info, 2926554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2927554c0a3aSHans de Goede { 2928554c0a3aSHans de Goede 2929554c0a3aSHans de Goede int ret = 0; 2930554c0a3aSHans de Goede 2931554c0a3aSHans de Goede return ret; 2932554c0a3aSHans de Goede 2933554c0a3aSHans de Goede } 2934554c0a3aSHans de Goede 2935554c0a3aSHans de Goede static int rtw_p2p_get2(struct net_device *dev, 2936554c0a3aSHans de Goede struct iw_request_info *info, 2937554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2938554c0a3aSHans de Goede { 2939554c0a3aSHans de Goede 2940554c0a3aSHans de Goede int ret = 0; 2941554c0a3aSHans de Goede 2942554c0a3aSHans de Goede return ret; 2943554c0a3aSHans de Goede 2944554c0a3aSHans de Goede } 2945554c0a3aSHans de Goede 2946554c0a3aSHans de Goede static int rtw_rereg_nd_name(struct net_device *dev, 2947554c0a3aSHans de Goede struct iw_request_info *info, 2948554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 2949554c0a3aSHans de Goede { 2950554c0a3aSHans de Goede int ret = 0; 2951554c0a3aSHans de Goede struct adapter *padapter = rtw_netdev_priv(dev); 2952554c0a3aSHans de Goede struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv; 2953554c0a3aSHans de Goede char new_ifname[IFNAMSIZ]; 2954554c0a3aSHans de Goede 2955554c0a3aSHans de Goede if (rereg_priv->old_ifname[0] == 0) { 2956554c0a3aSHans de Goede char *reg_ifname; 2957554c0a3aSHans de Goede reg_ifname = padapter->registrypriv.ifname; 2958554c0a3aSHans de Goede 2959554c0a3aSHans de Goede strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ); 2960554c0a3aSHans de Goede rereg_priv->old_ifname[IFNAMSIZ-1] = 0; 2961554c0a3aSHans de Goede } 2962554c0a3aSHans de Goede 2963554c0a3aSHans de Goede /* DBG_871X("%s wrqu->data.length:%d\n", __func__, wrqu->data.length); */ 2964554c0a3aSHans de Goede if (wrqu->data.length > IFNAMSIZ) 2965554c0a3aSHans de Goede return -EFAULT; 2966554c0a3aSHans de Goede 2967554c0a3aSHans de Goede if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ)) { 2968554c0a3aSHans de Goede return -EFAULT; 2969554c0a3aSHans de Goede } 2970554c0a3aSHans de Goede 2971554c0a3aSHans de Goede if (0 == strcmp(rereg_priv->old_ifname, new_ifname)) { 2972554c0a3aSHans de Goede return ret; 2973554c0a3aSHans de Goede } 2974554c0a3aSHans de Goede 2975554c0a3aSHans de Goede DBG_871X("%s new_ifname:%s\n", __func__, new_ifname); 2976554c0a3aSHans de Goede if (0 != (ret = rtw_change_ifname(padapter, new_ifname))) { 2977554c0a3aSHans de Goede goto exit; 2978554c0a3aSHans de Goede } 2979554c0a3aSHans de Goede 2980554c0a3aSHans de Goede strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ); 2981554c0a3aSHans de Goede rereg_priv->old_ifname[IFNAMSIZ-1] = 0; 2982554c0a3aSHans de Goede 2983554c0a3aSHans de Goede if (!memcmp(new_ifname, "disable%d", 9)) { 2984554c0a3aSHans de Goede 2985554c0a3aSHans de Goede DBG_871X("%s disable\n", __func__); 2986554c0a3aSHans de Goede /* free network queue for Android's timming issue */ 2987554c0a3aSHans de Goede rtw_free_network_queue(padapter, true); 2988554c0a3aSHans de Goede 2989554c0a3aSHans de Goede /* the interface is being "disabled", we can do deeper IPS */ 2990554c0a3aSHans de Goede /* rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); */ 2991554c0a3aSHans de Goede /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */ 2992554c0a3aSHans de Goede } 2993554c0a3aSHans de Goede exit: 2994554c0a3aSHans de Goede return ret; 2995554c0a3aSHans de Goede 2996554c0a3aSHans de Goede } 2997554c0a3aSHans de Goede 2998554c0a3aSHans de Goede static int rtw_dbg_port(struct net_device *dev, 2999554c0a3aSHans de Goede struct iw_request_info *info, 3000554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 3001554c0a3aSHans de Goede { 3002554c0a3aSHans de Goede int ret = 0; 3003554c0a3aSHans de Goede u8 major_cmd, minor_cmd; 3004554c0a3aSHans de Goede u16 arg; 3005554c0a3aSHans de Goede u32 extra_arg, *pdata, val32; 3006554c0a3aSHans de Goede struct sta_info *psta; 3007554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3008554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 3009554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3010554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3011554c0a3aSHans de Goede struct wlan_network *cur_network = &(pmlmepriv->cur_network); 3012554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3013554c0a3aSHans de Goede 3014554c0a3aSHans de Goede 3015554c0a3aSHans de Goede pdata = (u32*)&wrqu->data; 3016554c0a3aSHans de Goede 3017554c0a3aSHans de Goede val32 = *pdata; 3018554c0a3aSHans de Goede arg = (u16)(val32&0x0000ffff); 3019554c0a3aSHans de Goede major_cmd = (u8)(val32>>24); 3020554c0a3aSHans de Goede minor_cmd = (u8)((val32>>16)&0x00ff); 3021554c0a3aSHans de Goede 3022554c0a3aSHans de Goede extra_arg = *(pdata+1); 3023554c0a3aSHans de Goede 3024554c0a3aSHans de Goede switch (major_cmd) 3025554c0a3aSHans de Goede { 3026554c0a3aSHans de Goede case 0x70:/* read_reg */ 3027554c0a3aSHans de Goede switch (minor_cmd) 3028554c0a3aSHans de Goede { 3029554c0a3aSHans de Goede case 1: 3030554c0a3aSHans de Goede DBG_871X("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg)); 3031554c0a3aSHans de Goede break; 3032554c0a3aSHans de Goede case 2: 3033554c0a3aSHans de Goede DBG_871X("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg)); 3034554c0a3aSHans de Goede break; 3035554c0a3aSHans de Goede case 4: 3036554c0a3aSHans de Goede DBG_871X("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg)); 3037554c0a3aSHans de Goede break; 3038554c0a3aSHans de Goede } 3039554c0a3aSHans de Goede break; 3040554c0a3aSHans de Goede case 0x71:/* write_reg */ 3041554c0a3aSHans de Goede switch (minor_cmd) 3042554c0a3aSHans de Goede { 3043554c0a3aSHans de Goede case 1: 3044554c0a3aSHans de Goede rtw_write8(padapter, arg, extra_arg); 3045554c0a3aSHans de Goede DBG_871X("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg)); 3046554c0a3aSHans de Goede break; 3047554c0a3aSHans de Goede case 2: 3048554c0a3aSHans de Goede rtw_write16(padapter, arg, extra_arg); 3049554c0a3aSHans de Goede DBG_871X("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg)); 3050554c0a3aSHans de Goede break; 3051554c0a3aSHans de Goede case 4: 3052554c0a3aSHans de Goede rtw_write32(padapter, arg, extra_arg); 3053554c0a3aSHans de Goede DBG_871X("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg)); 3054554c0a3aSHans de Goede break; 3055554c0a3aSHans de Goede } 3056554c0a3aSHans de Goede break; 3057554c0a3aSHans de Goede case 0x72:/* read_bb */ 3058554c0a3aSHans de Goede DBG_871X("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff)); 3059554c0a3aSHans de Goede break; 3060554c0a3aSHans de Goede case 0x73:/* write_bb */ 3061554c0a3aSHans de Goede rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg); 3062554c0a3aSHans de Goede DBG_871X("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff)); 3063554c0a3aSHans de Goede break; 3064554c0a3aSHans de Goede case 0x74:/* read_rf */ 3065554c0a3aSHans de Goede DBG_871X("read RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff)); 3066554c0a3aSHans de Goede break; 3067554c0a3aSHans de Goede case 0x75:/* write_rf */ 3068554c0a3aSHans de Goede rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg); 3069554c0a3aSHans de Goede DBG_871X("write RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff)); 3070554c0a3aSHans de Goede break; 3071554c0a3aSHans de Goede 3072554c0a3aSHans de Goede case 0x76: 3073554c0a3aSHans de Goede switch (minor_cmd) 3074554c0a3aSHans de Goede { 3075554c0a3aSHans de Goede case 0x00: /* normal mode, */ 3076554c0a3aSHans de Goede padapter->recvpriv.is_signal_dbg = 0; 3077554c0a3aSHans de Goede break; 3078554c0a3aSHans de Goede case 0x01: /* dbg mode */ 3079554c0a3aSHans de Goede padapter->recvpriv.is_signal_dbg = 1; 3080554c0a3aSHans de Goede extra_arg = extra_arg>100?100:extra_arg; 3081554c0a3aSHans de Goede padapter->recvpriv.signal_strength_dbg =extra_arg; 3082554c0a3aSHans de Goede break; 3083554c0a3aSHans de Goede } 3084554c0a3aSHans de Goede break; 3085554c0a3aSHans de Goede case 0x78: /* IOL test */ 3086554c0a3aSHans de Goede break; 3087554c0a3aSHans de Goede case 0x79: 3088554c0a3aSHans de Goede { 3089554c0a3aSHans de Goede /* 3090554c0a3aSHans de Goede * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15 3091554c0a3aSHans de Goede * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15 3092554c0a3aSHans de Goede */ 3093554c0a3aSHans de Goede u8 value = extra_arg & 0x0f; 3094554c0a3aSHans de Goede u8 sign = minor_cmd; 3095554c0a3aSHans de Goede u16 write_value = 0; 3096554c0a3aSHans de Goede 3097554c0a3aSHans de Goede DBG_871X("%s set RESP_TXAGC to %s %u\n", __func__, sign?"minus":"plus", value); 3098554c0a3aSHans de Goede 3099554c0a3aSHans de Goede if (sign) 3100554c0a3aSHans de Goede value = value | 0x10; 3101554c0a3aSHans de Goede 3102554c0a3aSHans de Goede write_value = value | (value << 5); 3103554c0a3aSHans de Goede rtw_write16(padapter, 0x6d9, write_value); 3104554c0a3aSHans de Goede } 3105554c0a3aSHans de Goede break; 3106554c0a3aSHans de Goede case 0x7a: 3107554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress 3108554c0a3aSHans de Goede , WLAN_REASON_EXPIRATION_CHK); 3109554c0a3aSHans de Goede break; 3110554c0a3aSHans de Goede case 0x7F: 3111554c0a3aSHans de Goede switch (minor_cmd) 3112554c0a3aSHans de Goede { 3113554c0a3aSHans de Goede case 0x0: 3114554c0a3aSHans de Goede DBG_871X("fwstate = 0x%x\n", get_fwstate(pmlmepriv)); 3115554c0a3aSHans de Goede break; 3116554c0a3aSHans de Goede case 0x01: 3117554c0a3aSHans de Goede DBG_871X("minor_cmd 0x%x\n", minor_cmd); 3118554c0a3aSHans de Goede break; 3119554c0a3aSHans de Goede case 0x02: 3120554c0a3aSHans de Goede DBG_871X("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state); 3121554c0a3aSHans de Goede DBG_871X("DrvBcnEarly =%d\n", pmlmeext->DrvBcnEarly); 3122554c0a3aSHans de Goede DBG_871X("DrvBcnTimeOut =%d\n", pmlmeext->DrvBcnTimeOut); 3123554c0a3aSHans de Goede break; 3124554c0a3aSHans de Goede case 0x03: 3125554c0a3aSHans de Goede DBG_871X("qos_option =%d\n", pmlmepriv->qospriv.qos_option); 3126554c0a3aSHans de Goede DBG_871X("ht_option =%d\n", pmlmepriv->htpriv.ht_option); 3127554c0a3aSHans de Goede break; 3128554c0a3aSHans de Goede case 0x04: 3129554c0a3aSHans de Goede DBG_871X("cur_ch =%d\n", pmlmeext->cur_channel); 3130554c0a3aSHans de Goede DBG_871X("cur_bw =%d\n", pmlmeext->cur_bwmode); 3131554c0a3aSHans de Goede DBG_871X("cur_ch_off =%d\n", pmlmeext->cur_ch_offset); 3132554c0a3aSHans de Goede 3133554c0a3aSHans de Goede DBG_871X("oper_ch =%d\n", rtw_get_oper_ch(padapter)); 3134554c0a3aSHans de Goede DBG_871X("oper_bw =%d\n", rtw_get_oper_bw(padapter)); 3135554c0a3aSHans de Goede DBG_871X("oper_ch_offet =%d\n", rtw_get_oper_choffset(padapter)); 3136554c0a3aSHans de Goede 3137554c0a3aSHans de Goede break; 3138554c0a3aSHans de Goede case 0x05: 3139554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); 3140554c0a3aSHans de Goede if (psta) 3141554c0a3aSHans de Goede { 3142554c0a3aSHans de Goede int i; 3143554c0a3aSHans de Goede struct recv_reorder_ctrl *preorder_ctrl; 3144554c0a3aSHans de Goede 3145554c0a3aSHans de Goede DBG_871X("SSID =%s\n", cur_network->network.Ssid.Ssid); 3146554c0a3aSHans de Goede DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); 3147554c0a3aSHans de Goede DBG_871X("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); 3148554c0a3aSHans de Goede DBG_871X("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self); 3149554c0a3aSHans de Goede DBG_871X("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); 3150554c0a3aSHans de Goede DBG_871X("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); 3151554c0a3aSHans de Goede DBG_871X("bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); 3152554c0a3aSHans de Goede DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable); 3153554c0a3aSHans de Goede DBG_871X("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); 3154554c0a3aSHans de Goede 3155554c0a3aSHans de Goede for (i = 0;i<16;i++) 3156554c0a3aSHans de Goede { 3157554c0a3aSHans de Goede preorder_ctrl = &psta->recvreorder_ctrl[i]; 3158554c0a3aSHans de Goede if (preorder_ctrl->enable) 3159554c0a3aSHans de Goede { 3160554c0a3aSHans de Goede DBG_871X("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq); 3161554c0a3aSHans de Goede } 3162554c0a3aSHans de Goede } 3163554c0a3aSHans de Goede 3164554c0a3aSHans de Goede } 3165554c0a3aSHans de Goede else 3166554c0a3aSHans de Goede { 3167554c0a3aSHans de Goede DBG_871X("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress)); 3168554c0a3aSHans de Goede } 3169554c0a3aSHans de Goede break; 3170554c0a3aSHans de Goede case 0x06: 3171554c0a3aSHans de Goede { 3172554c0a3aSHans de Goede u32 ODMFlag; 3173554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag)); 3174554c0a3aSHans de Goede DBG_871X("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg); 3175554c0a3aSHans de Goede ODMFlag = (u32)(0x0f&arg); 3176554c0a3aSHans de Goede DBG_871X("(A)DMFlag = 0x%x\n", ODMFlag); 3177554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag)); 3178554c0a3aSHans de Goede } 3179554c0a3aSHans de Goede break; 3180554c0a3aSHans de Goede case 0x07: 3181554c0a3aSHans de Goede DBG_871X("bSurpriseRemoved =%d, bDriverStopped =%d\n", 3182554c0a3aSHans de Goede padapter->bSurpriseRemoved, padapter->bDriverStopped); 3183554c0a3aSHans de Goede break; 3184554c0a3aSHans de Goede case 0x08: 3185554c0a3aSHans de Goede { 3186554c0a3aSHans de Goede DBG_871X("minor_cmd 0x%x\n", minor_cmd); 3187554c0a3aSHans de Goede } 3188554c0a3aSHans de Goede break; 3189554c0a3aSHans de Goede case 0x09: 3190554c0a3aSHans de Goede { 3191554c0a3aSHans de Goede int i, j; 3192554c0a3aSHans de Goede struct list_head *plist, *phead; 3193554c0a3aSHans de Goede struct recv_reorder_ctrl *preorder_ctrl; 3194554c0a3aSHans de Goede 3195554c0a3aSHans de Goede DBG_871X("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); 3196554c0a3aSHans de Goede 3197554c0a3aSHans de Goede spin_lock_bh(&pstapriv->sta_hash_lock); 3198554c0a3aSHans de Goede 3199554c0a3aSHans de Goede for (i = 0; i< NUM_STA; i++) 3200554c0a3aSHans de Goede { 3201554c0a3aSHans de Goede phead = &(pstapriv->sta_hash[i]); 3202554c0a3aSHans de Goede plist = get_next(phead); 3203554c0a3aSHans de Goede 3204554c0a3aSHans de Goede while (phead != plist) 3205554c0a3aSHans de Goede { 3206554c0a3aSHans de Goede psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); 3207554c0a3aSHans de Goede 3208554c0a3aSHans de Goede plist = get_next(plist); 3209554c0a3aSHans de Goede 3210554c0a3aSHans de Goede if (extra_arg == psta->aid) 3211554c0a3aSHans de Goede { 3212554c0a3aSHans de Goede DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); 3213554c0a3aSHans de Goede DBG_871X("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self); 3214554c0a3aSHans de Goede DBG_871X("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); 3215554c0a3aSHans de Goede DBG_871X("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); 3216554c0a3aSHans de Goede DBG_871X("bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); 3217554c0a3aSHans de Goede DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable); 3218554c0a3aSHans de Goede DBG_871X("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); 3219554c0a3aSHans de Goede DBG_871X("capability = 0x%x\n", psta->capability); 3220554c0a3aSHans de Goede DBG_871X("flags = 0x%x\n", psta->flags); 3221554c0a3aSHans de Goede DBG_871X("wpa_psk = 0x%x\n", psta->wpa_psk); 3222554c0a3aSHans de Goede DBG_871X("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher); 3223554c0a3aSHans de Goede DBG_871X("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher); 3224554c0a3aSHans de Goede DBG_871X("qos_info = 0x%x\n", psta->qos_info); 3225554c0a3aSHans de Goede DBG_871X("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy); 3226554c0a3aSHans de Goede 3227554c0a3aSHans de Goede 3228554c0a3aSHans de Goede 3229554c0a3aSHans de Goede for (j = 0;j<16;j++) 3230554c0a3aSHans de Goede { 3231554c0a3aSHans de Goede preorder_ctrl = &psta->recvreorder_ctrl[j]; 3232554c0a3aSHans de Goede if (preorder_ctrl->enable) 3233554c0a3aSHans de Goede { 3234554c0a3aSHans de Goede DBG_871X("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq); 3235554c0a3aSHans de Goede } 3236554c0a3aSHans de Goede } 3237554c0a3aSHans de Goede 3238554c0a3aSHans de Goede } 3239554c0a3aSHans de Goede 3240554c0a3aSHans de Goede } 3241554c0a3aSHans de Goede } 3242554c0a3aSHans de Goede 3243554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->sta_hash_lock); 3244554c0a3aSHans de Goede 3245554c0a3aSHans de Goede } 3246554c0a3aSHans de Goede break; 3247554c0a3aSHans de Goede case 0x0a: 3248554c0a3aSHans de Goede { 3249554c0a3aSHans de Goede int max_mac_id = 0; 3250554c0a3aSHans de Goede max_mac_id = rtw_search_max_mac_id(padapter); 3251554c0a3aSHans de Goede printk("%s ==> max_mac_id = %d\n", __func__, max_mac_id); 3252554c0a3aSHans de Goede } 3253554c0a3aSHans de Goede break; 3254554c0a3aSHans de Goede case 0x0b: /* Enable = 1, Disable = 0 driver control vrtl_carrier_sense. */ 3255554c0a3aSHans de Goede if (arg == 0) { 3256554c0a3aSHans de Goede DBG_871X("disable driver ctrl vcs\n"); 3257554c0a3aSHans de Goede padapter->driver_vcs_en = 0; 3258554c0a3aSHans de Goede } 3259554c0a3aSHans de Goede else if (arg == 1) { 3260554c0a3aSHans de Goede DBG_871X("enable driver ctrl vcs = %d\n", extra_arg); 3261554c0a3aSHans de Goede padapter->driver_vcs_en = 1; 3262554c0a3aSHans de Goede 3263554c0a3aSHans de Goede if (extra_arg>2) 3264554c0a3aSHans de Goede padapter->driver_vcs_type = 1; 3265554c0a3aSHans de Goede else 3266554c0a3aSHans de Goede padapter->driver_vcs_type = extra_arg; 3267554c0a3aSHans de Goede } 3268554c0a3aSHans de Goede break; 3269554c0a3aSHans de Goede case 0x0c:/* dump rx/tx packet */ 3270554c0a3aSHans de Goede { 3271554c0a3aSHans de Goede if (arg == 0) { 3272554c0a3aSHans de Goede DBG_871X("dump rx packet (%d)\n", extra_arg); 3273554c0a3aSHans de Goede /* pHalData->bDumpRxPkt =extra_arg; */ 3274554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg)); 3275554c0a3aSHans de Goede } 3276554c0a3aSHans de Goede else if (arg == 1) { 3277554c0a3aSHans de Goede DBG_871X("dump tx packet (%d)\n", extra_arg); 3278554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg)); 3279554c0a3aSHans de Goede } 3280554c0a3aSHans de Goede } 3281554c0a3aSHans de Goede break; 3282554c0a3aSHans de Goede case 0x0e: 3283554c0a3aSHans de Goede { 3284554c0a3aSHans de Goede if (arg == 0) { 3285554c0a3aSHans de Goede DBG_871X("disable driver ctrl rx_ampdu_factor\n"); 3286554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor = 0xFF; 3287554c0a3aSHans de Goede } 3288554c0a3aSHans de Goede else if (arg == 1) { 3289554c0a3aSHans de Goede 3290554c0a3aSHans de Goede DBG_871X("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg); 3291554c0a3aSHans de Goede 3292554c0a3aSHans de Goede if ((extra_arg & 0x03) > 0x03) 3293554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor = 0xFF; 3294554c0a3aSHans de Goede else 3295554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor = extra_arg; 3296554c0a3aSHans de Goede } 3297554c0a3aSHans de Goede } 3298554c0a3aSHans de Goede break; 3299554c0a3aSHans de Goede 3300554c0a3aSHans de Goede case 0x10:/* driver version display */ 3301554c0a3aSHans de Goede dump_drv_version(RTW_DBGDUMP); 3302554c0a3aSHans de Goede break; 3303554c0a3aSHans de Goede case 0x11:/* dump linked status */ 3304554c0a3aSHans de Goede { 3305554c0a3aSHans de Goede linked_info_dump(padapter, extra_arg); 3306554c0a3aSHans de Goede } 3307554c0a3aSHans de Goede break; 3308554c0a3aSHans de Goede case 0x12: /* set rx_stbc */ 3309554c0a3aSHans de Goede { 3310554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 3311554c0a3aSHans de Goede /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */ 3312554c0a3aSHans de Goede /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */ 3313554c0a3aSHans de Goede if (pregpriv && (extra_arg == 0 || extra_arg == 1|| extra_arg == 2 || extra_arg == 3)) 3314554c0a3aSHans de Goede { 3315554c0a3aSHans de Goede pregpriv->rx_stbc = extra_arg; 3316554c0a3aSHans de Goede DBG_871X("set rx_stbc =%d\n", pregpriv->rx_stbc); 3317554c0a3aSHans de Goede } 3318554c0a3aSHans de Goede else 3319554c0a3aSHans de Goede DBG_871X("get rx_stbc =%d\n", pregpriv->rx_stbc); 3320554c0a3aSHans de Goede 3321554c0a3aSHans de Goede } 3322554c0a3aSHans de Goede break; 3323554c0a3aSHans de Goede case 0x13: /* set ampdu_enable */ 3324554c0a3aSHans de Goede { 3325554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 3326554c0a3aSHans de Goede /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */ 3327554c0a3aSHans de Goede if (pregpriv && extra_arg < 3) 3328554c0a3aSHans de Goede { 3329554c0a3aSHans de Goede pregpriv->ampdu_enable = extra_arg; 3330554c0a3aSHans de Goede DBG_871X("set ampdu_enable =%d\n", pregpriv->ampdu_enable); 3331554c0a3aSHans de Goede } 3332554c0a3aSHans de Goede else 3333554c0a3aSHans de Goede DBG_871X("get ampdu_enable =%d\n", pregpriv->ampdu_enable); 3334554c0a3aSHans de Goede 3335554c0a3aSHans de Goede } 3336554c0a3aSHans de Goede break; 3337554c0a3aSHans de Goede case 0x14: 3338554c0a3aSHans de Goede { 3339554c0a3aSHans de Goede DBG_871X("minor_cmd 0x%x\n", minor_cmd); 3340554c0a3aSHans de Goede } 3341554c0a3aSHans de Goede break; 3342554c0a3aSHans de Goede case 0x16: 3343554c0a3aSHans de Goede { 3344554c0a3aSHans de Goede if (arg == 0xff) { 3345554c0a3aSHans de Goede rtw_odm_dbg_comp_msg(RTW_DBGDUMP, padapter); 3346554c0a3aSHans de Goede } 3347554c0a3aSHans de Goede else { 3348554c0a3aSHans de Goede u64 dbg_comp = (u64)extra_arg; 3349554c0a3aSHans de Goede rtw_odm_dbg_comp_set(padapter, dbg_comp); 3350554c0a3aSHans de Goede } 3351554c0a3aSHans de Goede } 3352554c0a3aSHans de Goede break; 3353554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 3354554c0a3aSHans de Goede case 0x17: 3355554c0a3aSHans de Goede { 3356554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3357554c0a3aSHans de Goede printk("===> Fixed channel to %d\n", extra_arg); 3358554c0a3aSHans de Goede pmlmeext->fixed_chan = extra_arg; 3359554c0a3aSHans de Goede 3360554c0a3aSHans de Goede } 3361554c0a3aSHans de Goede break; 3362554c0a3aSHans de Goede #endif 3363554c0a3aSHans de Goede case 0x18: 3364554c0a3aSHans de Goede { 3365554c0a3aSHans de Goede printk("===> Switch USB Mode %d\n", extra_arg); 3366554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_USB_MODE, (u8 *)&extra_arg); 3367554c0a3aSHans de Goede } 3368554c0a3aSHans de Goede break; 3369554c0a3aSHans de Goede case 0x19: 3370554c0a3aSHans de Goede { 3371554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 3372554c0a3aSHans de Goede /* extra_arg : */ 3373554c0a3aSHans de Goede /* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */ 3374554c0a3aSHans de Goede /* BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */ 3375554c0a3aSHans de Goede if (arg == 0) { 3376554c0a3aSHans de Goede DBG_871X("driver disable LDPC\n"); 3377554c0a3aSHans de Goede pregistrypriv->ldpc_cap = 0x00; 3378554c0a3aSHans de Goede } 3379554c0a3aSHans de Goede else if (arg == 1) { 3380554c0a3aSHans de Goede DBG_871X("driver set LDPC cap = 0x%x\n", extra_arg); 3381554c0a3aSHans de Goede pregistrypriv->ldpc_cap = (u8)(extra_arg&0x33); 3382554c0a3aSHans de Goede } 3383554c0a3aSHans de Goede } 3384554c0a3aSHans de Goede break; 3385554c0a3aSHans de Goede case 0x1a: 3386554c0a3aSHans de Goede { 3387554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 3388554c0a3aSHans de Goede /* extra_arg : */ 3389554c0a3aSHans de Goede /* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */ 3390554c0a3aSHans de Goede /* BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */ 3391554c0a3aSHans de Goede if (arg == 0) { 3392554c0a3aSHans de Goede DBG_871X("driver disable STBC\n"); 3393554c0a3aSHans de Goede pregistrypriv->stbc_cap = 0x00; 3394554c0a3aSHans de Goede } 3395554c0a3aSHans de Goede else if (arg == 1) { 3396554c0a3aSHans de Goede DBG_871X("driver set STBC cap = 0x%x\n", extra_arg); 3397554c0a3aSHans de Goede pregistrypriv->stbc_cap = (u8)(extra_arg&0x33); 3398554c0a3aSHans de Goede } 3399554c0a3aSHans de Goede } 3400554c0a3aSHans de Goede break; 3401554c0a3aSHans de Goede case 0x1b: 3402554c0a3aSHans de Goede { 3403554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 3404554c0a3aSHans de Goede 3405554c0a3aSHans de Goede if (arg == 0) { 3406554c0a3aSHans de Goede DBG_871X("disable driver ctrl max_rx_rate, reset to default_rate_set\n"); 3407554c0a3aSHans de Goede init_mlme_default_rate_set(padapter); 3408554c0a3aSHans de Goede pregistrypriv->ht_enable = (u8)rtw_ht_enable; 3409554c0a3aSHans de Goede } 3410554c0a3aSHans de Goede else if (arg == 1) { 3411554c0a3aSHans de Goede 3412554c0a3aSHans de Goede int i; 3413554c0a3aSHans de Goede u8 max_rx_rate; 3414554c0a3aSHans de Goede 3415554c0a3aSHans de Goede DBG_871X("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg); 3416554c0a3aSHans de Goede 3417554c0a3aSHans de Goede max_rx_rate = (u8)extra_arg; 3418554c0a3aSHans de Goede 3419554c0a3aSHans de Goede if (max_rx_rate < 0xc) /* max_rx_rate < MSC0 -> B or G -> disable HT */ 3420554c0a3aSHans de Goede { 3421554c0a3aSHans de Goede pregistrypriv->ht_enable = 0; 3422554c0a3aSHans de Goede for (i = 0; i<NumRates; i++) 3423554c0a3aSHans de Goede { 3424554c0a3aSHans de Goede if (pmlmeext->datarate[i] > max_rx_rate) 3425554c0a3aSHans de Goede pmlmeext->datarate[i] = 0xff; 3426554c0a3aSHans de Goede } 3427554c0a3aSHans de Goede 3428554c0a3aSHans de Goede } 3429554c0a3aSHans de Goede else if (max_rx_rate < 0x1c) /* mcs0~mcs15 */ 3430554c0a3aSHans de Goede { 3431554c0a3aSHans de Goede u32 mcs_bitmap = 0x0; 3432554c0a3aSHans de Goede 3433554c0a3aSHans de Goede for (i = 0; i<((max_rx_rate+1)-0xc); i++) 3434554c0a3aSHans de Goede mcs_bitmap |= BIT(i); 3435554c0a3aSHans de Goede 3436554c0a3aSHans de Goede set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap); 3437554c0a3aSHans de Goede } 3438554c0a3aSHans de Goede } 3439554c0a3aSHans de Goede } 3440554c0a3aSHans de Goede break; 3441554c0a3aSHans de Goede case 0x1c: /* enable/disable driver control AMPDU Density for peer sta's rx */ 3442554c0a3aSHans de Goede { 3443554c0a3aSHans de Goede if (arg == 0) { 3444554c0a3aSHans de Goede DBG_871X("disable driver ctrl ampdu density\n"); 3445554c0a3aSHans de Goede padapter->driver_ampdu_spacing = 0xFF; 3446554c0a3aSHans de Goede } 3447554c0a3aSHans de Goede else if (arg == 1) { 3448554c0a3aSHans de Goede 3449554c0a3aSHans de Goede DBG_871X("enable driver ctrl ampdu density = %d\n", extra_arg); 3450554c0a3aSHans de Goede 3451554c0a3aSHans de Goede if ((extra_arg & 0x07) > 0x07) 3452554c0a3aSHans de Goede padapter->driver_ampdu_spacing = 0xFF; 3453554c0a3aSHans de Goede else 3454554c0a3aSHans de Goede padapter->driver_ampdu_spacing = extra_arg; 3455554c0a3aSHans de Goede } 3456554c0a3aSHans de Goede } 3457554c0a3aSHans de Goede break; 3458554c0a3aSHans de Goede #ifdef CONFIG_BACKGROUND_NOISE_MONITOR 3459554c0a3aSHans de Goede case 0x1e: 3460554c0a3aSHans de Goede { 3461554c0a3aSHans de Goede struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 3462554c0a3aSHans de Goede PDM_ODM_T pDM_Odm = &pHalData->odmpriv; 3463554c0a3aSHans de Goede u8 chan = rtw_get_oper_ch(padapter); 3464554c0a3aSHans de Goede DBG_871X("===========================================\n"); 3465554c0a3aSHans de Goede ODM_InbandNoise_Monitor(pDM_Odm, true, 0x1e, 100); 3466554c0a3aSHans de Goede DBG_871X("channel(%d), noise_a = %d, noise_b = %d , noise_all:%d\n", 3467554c0a3aSHans de Goede chan, pDM_Odm->noise_level.noise[ODM_RF_PATH_A], 3468554c0a3aSHans de Goede pDM_Odm->noise_level.noise[ODM_RF_PATH_B], 3469554c0a3aSHans de Goede pDM_Odm->noise_level.noise_all); 3470554c0a3aSHans de Goede DBG_871X("===========================================\n"); 3471554c0a3aSHans de Goede 3472554c0a3aSHans de Goede } 3473554c0a3aSHans de Goede break; 3474554c0a3aSHans de Goede #endif 3475554c0a3aSHans de Goede case 0x23: 3476554c0a3aSHans de Goede { 3477554c0a3aSHans de Goede DBG_871X("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1)?"on":"off"); 3478554c0a3aSHans de Goede padapter->bNotifyChannelChange = extra_arg; 3479554c0a3aSHans de Goede break; 3480554c0a3aSHans de Goede } 3481554c0a3aSHans de Goede case 0x24: 3482554c0a3aSHans de Goede { 3483554c0a3aSHans de Goede break; 3484554c0a3aSHans de Goede } 3485554c0a3aSHans de Goede #ifdef CONFIG_GPIO_API 3486554c0a3aSHans de Goede case 0x25: /* Get GPIO register */ 3487554c0a3aSHans de Goede { 3488554c0a3aSHans de Goede /* 3489554c0a3aSHans de Goede * dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7 3490554c0a3aSHans de Goede */ 3491554c0a3aSHans de Goede 3492554c0a3aSHans de Goede int value; 3493554c0a3aSHans de Goede DBG_871X("Read GPIO Value extra_arg = %d\n", extra_arg); 3494554c0a3aSHans de Goede value = rtw_get_gpio(dev, extra_arg); 3495554c0a3aSHans de Goede DBG_871X("Read GPIO Value = %d\n", value); 3496554c0a3aSHans de Goede break; 3497554c0a3aSHans de Goede } 3498554c0a3aSHans de Goede case 0x26: /* Set GPIO direction */ 3499554c0a3aSHans de Goede { 3500554c0a3aSHans de Goede 3501554c0a3aSHans de Goede /* dbg 0x7f26000x [y], Set gpio direction, 3502554c0a3aSHans de Goede * x: gpio_num, 4~7 y: indicate direction, 0~1 3503554c0a3aSHans de Goede */ 3504554c0a3aSHans de Goede 3505554c0a3aSHans de Goede int value; 3506554c0a3aSHans de Goede DBG_871X("Set GPIO Direction! arg = %d , extra_arg =%d\n", arg , extra_arg); 3507554c0a3aSHans de Goede value = rtw_config_gpio(dev, arg, extra_arg); 3508554c0a3aSHans de Goede DBG_871X("Set GPIO Direction %s\n", (value ==-1)?"Fail!!!":"Success"); 3509554c0a3aSHans de Goede break; 3510554c0a3aSHans de Goede } 3511554c0a3aSHans de Goede case 0x27: /* Set GPIO output direction value */ 3512554c0a3aSHans de Goede { 3513554c0a3aSHans de Goede /* 3514554c0a3aSHans de Goede * dbg 0x7f27000x [y], Set gpio output direction value, 3515554c0a3aSHans de Goede * x: gpio_num, 4~7 y: indicate direction, 0~1 3516554c0a3aSHans de Goede */ 3517554c0a3aSHans de Goede 3518554c0a3aSHans de Goede int value; 3519554c0a3aSHans de Goede DBG_871X("Set GPIO Value! arg = %d , extra_arg =%d\n", arg , extra_arg); 3520554c0a3aSHans de Goede value = rtw_set_gpio_output_value(dev, arg, extra_arg); 3521554c0a3aSHans de Goede DBG_871X("Set GPIO Value %s\n", (value ==-1)?"Fail!!!":"Success"); 3522554c0a3aSHans de Goede break; 3523554c0a3aSHans de Goede } 3524554c0a3aSHans de Goede #endif 3525554c0a3aSHans de Goede case 0xaa: 3526554c0a3aSHans de Goede { 3527554c0a3aSHans de Goede if ((extra_arg & 0x7F)> 0x3F) extra_arg = 0xFF; 3528554c0a3aSHans de Goede DBG_871X("chang data rate to :0x%02x\n", extra_arg); 3529554c0a3aSHans de Goede padapter->fix_rate = extra_arg; 3530554c0a3aSHans de Goede } 3531554c0a3aSHans de Goede break; 3532554c0a3aSHans de Goede case 0xdd:/* registers dump , 0 for mac reg, 1 for bb reg, 2 for rf reg */ 3533554c0a3aSHans de Goede { 3534554c0a3aSHans de Goede if (extra_arg == 0) { 3535554c0a3aSHans de Goede mac_reg_dump(RTW_DBGDUMP, padapter); 3536554c0a3aSHans de Goede } 3537554c0a3aSHans de Goede else if (extra_arg == 1) { 3538554c0a3aSHans de Goede bb_reg_dump(RTW_DBGDUMP, padapter); 3539554c0a3aSHans de Goede } 3540554c0a3aSHans de Goede else if (extra_arg ==2) { 3541554c0a3aSHans de Goede rf_reg_dump(RTW_DBGDUMP, padapter); 3542554c0a3aSHans de Goede } 3543554c0a3aSHans de Goede } 3544554c0a3aSHans de Goede break; 3545554c0a3aSHans de Goede 3546554c0a3aSHans de Goede case 0xee:/* turn on/off dynamic funcs */ 3547554c0a3aSHans de Goede { 3548554c0a3aSHans de Goede u32 odm_flag; 3549554c0a3aSHans de Goede 3550554c0a3aSHans de Goede if (0xf ==extra_arg) { 3551554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC,&odm_flag); 3552554c0a3aSHans de Goede DBG_871X(" === DMFlag(0x%08x) ===\n", odm_flag); 3553554c0a3aSHans de Goede DBG_871X("extra_arg = 0 - disable all dynamic func\n"); 3554554c0a3aSHans de Goede DBG_871X("extra_arg = 1 - disable DIG- BIT(0)\n"); 3555554c0a3aSHans de Goede DBG_871X("extra_arg = 2 - disable High power - BIT(1)\n"); 3556554c0a3aSHans de Goede DBG_871X("extra_arg = 3 - disable tx power tracking - BIT(2)\n"); 3557554c0a3aSHans de Goede DBG_871X("extra_arg = 4 - disable BT coexistence - BIT(3)\n"); 3558554c0a3aSHans de Goede DBG_871X("extra_arg = 5 - disable antenna diversity - BIT(4)\n"); 3559554c0a3aSHans de Goede DBG_871X("extra_arg = 6 - enable all dynamic func\n"); 3560554c0a3aSHans de Goede } 3561554c0a3aSHans de Goede else { 3562554c0a3aSHans de Goede /*extra_arg = 0 - disable all dynamic func 3563554c0a3aSHans de Goede extra_arg = 1 - disable DIG 3564554c0a3aSHans de Goede extra_arg = 2 - disable tx power tracking 3565554c0a3aSHans de Goede extra_arg = 3 - turn on all dynamic func 3566554c0a3aSHans de Goede */ 3567554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg)); 3568554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC,&odm_flag); 3569554c0a3aSHans de Goede DBG_871X(" === DMFlag(0x%08x) ===\n", odm_flag); 3570554c0a3aSHans de Goede } 3571554c0a3aSHans de Goede } 3572554c0a3aSHans de Goede break; 3573554c0a3aSHans de Goede 3574554c0a3aSHans de Goede case 0xfd: 3575554c0a3aSHans de Goede rtw_write8(padapter, 0xc50, arg); 3576554c0a3aSHans de Goede DBG_871X("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50)); 3577554c0a3aSHans de Goede rtw_write8(padapter, 0xc58, arg); 3578554c0a3aSHans de Goede DBG_871X("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58)); 3579554c0a3aSHans de Goede break; 3580554c0a3aSHans de Goede case 0xfe: 3581554c0a3aSHans de Goede DBG_871X("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50)); 3582554c0a3aSHans de Goede DBG_871X("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58)); 3583554c0a3aSHans de Goede break; 3584554c0a3aSHans de Goede case 0xff: 3585554c0a3aSHans de Goede { 3586554c0a3aSHans de Goede DBG_871X("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210)); 3587554c0a3aSHans de Goede DBG_871X("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608)); 3588554c0a3aSHans de Goede DBG_871X("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280)); 3589554c0a3aSHans de Goede DBG_871X("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284)); 3590554c0a3aSHans de Goede DBG_871X("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288)); 3591554c0a3aSHans de Goede 3592554c0a3aSHans de Goede DBG_871X("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664)); 3593554c0a3aSHans de Goede 3594554c0a3aSHans de Goede 3595554c0a3aSHans de Goede DBG_871X("\n"); 3596554c0a3aSHans de Goede 3597554c0a3aSHans de Goede DBG_871X("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430)); 3598554c0a3aSHans de Goede DBG_871X("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438)); 3599554c0a3aSHans de Goede 3600554c0a3aSHans de Goede DBG_871X("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440)); 3601554c0a3aSHans de Goede 3602554c0a3aSHans de Goede DBG_871X("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458)); 3603554c0a3aSHans de Goede 3604554c0a3aSHans de Goede DBG_871X("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484)); 3605554c0a3aSHans de Goede DBG_871X("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488)); 3606554c0a3aSHans de Goede 3607554c0a3aSHans de Goede DBG_871X("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444)); 3608554c0a3aSHans de Goede DBG_871X("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448)); 3609554c0a3aSHans de Goede DBG_871X("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c)); 3610554c0a3aSHans de Goede DBG_871X("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450)); 3611554c0a3aSHans de Goede } 3612554c0a3aSHans de Goede break; 3613554c0a3aSHans de Goede } 3614554c0a3aSHans de Goede break; 3615554c0a3aSHans de Goede default: 3616554c0a3aSHans de Goede DBG_871X("error dbg cmd!\n"); 3617554c0a3aSHans de Goede break; 3618554c0a3aSHans de Goede } 3619554c0a3aSHans de Goede 3620554c0a3aSHans de Goede 3621554c0a3aSHans de Goede return ret; 3622554c0a3aSHans de Goede 3623554c0a3aSHans de Goede } 3624554c0a3aSHans de Goede 3625554c0a3aSHans de Goede static int wpa_set_param(struct net_device *dev, u8 name, u32 value) 3626554c0a3aSHans de Goede { 3627554c0a3aSHans de Goede uint ret = 0; 3628554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3629554c0a3aSHans de Goede 3630554c0a3aSHans de Goede switch (name) { 3631554c0a3aSHans de Goede case IEEE_PARAM_WPA_ENABLED: 3632554c0a3aSHans de Goede 3633554c0a3aSHans de Goede padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */ 3634554c0a3aSHans de Goede 3635554c0a3aSHans de Goede /* ret = ieee80211_wpa_enable(ieee, value); */ 3636554c0a3aSHans de Goede 3637554c0a3aSHans de Goede switch ((value)&0xff) 3638554c0a3aSHans de Goede { 3639554c0a3aSHans de Goede case 1 : /* WPA */ 3640554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */ 3641554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; 3642554c0a3aSHans de Goede break; 3643554c0a3aSHans de Goede case 2: /* WPA2 */ 3644554c0a3aSHans de Goede padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */ 3645554c0a3aSHans de Goede padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; 3646554c0a3aSHans de Goede break; 3647554c0a3aSHans de Goede } 3648554c0a3aSHans de Goede 3649554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype)); 3650554c0a3aSHans de Goede 3651554c0a3aSHans de Goede break; 3652554c0a3aSHans de Goede 3653554c0a3aSHans de Goede case IEEE_PARAM_TKIP_COUNTERMEASURES: 3654554c0a3aSHans de Goede /* ieee->tkip_countermeasures =value; */ 3655554c0a3aSHans de Goede break; 3656554c0a3aSHans de Goede 3657554c0a3aSHans de Goede case IEEE_PARAM_DROP_UNENCRYPTED: 3658554c0a3aSHans de Goede { 3659554c0a3aSHans de Goede /* HACK: 3660554c0a3aSHans de Goede * 3661554c0a3aSHans de Goede * wpa_supplicant calls set_wpa_enabled when the driver 3662554c0a3aSHans de Goede * is loaded and unloaded, regardless of if WPA is being 3663554c0a3aSHans de Goede * used. No other calls are made which can be used to 3664554c0a3aSHans de Goede * determine if encryption will be used or not prior to 3665554c0a3aSHans de Goede * association being expected. If encryption is not being 3666554c0a3aSHans de Goede * used, drop_unencrypted is set to false, else true -- we 3667554c0a3aSHans de Goede * can use this to determine if the CAP_PRIVACY_ON bit should 3668554c0a3aSHans de Goede * be set. 3669554c0a3aSHans de Goede */ 3670554c0a3aSHans de Goede break; 3671554c0a3aSHans de Goede 3672554c0a3aSHans de Goede } 3673554c0a3aSHans de Goede case IEEE_PARAM_PRIVACY_INVOKED: 3674554c0a3aSHans de Goede 3675554c0a3aSHans de Goede /* ieee->privacy_invoked =value; */ 3676554c0a3aSHans de Goede 3677554c0a3aSHans de Goede break; 3678554c0a3aSHans de Goede 3679554c0a3aSHans de Goede case IEEE_PARAM_AUTH_ALGS: 3680554c0a3aSHans de Goede 3681554c0a3aSHans de Goede ret = wpa_set_auth_algs(dev, value); 3682554c0a3aSHans de Goede 3683554c0a3aSHans de Goede break; 3684554c0a3aSHans de Goede 3685554c0a3aSHans de Goede case IEEE_PARAM_IEEE_802_1X: 3686554c0a3aSHans de Goede 3687554c0a3aSHans de Goede /* ieee->ieee802_1x =value; */ 3688554c0a3aSHans de Goede 3689554c0a3aSHans de Goede break; 3690554c0a3aSHans de Goede 3691554c0a3aSHans de Goede case IEEE_PARAM_WPAX_SELECT: 3692554c0a3aSHans de Goede 3693554c0a3aSHans de Goede /* added for WPA2 mixed mode */ 3694554c0a3aSHans de Goede /* DBG_871X(KERN_WARNING "------------------------>wpax value = %x\n", value); */ 3695554c0a3aSHans de Goede /* 3696554c0a3aSHans de Goede spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags); 3697554c0a3aSHans de Goede ieee->wpax_type_set = 1; 3698554c0a3aSHans de Goede ieee->wpax_type_notify = value; 3699554c0a3aSHans de Goede spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags); 3700554c0a3aSHans de Goede */ 3701554c0a3aSHans de Goede 3702554c0a3aSHans de Goede break; 3703554c0a3aSHans de Goede 3704554c0a3aSHans de Goede default: 3705554c0a3aSHans de Goede 3706554c0a3aSHans de Goede 3707554c0a3aSHans de Goede 3708554c0a3aSHans de Goede ret = -EOPNOTSUPP; 3709554c0a3aSHans de Goede 3710554c0a3aSHans de Goede 3711554c0a3aSHans de Goede break; 3712554c0a3aSHans de Goede 3713554c0a3aSHans de Goede } 3714554c0a3aSHans de Goede 3715554c0a3aSHans de Goede return ret; 3716554c0a3aSHans de Goede 3717554c0a3aSHans de Goede } 3718554c0a3aSHans de Goede 3719554c0a3aSHans de Goede static int wpa_mlme(struct net_device *dev, u32 command, u32 reason) 3720554c0a3aSHans de Goede { 3721554c0a3aSHans de Goede int ret = 0; 3722554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3723554c0a3aSHans de Goede 3724554c0a3aSHans de Goede switch (command) 3725554c0a3aSHans de Goede { 3726554c0a3aSHans de Goede case IEEE_MLME_STA_DEAUTH: 3727554c0a3aSHans de Goede 3728554c0a3aSHans de Goede if (!rtw_set_802_11_disassociate(padapter)) 3729554c0a3aSHans de Goede ret = -1; 3730554c0a3aSHans de Goede 3731554c0a3aSHans de Goede break; 3732554c0a3aSHans de Goede 3733554c0a3aSHans de Goede case IEEE_MLME_STA_DISASSOC: 3734554c0a3aSHans de Goede 3735554c0a3aSHans de Goede if (!rtw_set_802_11_disassociate(padapter)) 3736554c0a3aSHans de Goede ret = -1; 3737554c0a3aSHans de Goede 3738554c0a3aSHans de Goede break; 3739554c0a3aSHans de Goede 3740554c0a3aSHans de Goede default: 3741554c0a3aSHans de Goede ret = -EOPNOTSUPP; 3742554c0a3aSHans de Goede break; 3743554c0a3aSHans de Goede } 3744554c0a3aSHans de Goede 3745554c0a3aSHans de Goede return ret; 3746554c0a3aSHans de Goede 3747554c0a3aSHans de Goede } 3748554c0a3aSHans de Goede 3749554c0a3aSHans de Goede static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) 3750554c0a3aSHans de Goede { 3751554c0a3aSHans de Goede struct ieee_param *param; 3752554c0a3aSHans de Goede uint ret = 0; 3753554c0a3aSHans de Goede 3754554c0a3aSHans de Goede /* down(&ieee->wx_sem); */ 3755554c0a3aSHans de Goede 3756554c0a3aSHans de Goede if (p->length < sizeof(struct ieee_param) || !p->pointer) { 3757554c0a3aSHans de Goede ret = -EINVAL; 3758554c0a3aSHans de Goede goto out; 3759554c0a3aSHans de Goede } 3760554c0a3aSHans de Goede 3761554c0a3aSHans de Goede param = (struct ieee_param *)rtw_malloc(p->length); 3762554c0a3aSHans de Goede if (param == NULL) 3763554c0a3aSHans de Goede { 3764554c0a3aSHans de Goede ret = -ENOMEM; 3765554c0a3aSHans de Goede goto out; 3766554c0a3aSHans de Goede } 3767554c0a3aSHans de Goede 3768554c0a3aSHans de Goede if (copy_from_user(param, p->pointer, p->length)) 3769554c0a3aSHans de Goede { 3770554c0a3aSHans de Goede kfree((u8 *)param); 3771554c0a3aSHans de Goede ret = -EFAULT; 3772554c0a3aSHans de Goede goto out; 3773554c0a3aSHans de Goede } 3774554c0a3aSHans de Goede 3775554c0a3aSHans de Goede switch (param->cmd) { 3776554c0a3aSHans de Goede 3777554c0a3aSHans de Goede case IEEE_CMD_SET_WPA_PARAM: 3778554c0a3aSHans de Goede ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value); 3779554c0a3aSHans de Goede break; 3780554c0a3aSHans de Goede 3781554c0a3aSHans de Goede case IEEE_CMD_SET_WPA_IE: 3782554c0a3aSHans de Goede /* ret = wpa_set_wpa_ie(dev, param, p->length); */ 3783554c0a3aSHans de Goede ret = rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev), (char*)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len); 3784554c0a3aSHans de Goede break; 3785554c0a3aSHans de Goede 3786554c0a3aSHans de Goede case IEEE_CMD_SET_ENCRYPTION: 3787554c0a3aSHans de Goede ret = wpa_set_encryption(dev, param, p->length); 3788554c0a3aSHans de Goede break; 3789554c0a3aSHans de Goede 3790554c0a3aSHans de Goede case IEEE_CMD_MLME: 3791554c0a3aSHans de Goede ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code); 3792554c0a3aSHans de Goede break; 3793554c0a3aSHans de Goede 3794554c0a3aSHans de Goede default: 3795554c0a3aSHans de Goede DBG_871X("Unknown WPA supplicant request: %d\n", param->cmd); 3796554c0a3aSHans de Goede ret = -EOPNOTSUPP; 3797554c0a3aSHans de Goede break; 3798554c0a3aSHans de Goede 3799554c0a3aSHans de Goede } 3800554c0a3aSHans de Goede 3801554c0a3aSHans de Goede if (ret == 0 && copy_to_user(p->pointer, param, p->length)) 3802554c0a3aSHans de Goede ret = -EFAULT; 3803554c0a3aSHans de Goede 3804554c0a3aSHans de Goede kfree((u8 *)param); 3805554c0a3aSHans de Goede 3806554c0a3aSHans de Goede out: 3807554c0a3aSHans de Goede 3808554c0a3aSHans de Goede /* up(&ieee->wx_sem); */ 3809554c0a3aSHans de Goede 3810554c0a3aSHans de Goede return ret; 3811554c0a3aSHans de Goede 3812554c0a3aSHans de Goede } 3813554c0a3aSHans de Goede 3814554c0a3aSHans de Goede static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) 3815554c0a3aSHans de Goede { 3816554c0a3aSHans de Goede int ret = 0; 3817554c0a3aSHans de Goede u32 wep_key_idx, wep_key_len, wep_total_len; 3818554c0a3aSHans de Goede struct ndis_802_11_wep *pwep = NULL; 3819554c0a3aSHans de Goede struct sta_info *psta = NULL, *pbcmc_sta = NULL; 3820554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3821554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3822554c0a3aSHans de Goede struct security_priv* psecuritypriv =&(padapter->securitypriv); 3823554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3824554c0a3aSHans de Goede 3825554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3826554c0a3aSHans de Goede 3827554c0a3aSHans de Goede param->u.crypt.err = 0; 3828554c0a3aSHans de Goede param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; 3829554c0a3aSHans de Goede 3830554c0a3aSHans de Goede /* sizeof(struct ieee_param) = 64 bytes; */ 3831554c0a3aSHans de Goede /* if (param_len != (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */ 3832554c0a3aSHans de Goede if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) 3833554c0a3aSHans de Goede { 3834554c0a3aSHans de Goede ret = -EINVAL; 3835554c0a3aSHans de Goede goto exit; 3836554c0a3aSHans de Goede } 3837554c0a3aSHans de Goede 3838554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 3839554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 3840554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 3841554c0a3aSHans de Goede { 3842554c0a3aSHans de Goede if (param->u.crypt.idx >= WEP_KEYS) 3843554c0a3aSHans de Goede { 3844554c0a3aSHans de Goede ret = -EINVAL; 3845554c0a3aSHans de Goede goto exit; 3846554c0a3aSHans de Goede } 3847554c0a3aSHans de Goede } 3848554c0a3aSHans de Goede else 3849554c0a3aSHans de Goede { 3850554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, param->sta_addr); 3851554c0a3aSHans de Goede if (!psta) 3852554c0a3aSHans de Goede { 3853554c0a3aSHans de Goede /* ret = -EINVAL; */ 3854554c0a3aSHans de Goede DBG_871X("rtw_set_encryption(), sta has already been removed or never been added\n"); 3855554c0a3aSHans de Goede goto exit; 3856554c0a3aSHans de Goede } 3857554c0a3aSHans de Goede } 3858554c0a3aSHans de Goede 3859554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) 3860554c0a3aSHans de Goede { 3861554c0a3aSHans de Goede /* todo:clear default encryption keys */ 3862554c0a3aSHans de Goede 3863554c0a3aSHans de Goede psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; 3864554c0a3aSHans de Goede psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled; 3865554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_; 3866554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; 3867554c0a3aSHans de Goede 3868554c0a3aSHans de Goede DBG_871X("clear default encryption keys, keyid =%d\n", param->u.crypt.idx); 3869554c0a3aSHans de Goede 3870554c0a3aSHans de Goede goto exit; 3871554c0a3aSHans de Goede } 3872554c0a3aSHans de Goede 3873554c0a3aSHans de Goede 3874554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) 3875554c0a3aSHans de Goede { 3876554c0a3aSHans de Goede DBG_871X("r871x_set_encryption, crypt.alg = WEP\n"); 3877554c0a3aSHans de Goede 3878554c0a3aSHans de Goede wep_key_idx = param->u.crypt.idx; 3879554c0a3aSHans de Goede wep_key_len = param->u.crypt.key_len; 3880554c0a3aSHans de Goede 3881554c0a3aSHans de Goede DBG_871X("r871x_set_encryption, wep_key_idx =%d, len =%d\n", wep_key_idx, wep_key_len); 3882554c0a3aSHans de Goede 3883554c0a3aSHans de Goede if ((wep_key_idx >= WEP_KEYS) || (wep_key_len<= 0)) 3884554c0a3aSHans de Goede { 3885554c0a3aSHans de Goede ret = -EINVAL; 3886554c0a3aSHans de Goede goto exit; 3887554c0a3aSHans de Goede } 3888554c0a3aSHans de Goede 3889554c0a3aSHans de Goede 3890554c0a3aSHans de Goede if (wep_key_len > 0) 3891554c0a3aSHans de Goede { 3892554c0a3aSHans de Goede wep_key_len = wep_key_len <= 5 ? 5 : 13; 3893554c0a3aSHans de Goede wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); 3894554c0a3aSHans de Goede pwep =(struct ndis_802_11_wep *)rtw_malloc(wep_total_len); 3895554c0a3aSHans de Goede if (pwep == NULL) { 3896554c0a3aSHans de Goede DBG_871X(" r871x_set_encryption: pwep allocate fail !!!\n"); 3897554c0a3aSHans de Goede goto exit; 3898554c0a3aSHans de Goede } 3899554c0a3aSHans de Goede 3900554c0a3aSHans de Goede memset(pwep, 0, wep_total_len); 3901554c0a3aSHans de Goede 3902554c0a3aSHans de Goede pwep->KeyLength = wep_key_len; 3903554c0a3aSHans de Goede pwep->Length = wep_total_len; 3904554c0a3aSHans de Goede 3905554c0a3aSHans de Goede } 3906554c0a3aSHans de Goede 3907554c0a3aSHans de Goede pwep->KeyIndex = wep_key_idx; 3908554c0a3aSHans de Goede 3909554c0a3aSHans de Goede memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); 3910554c0a3aSHans de Goede 3911554c0a3aSHans de Goede if (param->u.crypt.set_tx) 3912554c0a3aSHans de Goede { 3913554c0a3aSHans de Goede DBG_871X("wep, set_tx = 1\n"); 3914554c0a3aSHans de Goede 3915554c0a3aSHans de Goede psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; 3916554c0a3aSHans de Goede psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; 3917554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; 3918554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _WEP40_; 3919554c0a3aSHans de Goede 3920554c0a3aSHans de Goede if (pwep->KeyLength == 13) 3921554c0a3aSHans de Goede { 3922554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm = _WEP104_; 3923554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _WEP104_; 3924554c0a3aSHans de Goede } 3925554c0a3aSHans de Goede 3926554c0a3aSHans de Goede 3927554c0a3aSHans de Goede psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx; 3928554c0a3aSHans de Goede 3929554c0a3aSHans de Goede memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength); 3930554c0a3aSHans de Goede 3931554c0a3aSHans de Goede psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength; 3932554c0a3aSHans de Goede 3933554c0a3aSHans de Goede rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1); 3934554c0a3aSHans de Goede } 3935554c0a3aSHans de Goede else 3936554c0a3aSHans de Goede { 3937554c0a3aSHans de Goede DBG_871X("wep, set_tx = 0\n"); 3938554c0a3aSHans de Goede 3939554c0a3aSHans de Goede /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */ 3940554c0a3aSHans de Goede /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */ 3941554c0a3aSHans de Goede 3942554c0a3aSHans de Goede memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength); 3943554c0a3aSHans de Goede 3944554c0a3aSHans de Goede psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength; 3945554c0a3aSHans de Goede 3946554c0a3aSHans de Goede rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0); 3947554c0a3aSHans de Goede } 3948554c0a3aSHans de Goede 3949554c0a3aSHans de Goede goto exit; 3950554c0a3aSHans de Goede 3951554c0a3aSHans de Goede } 3952554c0a3aSHans de Goede 3953554c0a3aSHans de Goede 3954554c0a3aSHans de Goede if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) /* group key */ 3955554c0a3aSHans de Goede { 3956554c0a3aSHans de Goede if (param->u.crypt.set_tx == 1) 3957554c0a3aSHans de Goede { 3958554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "WEP") == 0) 3959554c0a3aSHans de Goede { 3960554c0a3aSHans de Goede DBG_871X("%s, set group_key, WEP\n", __func__); 3961554c0a3aSHans de Goede 3962554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 3963554c0a3aSHans de Goede 3964554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _WEP40_; 3965554c0a3aSHans de Goede if (param->u.crypt.key_len == 13) 3966554c0a3aSHans de Goede { 3967554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _WEP104_; 3968554c0a3aSHans de Goede } 3969554c0a3aSHans de Goede 3970554c0a3aSHans de Goede } 3971554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "TKIP") == 0) 3972554c0a3aSHans de Goede { 3973554c0a3aSHans de Goede DBG_871X("%s, set group_key, TKIP\n", __func__); 3974554c0a3aSHans de Goede 3975554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _TKIP_; 3976554c0a3aSHans de Goede 3977554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 3978554c0a3aSHans de Goede 3979554c0a3aSHans de Goede /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ 3980554c0a3aSHans de Goede /* set mic key */ 3981554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8); 3982554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8); 3983554c0a3aSHans de Goede 3984554c0a3aSHans de Goede psecuritypriv->busetkipkey = true; 3985554c0a3aSHans de Goede 3986554c0a3aSHans de Goede } 3987554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "CCMP") == 0) 3988554c0a3aSHans de Goede { 3989554c0a3aSHans de Goede DBG_871X("%s, set group_key, CCMP\n", __func__); 3990554c0a3aSHans de Goede 3991554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _AES_; 3992554c0a3aSHans de Goede 3993554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 3994554c0a3aSHans de Goede } 3995554c0a3aSHans de Goede else 3996554c0a3aSHans de Goede { 3997554c0a3aSHans de Goede DBG_871X("%s, set group_key, none\n", __func__); 3998554c0a3aSHans de Goede 3999554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; 4000554c0a3aSHans de Goede } 4001554c0a3aSHans de Goede 4002554c0a3aSHans de Goede psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx; 4003554c0a3aSHans de Goede 4004554c0a3aSHans de Goede psecuritypriv->binstallGrpkey = true; 4005554c0a3aSHans de Goede 4006554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */ 4007554c0a3aSHans de Goede 4008554c0a3aSHans de Goede rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx); 4009554c0a3aSHans de Goede 4010554c0a3aSHans de Goede pbcmc_sta =rtw_get_bcmc_stainfo(padapter); 4011554c0a3aSHans de Goede if (pbcmc_sta) 4012554c0a3aSHans de Goede { 4013554c0a3aSHans de Goede pbcmc_sta->ieee8021x_blocked = false; 4014554c0a3aSHans de Goede pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */ 4015554c0a3aSHans de Goede } 4016554c0a3aSHans de Goede 4017554c0a3aSHans de Goede } 4018554c0a3aSHans de Goede 4019554c0a3aSHans de Goede goto exit; 4020554c0a3aSHans de Goede 4021554c0a3aSHans de Goede } 4022554c0a3aSHans de Goede 4023554c0a3aSHans de Goede if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) /* psk/802_1x */ 4024554c0a3aSHans de Goede { 4025554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 4026554c0a3aSHans de Goede { 4027554c0a3aSHans de Goede if (param->u.crypt.set_tx == 1) 4028554c0a3aSHans de Goede { 4029554c0a3aSHans de Goede memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 4030554c0a3aSHans de Goede 4031554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "WEP") == 0) 4032554c0a3aSHans de Goede { 4033554c0a3aSHans de Goede DBG_871X("%s, set pairwise key, WEP\n", __func__); 4034554c0a3aSHans de Goede 4035554c0a3aSHans de Goede psta->dot118021XPrivacy = _WEP40_; 4036554c0a3aSHans de Goede if (param->u.crypt.key_len == 13) 4037554c0a3aSHans de Goede { 4038554c0a3aSHans de Goede psta->dot118021XPrivacy = _WEP104_; 4039554c0a3aSHans de Goede } 4040554c0a3aSHans de Goede } 4041554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "TKIP") == 0) 4042554c0a3aSHans de Goede { 4043554c0a3aSHans de Goede DBG_871X("%s, set pairwise key, TKIP\n", __func__); 4044554c0a3aSHans de Goede 4045554c0a3aSHans de Goede psta->dot118021XPrivacy = _TKIP_; 4046554c0a3aSHans de Goede 4047554c0a3aSHans de Goede /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ 4048554c0a3aSHans de Goede /* set mic key */ 4049554c0a3aSHans de Goede memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8); 4050554c0a3aSHans de Goede memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8); 4051554c0a3aSHans de Goede 4052554c0a3aSHans de Goede psecuritypriv->busetkipkey = true; 4053554c0a3aSHans de Goede 4054554c0a3aSHans de Goede } 4055554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "CCMP") == 0) 4056554c0a3aSHans de Goede { 4057554c0a3aSHans de Goede 4058554c0a3aSHans de Goede DBG_871X("%s, set pairwise key, CCMP\n", __func__); 4059554c0a3aSHans de Goede 4060554c0a3aSHans de Goede psta->dot118021XPrivacy = _AES_; 4061554c0a3aSHans de Goede } 4062554c0a3aSHans de Goede else 4063554c0a3aSHans de Goede { 4064554c0a3aSHans de Goede DBG_871X("%s, set pairwise key, none\n", __func__); 4065554c0a3aSHans de Goede 4066554c0a3aSHans de Goede psta->dot118021XPrivacy = _NO_PRIVACY_; 4067554c0a3aSHans de Goede } 4068554c0a3aSHans de Goede 4069554c0a3aSHans de Goede rtw_ap_set_pairwise_key(padapter, psta); 4070554c0a3aSHans de Goede 4071554c0a3aSHans de Goede psta->ieee8021x_blocked = false; 4072554c0a3aSHans de Goede 4073554c0a3aSHans de Goede } 4074554c0a3aSHans de Goede else/* group key??? */ 4075554c0a3aSHans de Goede { 4076554c0a3aSHans de Goede if (strcmp(param->u.crypt.alg, "WEP") == 0) 4077554c0a3aSHans de Goede { 4078554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 4079554c0a3aSHans de Goede 4080554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _WEP40_; 4081554c0a3aSHans de Goede if (param->u.crypt.key_len == 13) 4082554c0a3aSHans de Goede { 4083554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _WEP104_; 4084554c0a3aSHans de Goede } 4085554c0a3aSHans de Goede } 4086554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "TKIP") == 0) 4087554c0a3aSHans de Goede { 4088554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _TKIP_; 4089554c0a3aSHans de Goede 4090554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 4091554c0a3aSHans de Goede 4092554c0a3aSHans de Goede /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ 4093554c0a3aSHans de Goede /* set mic key */ 4094554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8); 4095554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8); 4096554c0a3aSHans de Goede 4097554c0a3aSHans de Goede psecuritypriv->busetkipkey = true; 4098554c0a3aSHans de Goede 4099554c0a3aSHans de Goede } 4100554c0a3aSHans de Goede else if (strcmp(param->u.crypt.alg, "CCMP") == 0) 4101554c0a3aSHans de Goede { 4102554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _AES_; 4103554c0a3aSHans de Goede 4104554c0a3aSHans de Goede memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len)); 4105554c0a3aSHans de Goede } 4106554c0a3aSHans de Goede else 4107554c0a3aSHans de Goede { 4108554c0a3aSHans de Goede psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; 4109554c0a3aSHans de Goede } 4110554c0a3aSHans de Goede 4111554c0a3aSHans de Goede psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx; 4112554c0a3aSHans de Goede 4113554c0a3aSHans de Goede psecuritypriv->binstallGrpkey = true; 4114554c0a3aSHans de Goede 4115554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */ 4116554c0a3aSHans de Goede 4117554c0a3aSHans de Goede rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx); 4118554c0a3aSHans de Goede 4119554c0a3aSHans de Goede pbcmc_sta =rtw_get_bcmc_stainfo(padapter); 4120554c0a3aSHans de Goede if (pbcmc_sta) 4121554c0a3aSHans de Goede { 4122554c0a3aSHans de Goede pbcmc_sta->ieee8021x_blocked = false; 4123554c0a3aSHans de Goede pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */ 4124554c0a3aSHans de Goede } 4125554c0a3aSHans de Goede 4126554c0a3aSHans de Goede } 4127554c0a3aSHans de Goede 4128554c0a3aSHans de Goede } 4129554c0a3aSHans de Goede 4130554c0a3aSHans de Goede } 4131554c0a3aSHans de Goede 4132554c0a3aSHans de Goede exit: 4133554c0a3aSHans de Goede kfree((u8 *)pwep); 4134554c0a3aSHans de Goede 4135554c0a3aSHans de Goede return ret; 4136554c0a3aSHans de Goede 4137554c0a3aSHans de Goede } 4138554c0a3aSHans de Goede 4139554c0a3aSHans de Goede static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len) 4140554c0a3aSHans de Goede { 4141554c0a3aSHans de Goede int ret = 0; 4142554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4143554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4144554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4145554c0a3aSHans de Goede unsigned char *pbuf = param->u.bcn_ie.buf; 4146554c0a3aSHans de Goede 4147554c0a3aSHans de Goede 4148554c0a3aSHans de Goede DBG_871X("%s, len =%d\n", __func__, len); 4149554c0a3aSHans de Goede 4150554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4151554c0a3aSHans de Goede return -EINVAL; 4152554c0a3aSHans de Goede 4153554c0a3aSHans de Goede memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2); 4154554c0a3aSHans de Goede 4155554c0a3aSHans de Goede if ((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<= 0)) 4156554c0a3aSHans de Goede pstapriv->max_num_sta = NUM_STA; 4157554c0a3aSHans de Goede 4158554c0a3aSHans de Goede 4159554c0a3aSHans de Goede if (rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)/* 12 = param header, 2:no packed */ 4160554c0a3aSHans de Goede ret = 0; 4161554c0a3aSHans de Goede else 4162554c0a3aSHans de Goede ret = -EINVAL; 4163554c0a3aSHans de Goede 4164554c0a3aSHans de Goede 4165554c0a3aSHans de Goede return ret; 4166554c0a3aSHans de Goede 4167554c0a3aSHans de Goede } 4168554c0a3aSHans de Goede 4169554c0a3aSHans de Goede static int rtw_hostapd_sta_flush(struct net_device *dev) 4170554c0a3aSHans de Goede { 4171554c0a3aSHans de Goede /* _irqL irqL; */ 4172554c0a3aSHans de Goede /* struct list_head *phead, *plist; */ 4173554c0a3aSHans de Goede int ret = 0; 4174554c0a3aSHans de Goede /* struct sta_info *psta = NULL; */ 4175554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4176554c0a3aSHans de Goede /* struct sta_priv *pstapriv = &padapter->stapriv; */ 4177554c0a3aSHans de Goede 4178554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 4179554c0a3aSHans de Goede 4180554c0a3aSHans de Goede flush_all_cam_entry(padapter); /* clear CAM */ 4181554c0a3aSHans de Goede 4182554c0a3aSHans de Goede ret = rtw_sta_flush(padapter); 4183554c0a3aSHans de Goede 4184554c0a3aSHans de Goede return ret; 4185554c0a3aSHans de Goede 4186554c0a3aSHans de Goede } 4187554c0a3aSHans de Goede 4188554c0a3aSHans de Goede static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) 4189554c0a3aSHans de Goede { 4190554c0a3aSHans de Goede int ret = 0; 4191554c0a3aSHans de Goede struct sta_info *psta = NULL; 4192554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4193554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4194554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4195554c0a3aSHans de Goede 4196554c0a3aSHans de Goede DBG_871X("rtw_add_sta(aid =%d) =" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr)); 4197554c0a3aSHans de Goede 4198554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 4199554c0a3aSHans de Goede { 4200554c0a3aSHans de Goede return -EINVAL; 4201554c0a3aSHans de Goede } 4202554c0a3aSHans de Goede 4203554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 4204554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 4205554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 4206554c0a3aSHans de Goede { 4207554c0a3aSHans de Goede return -EINVAL; 4208554c0a3aSHans de Goede } 4209554c0a3aSHans de Goede 4210554c0a3aSHans de Goede /* 4211554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, param->sta_addr); 4212554c0a3aSHans de Goede if (psta) 4213554c0a3aSHans de Goede { 4214554c0a3aSHans de Goede DBG_871X("rtw_add_sta(), free has been added psta =%p\n", psta); 4215554c0a3aSHans de Goede spin_lock_bh(&(pstapriv->sta_hash_lock)); 4216554c0a3aSHans de Goede rtw_free_stainfo(padapter, psta); 4217554c0a3aSHans de Goede spin_unlock_bh(&(pstapriv->sta_hash_lock)); 4218554c0a3aSHans de Goede 4219554c0a3aSHans de Goede psta = NULL; 4220554c0a3aSHans de Goede } 4221554c0a3aSHans de Goede */ 4222554c0a3aSHans de Goede /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */ 4223554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, param->sta_addr); 4224554c0a3aSHans de Goede if (psta) 4225554c0a3aSHans de Goede { 4226554c0a3aSHans de Goede int flags = param->u.add_sta.flags; 4227554c0a3aSHans de Goede 4228554c0a3aSHans de Goede /* DBG_871X("rtw_add_sta(), init sta's variables, psta =%p\n", psta); */ 4229554c0a3aSHans de Goede 4230554c0a3aSHans de Goede psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */ 4231554c0a3aSHans de Goede 4232554c0a3aSHans de Goede memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16); 4233554c0a3aSHans de Goede 4234554c0a3aSHans de Goede 4235554c0a3aSHans de Goede /* check wmm cap. */ 4236554c0a3aSHans de Goede if (WLAN_STA_WME&flags) 4237554c0a3aSHans de Goede psta->qos_option = 1; 4238554c0a3aSHans de Goede else 4239554c0a3aSHans de Goede psta->qos_option = 0; 4240554c0a3aSHans de Goede 4241554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option == 0) 4242554c0a3aSHans de Goede psta->qos_option = 0; 4243554c0a3aSHans de Goede 4244554c0a3aSHans de Goede /* chec 802.11n ht cap. */ 4245554c0a3aSHans de Goede if (WLAN_STA_HT&flags) 4246554c0a3aSHans de Goede { 4247554c0a3aSHans de Goede psta->htpriv.ht_option = true; 4248554c0a3aSHans de Goede psta->qos_option = 1; 4249554c0a3aSHans de Goede memcpy((void*)&psta->htpriv.ht_cap, (void*)¶m->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); 4250554c0a3aSHans de Goede } 4251554c0a3aSHans de Goede else 4252554c0a3aSHans de Goede { 4253554c0a3aSHans de Goede psta->htpriv.ht_option = false; 4254554c0a3aSHans de Goede } 4255554c0a3aSHans de Goede 4256554c0a3aSHans de Goede if (pmlmepriv->htpriv.ht_option == false) 4257554c0a3aSHans de Goede psta->htpriv.ht_option = false; 4258554c0a3aSHans de Goede 4259554c0a3aSHans de Goede update_sta_info_apmode(padapter, psta); 4260554c0a3aSHans de Goede 4261554c0a3aSHans de Goede 4262554c0a3aSHans de Goede } 4263554c0a3aSHans de Goede else 4264554c0a3aSHans de Goede { 4265554c0a3aSHans de Goede ret = -ENOMEM; 4266554c0a3aSHans de Goede } 4267554c0a3aSHans de Goede 4268554c0a3aSHans de Goede return ret; 4269554c0a3aSHans de Goede 4270554c0a3aSHans de Goede } 4271554c0a3aSHans de Goede 4272554c0a3aSHans de Goede static int rtw_del_sta(struct net_device *dev, struct ieee_param *param) 4273554c0a3aSHans de Goede { 4274554c0a3aSHans de Goede int ret = 0; 4275554c0a3aSHans de Goede struct sta_info *psta = NULL; 4276554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4277554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4278554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4279554c0a3aSHans de Goede 4280554c0a3aSHans de Goede DBG_871X("rtw_del_sta =" MAC_FMT "\n", MAC_ARG(param->sta_addr)); 4281554c0a3aSHans de Goede 4282554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 4283554c0a3aSHans de Goede { 4284554c0a3aSHans de Goede return -EINVAL; 4285554c0a3aSHans de Goede } 4286554c0a3aSHans de Goede 4287554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 4288554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 4289554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 4290554c0a3aSHans de Goede { 4291554c0a3aSHans de Goede return -EINVAL; 4292554c0a3aSHans de Goede } 4293554c0a3aSHans de Goede 4294554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, param->sta_addr); 4295554c0a3aSHans de Goede if (psta) 4296554c0a3aSHans de Goede { 4297554c0a3aSHans de Goede u8 updated =false; 4298554c0a3aSHans de Goede 4299554c0a3aSHans de Goede /* DBG_871X("free psta =%p, aid =%d\n", psta, psta->aid); */ 4300554c0a3aSHans de Goede 4301554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 4302554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) ==false) 4303554c0a3aSHans de Goede { 4304554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 4305554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 4306554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); 4307554c0a3aSHans de Goede 4308554c0a3aSHans de Goede } 4309554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 4310554c0a3aSHans de Goede 4311554c0a3aSHans de Goede associated_clients_update(padapter, updated); 4312554c0a3aSHans de Goede 4313554c0a3aSHans de Goede psta = NULL; 4314554c0a3aSHans de Goede 4315554c0a3aSHans de Goede } 4316554c0a3aSHans de Goede else 4317554c0a3aSHans de Goede { 4318554c0a3aSHans de Goede DBG_871X("rtw_del_sta(), sta has already been removed or never been added\n"); 4319554c0a3aSHans de Goede 4320554c0a3aSHans de Goede /* ret = -1; */ 4321554c0a3aSHans de Goede } 4322554c0a3aSHans de Goede 4323554c0a3aSHans de Goede 4324554c0a3aSHans de Goede return ret; 4325554c0a3aSHans de Goede 4326554c0a3aSHans de Goede } 4327554c0a3aSHans de Goede 4328554c0a3aSHans de Goede static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len) 4329554c0a3aSHans de Goede { 4330554c0a3aSHans de Goede int ret = 0; 4331554c0a3aSHans de Goede struct sta_info *psta = NULL; 4332554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4333554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4334554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4335554c0a3aSHans de Goede struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param; 4336554c0a3aSHans de Goede struct sta_data *psta_data = (struct sta_data *)param_ex->data; 4337554c0a3aSHans de Goede 4338554c0a3aSHans de Goede DBG_871X("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr)); 4339554c0a3aSHans de Goede 4340554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 4341554c0a3aSHans de Goede { 4342554c0a3aSHans de Goede return -EINVAL; 4343554c0a3aSHans de Goede } 4344554c0a3aSHans de Goede 4345554c0a3aSHans de Goede if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff && 4346554c0a3aSHans de Goede param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff && 4347554c0a3aSHans de Goede param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) 4348554c0a3aSHans de Goede { 4349554c0a3aSHans de Goede return -EINVAL; 4350554c0a3aSHans de Goede } 4351554c0a3aSHans de Goede 4352554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr); 4353554c0a3aSHans de Goede if (psta) 4354554c0a3aSHans de Goede { 4355554c0a3aSHans de Goede psta_data->aid = (u16)psta->aid; 4356554c0a3aSHans de Goede psta_data->capability = psta->capability; 4357554c0a3aSHans de Goede psta_data->flags = psta->flags; 4358554c0a3aSHans de Goede 4359554c0a3aSHans de Goede /* 4360554c0a3aSHans de Goede nonerp_set : BIT(0) 4361554c0a3aSHans de Goede no_short_slot_time_set : BIT(1) 4362554c0a3aSHans de Goede no_short_preamble_set : BIT(2) 4363554c0a3aSHans de Goede no_ht_gf_set : BIT(3) 4364554c0a3aSHans de Goede no_ht_set : BIT(4) 4365554c0a3aSHans de Goede ht_20mhz_set : BIT(5) 4366554c0a3aSHans de Goede */ 4367554c0a3aSHans de Goede 4368554c0a3aSHans de Goede psta_data->sta_set =((psta->nonerp_set) | 4369554c0a3aSHans de Goede (psta->no_short_slot_time_set <<1) | 4370554c0a3aSHans de Goede (psta->no_short_preamble_set <<2) | 4371554c0a3aSHans de Goede (psta->no_ht_gf_set <<3) | 4372554c0a3aSHans de Goede (psta->no_ht_set <<4) | 4373554c0a3aSHans de Goede (psta->ht_20mhz_set <<5)); 4374554c0a3aSHans de Goede 4375554c0a3aSHans de Goede psta_data->tx_supp_rates_len = psta->bssratelen; 4376554c0a3aSHans de Goede memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen); 4377554c0a3aSHans de Goede memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); 4378554c0a3aSHans de Goede psta_data->rx_pkts = psta->sta_stats.rx_data_pkts; 4379554c0a3aSHans de Goede psta_data->rx_bytes = psta->sta_stats.rx_bytes; 4380554c0a3aSHans de Goede psta_data->rx_drops = psta->sta_stats.rx_drops; 4381554c0a3aSHans de Goede 4382554c0a3aSHans de Goede psta_data->tx_pkts = psta->sta_stats.tx_pkts; 4383554c0a3aSHans de Goede psta_data->tx_bytes = psta->sta_stats.tx_bytes; 4384554c0a3aSHans de Goede psta_data->tx_drops = psta->sta_stats.tx_drops; 4385554c0a3aSHans de Goede 4386554c0a3aSHans de Goede 4387554c0a3aSHans de Goede } 4388554c0a3aSHans de Goede else 4389554c0a3aSHans de Goede { 4390554c0a3aSHans de Goede ret = -1; 4391554c0a3aSHans de Goede } 4392554c0a3aSHans de Goede 4393554c0a3aSHans de Goede return ret; 4394554c0a3aSHans de Goede 4395554c0a3aSHans de Goede } 4396554c0a3aSHans de Goede 4397554c0a3aSHans de Goede static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param) 4398554c0a3aSHans de Goede { 4399554c0a3aSHans de Goede int ret = 0; 4400554c0a3aSHans de Goede struct sta_info *psta = NULL; 4401554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4402554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4403554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4404554c0a3aSHans de Goede 4405554c0a3aSHans de Goede DBG_871X("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr)); 4406554c0a3aSHans de Goede 4407554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 4408554c0a3aSHans de Goede { 4409554c0a3aSHans de Goede return -EINVAL; 4410554c0a3aSHans de Goede } 4411554c0a3aSHans de Goede 4412554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 4413554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 4414554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 4415554c0a3aSHans de Goede { 4416554c0a3aSHans de Goede return -EINVAL; 4417554c0a3aSHans de Goede } 4418554c0a3aSHans de Goede 4419554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, param->sta_addr); 4420554c0a3aSHans de Goede if (psta) 4421554c0a3aSHans de Goede { 4422554c0a3aSHans de Goede if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) 4423554c0a3aSHans de Goede { 4424554c0a3aSHans de Goede int wpa_ie_len; 4425554c0a3aSHans de Goede int copy_len; 4426554c0a3aSHans de Goede 4427554c0a3aSHans de Goede wpa_ie_len = psta->wpa_ie[1]; 4428554c0a3aSHans de Goede 4429554c0a3aSHans de Goede copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2); 4430554c0a3aSHans de Goede 4431554c0a3aSHans de Goede param->u.wpa_ie.len = copy_len; 4432554c0a3aSHans de Goede 4433554c0a3aSHans de Goede memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len); 4434554c0a3aSHans de Goede } 4435554c0a3aSHans de Goede else 4436554c0a3aSHans de Goede { 4437554c0a3aSHans de Goede /* ret = -1; */ 4438554c0a3aSHans de Goede DBG_871X("sta's wpa_ie is NONE\n"); 4439554c0a3aSHans de Goede } 4440554c0a3aSHans de Goede } 4441554c0a3aSHans de Goede else 4442554c0a3aSHans de Goede { 4443554c0a3aSHans de Goede ret = -1; 4444554c0a3aSHans de Goede } 4445554c0a3aSHans de Goede 4446554c0a3aSHans de Goede return ret; 4447554c0a3aSHans de Goede 4448554c0a3aSHans de Goede } 4449554c0a3aSHans de Goede 4450554c0a3aSHans de Goede static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len) 4451554c0a3aSHans de Goede { 4452554c0a3aSHans de Goede int ret = 0; 4453554c0a3aSHans de Goede unsigned char wps_oui[4]={0x0, 0x50, 0xf2, 0x04}; 4454554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4455554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4456554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 4457554c0a3aSHans de Goede int ie_len; 4458554c0a3aSHans de Goede 4459554c0a3aSHans de Goede DBG_871X("%s, len =%d\n", __func__, len); 4460554c0a3aSHans de Goede 4461554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4462554c0a3aSHans de Goede return -EINVAL; 4463554c0a3aSHans de Goede 4464554c0a3aSHans de Goede ie_len = len-12-2;/* 12 = param header, 2:no packed */ 4465554c0a3aSHans de Goede 4466554c0a3aSHans de Goede 4467554c0a3aSHans de Goede if (pmlmepriv->wps_beacon_ie) 4468554c0a3aSHans de Goede { 4469554c0a3aSHans de Goede kfree(pmlmepriv->wps_beacon_ie); 4470554c0a3aSHans de Goede pmlmepriv->wps_beacon_ie = NULL; 4471554c0a3aSHans de Goede } 4472554c0a3aSHans de Goede 4473554c0a3aSHans de Goede if (ie_len>0) 4474554c0a3aSHans de Goede { 4475554c0a3aSHans de Goede pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len); 4476554c0a3aSHans de Goede pmlmepriv->wps_beacon_ie_len = ie_len; 4477554c0a3aSHans de Goede if (pmlmepriv->wps_beacon_ie == NULL) { 4478554c0a3aSHans de Goede DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 4479554c0a3aSHans de Goede return -EINVAL; 4480554c0a3aSHans de Goede } 4481554c0a3aSHans de Goede 4482554c0a3aSHans de Goede memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len); 4483554c0a3aSHans de Goede 4484554c0a3aSHans de Goede update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true); 4485554c0a3aSHans de Goede 4486554c0a3aSHans de Goede pmlmeext->bstart_bss = true; 4487554c0a3aSHans de Goede 4488554c0a3aSHans de Goede } 4489554c0a3aSHans de Goede 4490554c0a3aSHans de Goede 4491554c0a3aSHans de Goede return ret; 4492554c0a3aSHans de Goede 4493554c0a3aSHans de Goede } 4494554c0a3aSHans de Goede 4495554c0a3aSHans de Goede static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len) 4496554c0a3aSHans de Goede { 4497554c0a3aSHans de Goede int ret = 0; 4498554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4499554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4500554c0a3aSHans de Goede int ie_len; 4501554c0a3aSHans de Goede 4502554c0a3aSHans de Goede DBG_871X("%s, len =%d\n", __func__, len); 4503554c0a3aSHans de Goede 4504554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4505554c0a3aSHans de Goede return -EINVAL; 4506554c0a3aSHans de Goede 4507554c0a3aSHans de Goede ie_len = len-12-2;/* 12 = param header, 2:no packed */ 4508554c0a3aSHans de Goede 4509554c0a3aSHans de Goede 4510554c0a3aSHans de Goede if (pmlmepriv->wps_probe_resp_ie) 4511554c0a3aSHans de Goede { 4512554c0a3aSHans de Goede kfree(pmlmepriv->wps_probe_resp_ie); 4513554c0a3aSHans de Goede pmlmepriv->wps_probe_resp_ie = NULL; 4514554c0a3aSHans de Goede } 4515554c0a3aSHans de Goede 4516554c0a3aSHans de Goede if (ie_len>0) 4517554c0a3aSHans de Goede { 4518554c0a3aSHans de Goede pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len); 4519554c0a3aSHans de Goede pmlmepriv->wps_probe_resp_ie_len = ie_len; 4520554c0a3aSHans de Goede if (pmlmepriv->wps_probe_resp_ie == NULL) { 4521554c0a3aSHans de Goede DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 4522554c0a3aSHans de Goede return -EINVAL; 4523554c0a3aSHans de Goede } 4524554c0a3aSHans de Goede memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len); 4525554c0a3aSHans de Goede } 4526554c0a3aSHans de Goede 4527554c0a3aSHans de Goede 4528554c0a3aSHans de Goede return ret; 4529554c0a3aSHans de Goede 4530554c0a3aSHans de Goede } 4531554c0a3aSHans de Goede 4532554c0a3aSHans de Goede static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len) 4533554c0a3aSHans de Goede { 4534554c0a3aSHans de Goede int ret = 0; 4535554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4536554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4537554c0a3aSHans de Goede int ie_len; 4538554c0a3aSHans de Goede 4539554c0a3aSHans de Goede DBG_871X("%s, len =%d\n", __func__, len); 4540554c0a3aSHans de Goede 4541554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4542554c0a3aSHans de Goede return -EINVAL; 4543554c0a3aSHans de Goede 4544554c0a3aSHans de Goede ie_len = len-12-2;/* 12 = param header, 2:no packed */ 4545554c0a3aSHans de Goede 4546554c0a3aSHans de Goede 4547554c0a3aSHans de Goede if (pmlmepriv->wps_assoc_resp_ie) 4548554c0a3aSHans de Goede { 4549554c0a3aSHans de Goede kfree(pmlmepriv->wps_assoc_resp_ie); 4550554c0a3aSHans de Goede pmlmepriv->wps_assoc_resp_ie = NULL; 4551554c0a3aSHans de Goede } 4552554c0a3aSHans de Goede 4553554c0a3aSHans de Goede if (ie_len>0) 4554554c0a3aSHans de Goede { 4555554c0a3aSHans de Goede pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len); 4556554c0a3aSHans de Goede pmlmepriv->wps_assoc_resp_ie_len = ie_len; 4557554c0a3aSHans de Goede if (pmlmepriv->wps_assoc_resp_ie == NULL) { 4558554c0a3aSHans de Goede DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 4559554c0a3aSHans de Goede return -EINVAL; 4560554c0a3aSHans de Goede } 4561554c0a3aSHans de Goede 4562554c0a3aSHans de Goede memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len); 4563554c0a3aSHans de Goede } 4564554c0a3aSHans de Goede 4565554c0a3aSHans de Goede 4566554c0a3aSHans de Goede return ret; 4567554c0a3aSHans de Goede 4568554c0a3aSHans de Goede } 4569554c0a3aSHans de Goede 4570554c0a3aSHans de Goede static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len) 4571554c0a3aSHans de Goede { 4572554c0a3aSHans de Goede int ret = 0; 4573554c0a3aSHans de Goede struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); 4574554c0a3aSHans de Goede struct mlme_priv *mlmepriv = &(adapter->mlmepriv); 4575554c0a3aSHans de Goede struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); 4576554c0a3aSHans de Goede struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info); 4577554c0a3aSHans de Goede int ie_len; 4578554c0a3aSHans de Goede u8 *ssid_ie; 4579554c0a3aSHans de Goede char ssid[NDIS_802_11_LENGTH_SSID + 1]; 4580554c0a3aSHans de Goede sint ssid_len; 4581554c0a3aSHans de Goede u8 ignore_broadcast_ssid; 4582554c0a3aSHans de Goede 4583554c0a3aSHans de Goede if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true) 4584554c0a3aSHans de Goede return -EPERM; 4585554c0a3aSHans de Goede 4586554c0a3aSHans de Goede if (param->u.bcn_ie.reserved[0] != 0xea) 4587554c0a3aSHans de Goede return -EINVAL; 4588554c0a3aSHans de Goede 4589554c0a3aSHans de Goede mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1]; 4590554c0a3aSHans de Goede 4591554c0a3aSHans de Goede ie_len = len-12-2;/* 12 = param header, 2:no packed */ 4592554c0a3aSHans de Goede ssid_ie = rtw_get_ie(param->u.bcn_ie.buf, WLAN_EID_SSID, &ssid_len, ie_len); 4593554c0a3aSHans de Goede 4594554c0a3aSHans de Goede if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) { 4595554c0a3aSHans de Goede struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network; 4596554c0a3aSHans de Goede struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network; 4597554c0a3aSHans de Goede 4598554c0a3aSHans de Goede memcpy(ssid, ssid_ie+2, ssid_len); 4599554c0a3aSHans de Goede ssid[ssid_len] = 0x0; 4600554c0a3aSHans de Goede 4601554c0a3aSHans de Goede if (0) 4602554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter), 4603554c0a3aSHans de Goede ssid, ssid_len, 4604554c0a3aSHans de Goede pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength, 4605554c0a3aSHans de Goede pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength); 4606554c0a3aSHans de Goede 4607554c0a3aSHans de Goede memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len); 4608554c0a3aSHans de Goede pbss_network->Ssid.SsidLength = ssid_len; 4609554c0a3aSHans de Goede memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len); 4610554c0a3aSHans de Goede pbss_network_ext->Ssid.SsidLength = ssid_len; 4611554c0a3aSHans de Goede 4612554c0a3aSHans de Goede if (0) 4613554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter), 4614554c0a3aSHans de Goede pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength, 4615554c0a3aSHans de Goede pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength); 4616554c0a3aSHans de Goede } 4617554c0a3aSHans de Goede 4618554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter), 4619554c0a3aSHans de Goede ignore_broadcast_ssid, ssid, ssid_len); 4620554c0a3aSHans de Goede 4621554c0a3aSHans de Goede return ret; 4622554c0a3aSHans de Goede } 4623554c0a3aSHans de Goede 4624554c0a3aSHans de Goede static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len) 4625554c0a3aSHans de Goede { 4626554c0a3aSHans de Goede int ret = 0; 4627554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4628554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4629554c0a3aSHans de Goede 4630554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4631554c0a3aSHans de Goede return -EINVAL; 4632554c0a3aSHans de Goede 4633554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 4634554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 4635554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 4636554c0a3aSHans de Goede { 4637554c0a3aSHans de Goede return -EINVAL; 4638554c0a3aSHans de Goede } 4639554c0a3aSHans de Goede 4640554c0a3aSHans de Goede ret = rtw_acl_remove_sta(padapter, param->sta_addr); 4641554c0a3aSHans de Goede 4642554c0a3aSHans de Goede return ret; 4643554c0a3aSHans de Goede 4644554c0a3aSHans de Goede } 4645554c0a3aSHans de Goede 4646554c0a3aSHans de Goede static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len) 4647554c0a3aSHans de Goede { 4648554c0a3aSHans de Goede int ret = 0; 4649554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4650554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4651554c0a3aSHans de Goede 4652554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4653554c0a3aSHans de Goede return -EINVAL; 4654554c0a3aSHans de Goede 4655554c0a3aSHans de Goede if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 4656554c0a3aSHans de Goede param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 4657554c0a3aSHans de Goede param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 4658554c0a3aSHans de Goede { 4659554c0a3aSHans de Goede return -EINVAL; 4660554c0a3aSHans de Goede } 4661554c0a3aSHans de Goede 4662554c0a3aSHans de Goede ret = rtw_acl_add_sta(padapter, param->sta_addr); 4663554c0a3aSHans de Goede 4664554c0a3aSHans de Goede return ret; 4665554c0a3aSHans de Goede 4666554c0a3aSHans de Goede } 4667554c0a3aSHans de Goede 4668554c0a3aSHans de Goede static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len) 4669554c0a3aSHans de Goede { 4670554c0a3aSHans de Goede int ret = 0; 4671554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4672554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4673554c0a3aSHans de Goede 4674554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 4675554c0a3aSHans de Goede return -EINVAL; 4676554c0a3aSHans de Goede 4677554c0a3aSHans de Goede rtw_set_macaddr_acl(padapter, param->u.mlme.command); 4678554c0a3aSHans de Goede 4679554c0a3aSHans de Goede return ret; 4680554c0a3aSHans de Goede } 4681554c0a3aSHans de Goede 4682554c0a3aSHans de Goede static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) 4683554c0a3aSHans de Goede { 4684554c0a3aSHans de Goede struct ieee_param *param; 4685554c0a3aSHans de Goede int ret = 0; 4686554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4687554c0a3aSHans de Goede 4688554c0a3aSHans de Goede /* DBG_871X("%s\n", __func__); */ 4689554c0a3aSHans de Goede 4690554c0a3aSHans de Goede /* 4691554c0a3aSHans de Goede * this function is expect to call in master mode, which allows no power saving 4692554c0a3aSHans de Goede * so, we just check hw_init_completed 4693554c0a3aSHans de Goede */ 4694554c0a3aSHans de Goede 4695554c0a3aSHans de Goede if (padapter->hw_init_completed ==false) { 4696554c0a3aSHans de Goede ret = -EPERM; 4697554c0a3aSHans de Goede goto out; 4698554c0a3aSHans de Goede } 4699554c0a3aSHans de Goede 4700554c0a3aSHans de Goede 4701554c0a3aSHans de Goede /* if (p->length < sizeof(struct ieee_param) || !p->pointer) { */ 4702554c0a3aSHans de Goede if (!p->pointer) { 4703554c0a3aSHans de Goede ret = -EINVAL; 4704554c0a3aSHans de Goede goto out; 4705554c0a3aSHans de Goede } 4706554c0a3aSHans de Goede 4707554c0a3aSHans de Goede param = (struct ieee_param *)rtw_malloc(p->length); 4708554c0a3aSHans de Goede if (param == NULL) 4709554c0a3aSHans de Goede { 4710554c0a3aSHans de Goede ret = -ENOMEM; 4711554c0a3aSHans de Goede goto out; 4712554c0a3aSHans de Goede } 4713554c0a3aSHans de Goede 4714554c0a3aSHans de Goede if (copy_from_user(param, p->pointer, p->length)) 4715554c0a3aSHans de Goede { 4716554c0a3aSHans de Goede kfree((u8 *)param); 4717554c0a3aSHans de Goede ret = -EFAULT; 4718554c0a3aSHans de Goede goto out; 4719554c0a3aSHans de Goede } 4720554c0a3aSHans de Goede 4721554c0a3aSHans de Goede /* DBG_871X("%s, cmd =%d\n", __func__, param->cmd); */ 4722554c0a3aSHans de Goede 4723554c0a3aSHans de Goede switch (param->cmd) 4724554c0a3aSHans de Goede { 4725554c0a3aSHans de Goede case RTL871X_HOSTAPD_FLUSH: 4726554c0a3aSHans de Goede 4727554c0a3aSHans de Goede ret = rtw_hostapd_sta_flush(dev); 4728554c0a3aSHans de Goede 4729554c0a3aSHans de Goede break; 4730554c0a3aSHans de Goede 4731554c0a3aSHans de Goede case RTL871X_HOSTAPD_ADD_STA: 4732554c0a3aSHans de Goede 4733554c0a3aSHans de Goede ret = rtw_add_sta(dev, param); 4734554c0a3aSHans de Goede 4735554c0a3aSHans de Goede break; 4736554c0a3aSHans de Goede 4737554c0a3aSHans de Goede case RTL871X_HOSTAPD_REMOVE_STA: 4738554c0a3aSHans de Goede 4739554c0a3aSHans de Goede ret = rtw_del_sta(dev, param); 4740554c0a3aSHans de Goede 4741554c0a3aSHans de Goede break; 4742554c0a3aSHans de Goede 4743554c0a3aSHans de Goede case RTL871X_HOSTAPD_SET_BEACON: 4744554c0a3aSHans de Goede 4745554c0a3aSHans de Goede ret = rtw_set_beacon(dev, param, p->length); 4746554c0a3aSHans de Goede 4747554c0a3aSHans de Goede break; 4748554c0a3aSHans de Goede 4749554c0a3aSHans de Goede case RTL871X_SET_ENCRYPTION: 4750554c0a3aSHans de Goede 4751554c0a3aSHans de Goede ret = rtw_set_encryption(dev, param, p->length); 4752554c0a3aSHans de Goede 4753554c0a3aSHans de Goede break; 4754554c0a3aSHans de Goede 4755554c0a3aSHans de Goede case RTL871X_HOSTAPD_GET_WPAIE_STA: 4756554c0a3aSHans de Goede 4757554c0a3aSHans de Goede ret = rtw_get_sta_wpaie(dev, param); 4758554c0a3aSHans de Goede 4759554c0a3aSHans de Goede break; 4760554c0a3aSHans de Goede 4761554c0a3aSHans de Goede case RTL871X_HOSTAPD_SET_WPS_BEACON: 4762554c0a3aSHans de Goede 4763554c0a3aSHans de Goede ret = rtw_set_wps_beacon(dev, param, p->length); 4764554c0a3aSHans de Goede 4765554c0a3aSHans de Goede break; 4766554c0a3aSHans de Goede 4767554c0a3aSHans de Goede case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP: 4768554c0a3aSHans de Goede 4769554c0a3aSHans de Goede ret = rtw_set_wps_probe_resp(dev, param, p->length); 4770554c0a3aSHans de Goede 4771554c0a3aSHans de Goede break; 4772554c0a3aSHans de Goede 4773554c0a3aSHans de Goede case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP: 4774554c0a3aSHans de Goede 4775554c0a3aSHans de Goede ret = rtw_set_wps_assoc_resp(dev, param, p->length); 4776554c0a3aSHans de Goede 4777554c0a3aSHans de Goede break; 4778554c0a3aSHans de Goede 4779554c0a3aSHans de Goede case RTL871X_HOSTAPD_SET_HIDDEN_SSID: 4780554c0a3aSHans de Goede 4781554c0a3aSHans de Goede ret = rtw_set_hidden_ssid(dev, param, p->length); 4782554c0a3aSHans de Goede 4783554c0a3aSHans de Goede break; 4784554c0a3aSHans de Goede 4785554c0a3aSHans de Goede case RTL871X_HOSTAPD_GET_INFO_STA: 4786554c0a3aSHans de Goede 4787554c0a3aSHans de Goede ret = rtw_ioctl_get_sta_data(dev, param, p->length); 4788554c0a3aSHans de Goede 4789554c0a3aSHans de Goede break; 4790554c0a3aSHans de Goede 4791554c0a3aSHans de Goede case RTL871X_HOSTAPD_SET_MACADDR_ACL: 4792554c0a3aSHans de Goede 4793554c0a3aSHans de Goede ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length); 4794554c0a3aSHans de Goede 4795554c0a3aSHans de Goede break; 4796554c0a3aSHans de Goede 4797554c0a3aSHans de Goede case RTL871X_HOSTAPD_ACL_ADD_STA: 4798554c0a3aSHans de Goede 4799554c0a3aSHans de Goede ret = rtw_ioctl_acl_add_sta(dev, param, p->length); 4800554c0a3aSHans de Goede 4801554c0a3aSHans de Goede break; 4802554c0a3aSHans de Goede 4803554c0a3aSHans de Goede case RTL871X_HOSTAPD_ACL_REMOVE_STA: 4804554c0a3aSHans de Goede 4805554c0a3aSHans de Goede ret = rtw_ioctl_acl_remove_sta(dev, param, p->length); 4806554c0a3aSHans de Goede 4807554c0a3aSHans de Goede break; 4808554c0a3aSHans de Goede 4809554c0a3aSHans de Goede default: 4810554c0a3aSHans de Goede DBG_871X("Unknown hostapd request: %d\n", param->cmd); 4811554c0a3aSHans de Goede ret = -EOPNOTSUPP; 4812554c0a3aSHans de Goede break; 4813554c0a3aSHans de Goede 4814554c0a3aSHans de Goede } 4815554c0a3aSHans de Goede 4816554c0a3aSHans de Goede if (ret == 0 && copy_to_user(p->pointer, param, p->length)) 4817554c0a3aSHans de Goede ret = -EFAULT; 4818554c0a3aSHans de Goede 4819554c0a3aSHans de Goede 4820554c0a3aSHans de Goede kfree((u8 *)param); 4821554c0a3aSHans de Goede 4822554c0a3aSHans de Goede out: 4823554c0a3aSHans de Goede 4824554c0a3aSHans de Goede return ret; 4825554c0a3aSHans de Goede 4826554c0a3aSHans de Goede } 4827554c0a3aSHans de Goede 4828554c0a3aSHans de Goede static int rtw_wx_set_priv(struct net_device *dev, 4829554c0a3aSHans de Goede struct iw_request_info *info, 4830554c0a3aSHans de Goede union iwreq_data *awrq, 4831554c0a3aSHans de Goede char *extra) 4832554c0a3aSHans de Goede { 4833554c0a3aSHans de Goede 4834f55a6d45SArnd Bergmann #ifdef DEBUG_RTW_WX_SET_PRIV 4835554c0a3aSHans de Goede char *ext_dbg; 4836554c0a3aSHans de Goede #endif 4837554c0a3aSHans de Goede 4838554c0a3aSHans de Goede int ret = 0; 4839554c0a3aSHans de Goede int len = 0; 4840554c0a3aSHans de Goede char *ext; 4841554c0a3aSHans de Goede 4842554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4843554c0a3aSHans de Goede struct iw_point *dwrq = (struct iw_point*)awrq; 4844554c0a3aSHans de Goede 4845554c0a3aSHans de Goede /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n")); */ 4846554c0a3aSHans de Goede if (dwrq->length == 0) 4847554c0a3aSHans de Goede return -EFAULT; 4848554c0a3aSHans de Goede 4849554c0a3aSHans de Goede len = dwrq->length; 4850554c0a3aSHans de Goede if (!(ext = vmalloc(len))) 4851554c0a3aSHans de Goede return -ENOMEM; 4852554c0a3aSHans de Goede 4853554c0a3aSHans de Goede if (copy_from_user(ext, dwrq->pointer, len)) { 4854554c0a3aSHans de Goede vfree(ext); 4855554c0a3aSHans de Goede return -EFAULT; 4856554c0a3aSHans de Goede } 4857554c0a3aSHans de Goede 4858554c0a3aSHans de Goede 4859554c0a3aSHans de Goede /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, */ 4860554c0a3aSHans de Goede /* ("rtw_wx_set_priv: %s req =%s\n", */ 4861554c0a3aSHans de Goede /* dev->name, ext)); */ 4862554c0a3aSHans de Goede 4863f55a6d45SArnd Bergmann #ifdef DEBUG_RTW_WX_SET_PRIV 4864554c0a3aSHans de Goede if (!(ext_dbg = vmalloc(len))) 4865554c0a3aSHans de Goede { 4866554c0a3aSHans de Goede vfree(ext, len); 4867554c0a3aSHans de Goede return -ENOMEM; 4868554c0a3aSHans de Goede } 4869554c0a3aSHans de Goede 4870554c0a3aSHans de Goede memcpy(ext_dbg, ext, len); 4871554c0a3aSHans de Goede #endif 4872554c0a3aSHans de Goede 4873554c0a3aSHans de Goede /* added for wps2.0 @20110524 */ 4874554c0a3aSHans de Goede if (dwrq->flags == 0x8766 && len > 8) 4875554c0a3aSHans de Goede { 4876554c0a3aSHans de Goede u32 cp_sz; 4877554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4878554c0a3aSHans de Goede u8 *probereq_wpsie = ext; 4879554c0a3aSHans de Goede int probereq_wpsie_len = len; 4880554c0a3aSHans de Goede u8 wps_oui[4]={0x0, 0x50, 0xf2, 0x04}; 4881554c0a3aSHans de Goede 4882554c0a3aSHans de Goede if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) && 4883554c0a3aSHans de Goede (!memcmp(&probereq_wpsie[2], wps_oui, 4))) 4884554c0a3aSHans de Goede { 4885554c0a3aSHans de Goede cp_sz = probereq_wpsie_len>MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN:probereq_wpsie_len; 4886554c0a3aSHans de Goede 4887554c0a3aSHans de Goede if (pmlmepriv->wps_probe_req_ie) 4888554c0a3aSHans de Goede { 4889554c0a3aSHans de Goede pmlmepriv->wps_probe_req_ie_len = 0; 4890554c0a3aSHans de Goede kfree(pmlmepriv->wps_probe_req_ie); 4891554c0a3aSHans de Goede pmlmepriv->wps_probe_req_ie = NULL; 4892554c0a3aSHans de Goede } 4893554c0a3aSHans de Goede 4894554c0a3aSHans de Goede pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz); 4895554c0a3aSHans de Goede if (pmlmepriv->wps_probe_req_ie == NULL) { 4896554c0a3aSHans de Goede printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 4897554c0a3aSHans de Goede ret = -EINVAL; 4898554c0a3aSHans de Goede goto FREE_EXT; 4899554c0a3aSHans de Goede 4900554c0a3aSHans de Goede } 4901554c0a3aSHans de Goede 4902554c0a3aSHans de Goede memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz); 4903554c0a3aSHans de Goede pmlmepriv->wps_probe_req_ie_len = cp_sz; 4904554c0a3aSHans de Goede 4905554c0a3aSHans de Goede } 4906554c0a3aSHans de Goede 4907554c0a3aSHans de Goede goto FREE_EXT; 4908554c0a3aSHans de Goede 4909554c0a3aSHans de Goede } 4910554c0a3aSHans de Goede 4911554c0a3aSHans de Goede if (len >= WEXT_CSCAN_HEADER_SIZE 4912554c0a3aSHans de Goede && !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) 4913554c0a3aSHans de Goede ) { 4914554c0a3aSHans de Goede ret = rtw_wx_set_scan(dev, info, awrq, ext); 4915554c0a3aSHans de Goede goto FREE_EXT; 4916554c0a3aSHans de Goede } 4917554c0a3aSHans de Goede 4918554c0a3aSHans de Goede FREE_EXT: 4919554c0a3aSHans de Goede 4920554c0a3aSHans de Goede vfree(ext); 4921f55a6d45SArnd Bergmann #ifdef DEBUG_RTW_WX_SET_PRIV 4922554c0a3aSHans de Goede vfree(ext_dbg); 4923554c0a3aSHans de Goede #endif 4924554c0a3aSHans de Goede 4925554c0a3aSHans de Goede /* DBG_871X("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret =%d\n", */ 4926554c0a3aSHans de Goede /* dev->name, ret); */ 4927554c0a3aSHans de Goede 4928554c0a3aSHans de Goede return ret; 4929554c0a3aSHans de Goede 4930554c0a3aSHans de Goede } 4931554c0a3aSHans de Goede 4932554c0a3aSHans de Goede static int rtw_pm_set(struct net_device *dev, 4933554c0a3aSHans de Goede struct iw_request_info *info, 4934554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 4935554c0a3aSHans de Goede { 4936554c0a3aSHans de Goede int ret = 0; 4937554c0a3aSHans de Goede unsigned mode = 0; 4938554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4939554c0a3aSHans de Goede 4940554c0a3aSHans de Goede DBG_871X("[%s] extra = %s\n", __func__, extra); 4941554c0a3aSHans de Goede 4942554c0a3aSHans de Goede if (!memcmp(extra, "lps =", 4)) 4943554c0a3aSHans de Goede { 4944554c0a3aSHans de Goede sscanf(extra+4, "%u", &mode); 4945554c0a3aSHans de Goede ret = rtw_pm_set_lps(padapter, mode); 4946554c0a3aSHans de Goede } 4947554c0a3aSHans de Goede else if (!memcmp(extra, "ips =", 4)) 4948554c0a3aSHans de Goede { 4949554c0a3aSHans de Goede sscanf(extra+4, "%u", &mode); 4950554c0a3aSHans de Goede ret = rtw_pm_set_ips(padapter, mode); 4951554c0a3aSHans de Goede } 4952554c0a3aSHans de Goede else { 4953554c0a3aSHans de Goede ret = -EINVAL; 4954554c0a3aSHans de Goede } 4955554c0a3aSHans de Goede 4956554c0a3aSHans de Goede return ret; 4957554c0a3aSHans de Goede } 4958554c0a3aSHans de Goede 4959554c0a3aSHans de Goede static int rtw_mp_efuse_get(struct net_device *dev, 4960554c0a3aSHans de Goede struct iw_request_info *info, 4961554c0a3aSHans de Goede union iwreq_data *wdata, char *extra) 4962554c0a3aSHans de Goede { 4963554c0a3aSHans de Goede int err = 0; 4964554c0a3aSHans de Goede return err; 4965554c0a3aSHans de Goede } 4966554c0a3aSHans de Goede 4967554c0a3aSHans de Goede static int rtw_mp_efuse_set(struct net_device *dev, 4968554c0a3aSHans de Goede struct iw_request_info *info, 4969554c0a3aSHans de Goede union iwreq_data *wdata, char *extra) 4970554c0a3aSHans de Goede { 4971554c0a3aSHans de Goede int err = 0; 4972554c0a3aSHans de Goede return err; 4973554c0a3aSHans de Goede } 4974554c0a3aSHans de Goede 4975554c0a3aSHans de Goede static int rtw_tdls(struct net_device *dev, 4976554c0a3aSHans de Goede struct iw_request_info *info, 4977554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 4978554c0a3aSHans de Goede { 4979554c0a3aSHans de Goede int ret = 0; 4980554c0a3aSHans de Goede return ret; 4981554c0a3aSHans de Goede } 4982554c0a3aSHans de Goede 4983554c0a3aSHans de Goede 4984554c0a3aSHans de Goede static int rtw_tdls_get(struct net_device *dev, 4985554c0a3aSHans de Goede struct iw_request_info *info, 4986554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 4987554c0a3aSHans de Goede { 4988554c0a3aSHans de Goede int ret = 0; 4989554c0a3aSHans de Goede return ret; 4990554c0a3aSHans de Goede } 4991554c0a3aSHans de Goede 4992554c0a3aSHans de Goede 4993554c0a3aSHans de Goede 4994554c0a3aSHans de Goede 4995554c0a3aSHans de Goede 4996554c0a3aSHans de Goede #ifdef CONFIG_INTEL_WIDI 4997554c0a3aSHans de Goede static int rtw_widi_set(struct net_device *dev, 4998554c0a3aSHans de Goede struct iw_request_info *info, 4999554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 5000554c0a3aSHans de Goede { 5001554c0a3aSHans de Goede int ret = 0; 5002554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5003554c0a3aSHans de Goede 5004554c0a3aSHans de Goede process_intel_widi_cmd(padapter, extra); 5005554c0a3aSHans de Goede 5006554c0a3aSHans de Goede return ret; 5007554c0a3aSHans de Goede } 5008554c0a3aSHans de Goede 5009554c0a3aSHans de Goede static int rtw_widi_set_probe_request(struct net_device *dev, 5010554c0a3aSHans de Goede struct iw_request_info *info, 5011554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 5012554c0a3aSHans de Goede { 5013554c0a3aSHans de Goede int ret = 0; 5014554c0a3aSHans de Goede u8 *pbuf = NULL; 5015554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5016554c0a3aSHans de Goede 5017554c0a3aSHans de Goede pbuf = rtw_malloc(sizeof(l2_msg_t)); 5018554c0a3aSHans de Goede if (pbuf) 5019554c0a3aSHans de Goede { 5020554c0a3aSHans de Goede if (copy_from_user(pbuf, wrqu->data.pointer, wrqu->data.length)) 5021554c0a3aSHans de Goede ret = -EFAULT; 5022554c0a3aSHans de Goede /* memcpy(pbuf, wrqu->data.pointer, wrqu->data.length); */ 5023554c0a3aSHans de Goede 5024554c0a3aSHans de Goede if (wrqu->data.flags == 0) 5025554c0a3aSHans de Goede intel_widi_wk_cmd(padapter, INTEL_WIDI_ISSUE_PROB_WK, pbuf, sizeof(l2_msg_t)); 5026554c0a3aSHans de Goede else if (wrqu->data.flags == 1) 5027554c0a3aSHans de Goede rtw_set_wfd_rds_sink_info(padapter, (l2_msg_t *)pbuf); 5028554c0a3aSHans de Goede } 5029554c0a3aSHans de Goede return ret; 5030554c0a3aSHans de Goede } 5031554c0a3aSHans de Goede #endif /* CONFIG_INTEL_WIDI */ 5032554c0a3aSHans de Goede 5033554c0a3aSHans de Goede static int rtw_test( 5034554c0a3aSHans de Goede struct net_device *dev, 5035554c0a3aSHans de Goede struct iw_request_info *info, 5036554c0a3aSHans de Goede union iwreq_data *wrqu, char *extra) 5037554c0a3aSHans de Goede { 5038554c0a3aSHans de Goede u32 len; 5039554c0a3aSHans de Goede u8 *pbuf, *pch; 5040554c0a3aSHans de Goede char *ptmp; 5041554c0a3aSHans de Goede u8 *delim = ","; 5042554c0a3aSHans de Goede struct adapter *padapter = rtw_netdev_priv(dev); 5043554c0a3aSHans de Goede 5044554c0a3aSHans de Goede 5045554c0a3aSHans de Goede DBG_871X("+%s\n", __func__); 5046554c0a3aSHans de Goede len = wrqu->data.length; 5047554c0a3aSHans de Goede 5048554c0a3aSHans de Goede pbuf = (u8 *)rtw_zmalloc(len); 5049554c0a3aSHans de Goede if (pbuf == NULL) { 5050554c0a3aSHans de Goede DBG_871X("%s: no memory!\n", __func__); 5051554c0a3aSHans de Goede return -ENOMEM; 5052554c0a3aSHans de Goede } 5053554c0a3aSHans de Goede 5054554c0a3aSHans de Goede if (copy_from_user(pbuf, wrqu->data.pointer, len)) { 5055554c0a3aSHans de Goede kfree(pbuf); 5056554c0a3aSHans de Goede DBG_871X("%s: copy from user fail!\n", __func__); 5057554c0a3aSHans de Goede return -EFAULT; 5058554c0a3aSHans de Goede } 5059554c0a3aSHans de Goede DBG_871X("%s: string =\"%s\"\n", __func__, pbuf); 5060554c0a3aSHans de Goede 5061554c0a3aSHans de Goede ptmp = (char*)pbuf; 5062554c0a3aSHans de Goede pch = strsep(&ptmp, delim); 5063554c0a3aSHans de Goede if ((pch == NULL) || (strlen(pch) == 0)) { 5064554c0a3aSHans de Goede kfree(pbuf); 5065554c0a3aSHans de Goede DBG_871X("%s: parameter error(level 1)!\n", __func__); 5066554c0a3aSHans de Goede return -EFAULT; 5067554c0a3aSHans de Goede } 5068554c0a3aSHans de Goede 5069554c0a3aSHans de Goede if (strcmp(pch, "bton") == 0) 5070554c0a3aSHans de Goede { 5071554c0a3aSHans de Goede rtw_btcoex_SetManualControl(padapter, false); 5072554c0a3aSHans de Goede } 5073554c0a3aSHans de Goede 5074554c0a3aSHans de Goede if (strcmp(pch, "btoff") == 0) 5075554c0a3aSHans de Goede { 5076554c0a3aSHans de Goede rtw_btcoex_SetManualControl(padapter, true); 5077554c0a3aSHans de Goede } 5078554c0a3aSHans de Goede 5079554c0a3aSHans de Goede if (strcmp(pch, "h2c") == 0) 5080554c0a3aSHans de Goede { 5081554c0a3aSHans de Goede u8 param[8]; 5082554c0a3aSHans de Goede u8 count = 0; 5083554c0a3aSHans de Goede u32 tmp; 5084554c0a3aSHans de Goede u8 i; 5085554c0a3aSHans de Goede u32 pos; 5086554c0a3aSHans de Goede s32 ret; 5087554c0a3aSHans de Goede 5088554c0a3aSHans de Goede 5089554c0a3aSHans de Goede do { 5090554c0a3aSHans de Goede pch = strsep(&ptmp, delim); 5091554c0a3aSHans de Goede if ((pch == NULL) || (strlen(pch) == 0)) 5092554c0a3aSHans de Goede break; 5093554c0a3aSHans de Goede 5094554c0a3aSHans de Goede sscanf(pch, "%x", &tmp); 5095554c0a3aSHans de Goede param[count++] = (u8)tmp; 5096554c0a3aSHans de Goede } while (count < 8); 5097554c0a3aSHans de Goede 5098554c0a3aSHans de Goede if (count == 0) { 5099554c0a3aSHans de Goede kfree(pbuf); 5100554c0a3aSHans de Goede DBG_871X("%s: parameter error(level 2)!\n", __func__); 5101554c0a3aSHans de Goede return -EFAULT; 5102554c0a3aSHans de Goede } 5103554c0a3aSHans de Goede 5104554c0a3aSHans de Goede ret = rtw_hal_fill_h2c_cmd(padapter, param[0], count-1, ¶m[1]); 5105554c0a3aSHans de Goede 5106554c0a3aSHans de Goede pos = sprintf(extra, "H2C ID = 0x%02x content =", param[0]); 5107554c0a3aSHans de Goede for (i = 1; i<count; i++) { 5108554c0a3aSHans de Goede pos += sprintf(extra+pos, "%02x,", param[i]); 5109554c0a3aSHans de Goede } 5110554c0a3aSHans de Goede extra[pos] = 0; 5111554c0a3aSHans de Goede pos--; 5112554c0a3aSHans de Goede pos += sprintf(extra+pos, " %s", ret == _FAIL?"FAIL":"OK"); 5113554c0a3aSHans de Goede 5114554c0a3aSHans de Goede wrqu->data.length = strlen(extra) + 1; 5115554c0a3aSHans de Goede } 5116554c0a3aSHans de Goede 5117554c0a3aSHans de Goede kfree(pbuf); 5118554c0a3aSHans de Goede return 0; 5119554c0a3aSHans de Goede } 5120554c0a3aSHans de Goede 5121554c0a3aSHans de Goede static iw_handler rtw_handlers[] = 5122554c0a3aSHans de Goede { 5123554c0a3aSHans de Goede NULL, /* SIOCSIWCOMMIT */ 5124554c0a3aSHans de Goede rtw_wx_get_name, /* SIOCGIWNAME */ 5125554c0a3aSHans de Goede dummy, /* SIOCSIWNWID */ 5126554c0a3aSHans de Goede dummy, /* SIOCGIWNWID */ 5127554c0a3aSHans de Goede rtw_wx_set_freq, /* SIOCSIWFREQ */ 5128554c0a3aSHans de Goede rtw_wx_get_freq, /* SIOCGIWFREQ */ 5129554c0a3aSHans de Goede rtw_wx_set_mode, /* SIOCSIWMODE */ 5130554c0a3aSHans de Goede rtw_wx_get_mode, /* SIOCGIWMODE */ 5131554c0a3aSHans de Goede dummy, /* SIOCSIWSENS */ 5132554c0a3aSHans de Goede rtw_wx_get_sens, /* SIOCGIWSENS */ 5133554c0a3aSHans de Goede NULL, /* SIOCSIWRANGE */ 5134554c0a3aSHans de Goede rtw_wx_get_range, /* SIOCGIWRANGE */ 5135554c0a3aSHans de Goede rtw_wx_set_priv, /* SIOCSIWPRIV */ 5136554c0a3aSHans de Goede NULL, /* SIOCGIWPRIV */ 5137554c0a3aSHans de Goede NULL, /* SIOCSIWSTATS */ 5138554c0a3aSHans de Goede NULL, /* SIOCGIWSTATS */ 5139554c0a3aSHans de Goede dummy, /* SIOCSIWSPY */ 5140554c0a3aSHans de Goede dummy, /* SIOCGIWSPY */ 5141554c0a3aSHans de Goede NULL, /* SIOCGIWTHRSPY */ 5142554c0a3aSHans de Goede NULL, /* SIOCWIWTHRSPY */ 5143554c0a3aSHans de Goede rtw_wx_set_wap, /* SIOCSIWAP */ 5144554c0a3aSHans de Goede rtw_wx_get_wap, /* SIOCGIWAP */ 5145554c0a3aSHans de Goede rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */ 5146554c0a3aSHans de Goede dummy, /* SIOCGIWAPLIST -- depricated */ 5147554c0a3aSHans de Goede rtw_wx_set_scan, /* SIOCSIWSCAN */ 5148554c0a3aSHans de Goede rtw_wx_get_scan, /* SIOCGIWSCAN */ 5149554c0a3aSHans de Goede rtw_wx_set_essid, /* SIOCSIWESSID */ 5150554c0a3aSHans de Goede rtw_wx_get_essid, /* SIOCGIWESSID */ 5151554c0a3aSHans de Goede dummy, /* SIOCSIWNICKN */ 5152554c0a3aSHans de Goede rtw_wx_get_nick, /* SIOCGIWNICKN */ 5153554c0a3aSHans de Goede NULL, /* -- hole -- */ 5154554c0a3aSHans de Goede NULL, /* -- hole -- */ 5155554c0a3aSHans de Goede rtw_wx_set_rate, /* SIOCSIWRATE */ 5156554c0a3aSHans de Goede rtw_wx_get_rate, /* SIOCGIWRATE */ 5157554c0a3aSHans de Goede rtw_wx_set_rts, /* SIOCSIWRTS */ 5158554c0a3aSHans de Goede rtw_wx_get_rts, /* SIOCGIWRTS */ 5159554c0a3aSHans de Goede rtw_wx_set_frag, /* SIOCSIWFRAG */ 5160554c0a3aSHans de Goede rtw_wx_get_frag, /* SIOCGIWFRAG */ 5161554c0a3aSHans de Goede dummy, /* SIOCSIWTXPOW */ 5162554c0a3aSHans de Goede dummy, /* SIOCGIWTXPOW */ 5163554c0a3aSHans de Goede dummy, /* SIOCSIWRETRY */ 5164554c0a3aSHans de Goede rtw_wx_get_retry, /* SIOCGIWRETRY */ 5165554c0a3aSHans de Goede rtw_wx_set_enc, /* SIOCSIWENCODE */ 5166554c0a3aSHans de Goede rtw_wx_get_enc, /* SIOCGIWENCODE */ 5167554c0a3aSHans de Goede dummy, /* SIOCSIWPOWER */ 5168554c0a3aSHans de Goede rtw_wx_get_power, /* SIOCGIWPOWER */ 5169554c0a3aSHans de Goede NULL, /*---hole---*/ 5170554c0a3aSHans de Goede NULL, /*---hole---*/ 5171554c0a3aSHans de Goede rtw_wx_set_gen_ie, /* SIOCSIWGENIE */ 5172554c0a3aSHans de Goede NULL, /* SIOCGWGENIE */ 5173554c0a3aSHans de Goede rtw_wx_set_auth, /* SIOCSIWAUTH */ 5174554c0a3aSHans de Goede NULL, /* SIOCGIWAUTH */ 5175554c0a3aSHans de Goede rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 5176554c0a3aSHans de Goede NULL, /* SIOCGIWENCODEEXT */ 5177554c0a3aSHans de Goede rtw_wx_set_pmkid, /* SIOCSIWPMKSA */ 5178554c0a3aSHans de Goede NULL, /*---hole---*/ 5179554c0a3aSHans de Goede }; 5180554c0a3aSHans de Goede 5181554c0a3aSHans de Goede static const struct iw_priv_args rtw_private_args[] = { 5182554c0a3aSHans de Goede { 5183554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x0, 5184554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write" 5185554c0a3aSHans de Goede }, 5186554c0a3aSHans de Goede { 5187554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x1, 5188554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 0x7FF, 5189554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read" 5190554c0a3aSHans de Goede }, 5191554c0a3aSHans de Goede { 5192554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext" 5193554c0a3aSHans de Goede }, 5194554c0a3aSHans de Goede { 5195554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl" 5196554c0a3aSHans de Goede }, 5197554c0a3aSHans de Goede { 5198554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x4, 5199554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" 5200554c0a3aSHans de Goede }, 5201554c0a3aSHans de Goede { 5202554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x5, 5203554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid" 5204554c0a3aSHans de Goede }, 5205554c0a3aSHans de Goede { 5206554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x6, 5207554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start" 5208554c0a3aSHans de Goede }, 5209554c0a3aSHans de Goede /* for PLATFORM_MT53XX */ 5210554c0a3aSHans de Goede { 5211554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x7, 5212554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity" 5213554c0a3aSHans de Goede }, 5214554c0a3aSHans de Goede { 5215554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x8, 5216554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie" 5217554c0a3aSHans de Goede }, 5218554c0a3aSHans de Goede { 5219554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x9, 5220554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie" 5221554c0a3aSHans de Goede }, 5222554c0a3aSHans de Goede 5223554c0a3aSHans de Goede /* for RTK_DMP_PLATFORM */ 5224554c0a3aSHans de Goede { 5225554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0xA, 5226554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan" 5227554c0a3aSHans de Goede }, 5228554c0a3aSHans de Goede 5229554c0a3aSHans de Goede { 5230554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0xB, 5231554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg" 5232554c0a3aSHans de Goede }, 5233554c0a3aSHans de Goede { 5234554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0xC, 5235554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw" 5236554c0a3aSHans de Goede }, 5237554c0a3aSHans de Goede { 5238554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0xD, 5239554c0a3aSHans de Goede IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr" 5240554c0a3aSHans de Goede }, 5241554c0a3aSHans de Goede { 5242554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x10, 5243554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set" 5244554c0a3aSHans de Goede }, 5245554c0a3aSHans de Goede { 5246554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x11, 5247554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "p2p_get" 5248554c0a3aSHans de Goede }, 5249554c0a3aSHans de Goede { 5250554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL" 5251554c0a3aSHans de Goede }, 5252554c0a3aSHans de Goede { 5253554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x13, 5254554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2" 5255554c0a3aSHans de Goede }, 5256554c0a3aSHans de Goede { 5257554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x14, 5258554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 64, 0, "tdls" 5259554c0a3aSHans de Goede }, 5260554c0a3aSHans de Goede { 5261554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x15, 5262554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "tdls_get" 5263554c0a3aSHans de Goede }, 5264554c0a3aSHans de Goede { 5265554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x16, 5266554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 64, 0, "pm_set" 5267554c0a3aSHans de Goede }, 5268554c0a3aSHans de Goede 5269554c0a3aSHans de Goede {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"}, 5270554c0a3aSHans de Goede {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"}, 5271554c0a3aSHans de Goede {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"}, 5272554c0a3aSHans de Goede { 5273554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x1D, 5274554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test" 5275554c0a3aSHans de Goede }, 5276554c0a3aSHans de Goede 5277554c0a3aSHans de Goede #ifdef CONFIG_INTEL_WIDI 5278554c0a3aSHans de Goede { 5279554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x1E, 5280554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 1024, 0, "widi_set" 5281554c0a3aSHans de Goede }, 5282554c0a3aSHans de Goede { 5283554c0a3aSHans de Goede SIOCIWFIRSTPRIV + 0x1F, 5284554c0a3aSHans de Goede IW_PRIV_TYPE_CHAR | 128, 0, "widi_prob_req" 5285554c0a3aSHans de Goede }, 5286554c0a3aSHans de Goede #endif /* CONFIG_INTEL_WIDI */ 5287554c0a3aSHans de Goede 5288554c0a3aSHans de Goede #ifdef CONFIG_WOWLAN 5289554c0a3aSHans de Goede { MP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" }, /* set */ 5290554c0a3aSHans de Goede #endif 5291554c0a3aSHans de Goede #ifdef CONFIG_AP_WOWLAN 5292554c0a3aSHans de Goede { MP_AP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, /* set */ 5293554c0a3aSHans de Goede #endif 5294554c0a3aSHans de Goede }; 5295554c0a3aSHans de Goede 5296554c0a3aSHans de Goede static iw_handler rtw_private_handler[] = 5297554c0a3aSHans de Goede { 5298554c0a3aSHans de Goede rtw_wx_write32, /* 0x00 */ 5299554c0a3aSHans de Goede rtw_wx_read32, /* 0x01 */ 5300554c0a3aSHans de Goede rtw_drvext_hdl, /* 0x02 */ 5301554c0a3aSHans de Goede rtw_mp_ioctl_hdl, /* 0x03 */ 5302554c0a3aSHans de Goede 5303554c0a3aSHans de Goede /* for MM DTV platform */ 5304554c0a3aSHans de Goede rtw_get_ap_info, /* 0x04 */ 5305554c0a3aSHans de Goede 5306554c0a3aSHans de Goede rtw_set_pid, /* 0x05 */ 5307554c0a3aSHans de Goede rtw_wps_start, /* 0x06 */ 5308554c0a3aSHans de Goede 5309554c0a3aSHans de Goede /* for PLATFORM_MT53XX */ 5310554c0a3aSHans de Goede rtw_wx_get_sensitivity, /* 0x07 */ 5311554c0a3aSHans de Goede rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */ 5312554c0a3aSHans de Goede rtw_wx_set_mtk_wps_ie, /* 0x09 */ 5313554c0a3aSHans de Goede 5314554c0a3aSHans de Goede /* for RTK_DMP_PLATFORM */ 5315554c0a3aSHans de Goede /* Set Channel depend on the country code */ 5316554c0a3aSHans de Goede rtw_wx_set_channel_plan, /* 0x0A */ 5317554c0a3aSHans de Goede 5318554c0a3aSHans de Goede rtw_dbg_port, /* 0x0B */ 5319554c0a3aSHans de Goede rtw_wx_write_rf, /* 0x0C */ 5320554c0a3aSHans de Goede rtw_wx_read_rf, /* 0x0D */ 5321554c0a3aSHans de Goede rtw_wx_priv_null, /* 0x0E */ 5322554c0a3aSHans de Goede rtw_wx_priv_null, /* 0x0F */ 5323554c0a3aSHans de Goede rtw_p2p_set, /* 0x10 */ 5324554c0a3aSHans de Goede rtw_p2p_get, /* 0x11 */ 5325554c0a3aSHans de Goede NULL, /* 0x12 */ 5326554c0a3aSHans de Goede rtw_p2p_get2, /* 0x13 */ 5327554c0a3aSHans de Goede 5328554c0a3aSHans de Goede rtw_tdls, /* 0x14 */ 5329554c0a3aSHans de Goede rtw_tdls_get, /* 0x15 */ 5330554c0a3aSHans de Goede 5331554c0a3aSHans de Goede rtw_pm_set, /* 0x16 */ 5332554c0a3aSHans de Goede rtw_wx_priv_null, /* 0x17 */ 5333554c0a3aSHans de Goede rtw_rereg_nd_name, /* 0x18 */ 5334554c0a3aSHans de Goede rtw_wx_priv_null, /* 0x19 */ 5335554c0a3aSHans de Goede rtw_mp_efuse_set, /* 0x1A */ 5336554c0a3aSHans de Goede rtw_mp_efuse_get, /* 0x1B */ 5337554c0a3aSHans de Goede NULL, /* 0x1C is reserved for hostapd */ 5338554c0a3aSHans de Goede rtw_test, /* 0x1D */ 5339554c0a3aSHans de Goede #ifdef CONFIG_INTEL_WIDI 5340554c0a3aSHans de Goede rtw_widi_set, /* 0x1E */ 5341554c0a3aSHans de Goede rtw_widi_set_probe_request, /* 0x1F */ 5342554c0a3aSHans de Goede #endif /* CONFIG_INTEL_WIDI */ 5343554c0a3aSHans de Goede }; 5344554c0a3aSHans de Goede 5345554c0a3aSHans de Goede static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev) 5346554c0a3aSHans de Goede { 5347554c0a3aSHans de Goede struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5348554c0a3aSHans de Goede struct iw_statistics *piwstats =&padapter->iwstats; 5349554c0a3aSHans de Goede int tmp_level = 0; 5350554c0a3aSHans de Goede int tmp_qual = 0; 5351554c0a3aSHans de Goede int tmp_noise = 0; 5352554c0a3aSHans de Goede 5353554c0a3aSHans de Goede if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) 5354554c0a3aSHans de Goede { 5355554c0a3aSHans de Goede piwstats->qual.qual = 0; 5356554c0a3aSHans de Goede piwstats->qual.level = 0; 5357554c0a3aSHans de Goede piwstats->qual.noise = 0; 5358554c0a3aSHans de Goede /* DBG_871X("No link level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); */ 5359554c0a3aSHans de Goede } 5360554c0a3aSHans de Goede else { 5361554c0a3aSHans de Goede #ifdef CONFIG_SIGNAL_DISPLAY_DBM 5362554c0a3aSHans de Goede tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength); 5363554c0a3aSHans de Goede #else 5364554c0a3aSHans de Goede #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING 5365554c0a3aSHans de Goede { 5366554c0a3aSHans de Goede /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */ 5367554c0a3aSHans de Goede 5368554c0a3aSHans de Goede struct hal_com_data *pHal = GET_HAL_DATA(padapter); 5369554c0a3aSHans de Goede 5370554c0a3aSHans de Goede tmp_level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, padapter->recvpriv.signal_strength); 5371554c0a3aSHans de Goede } 5372554c0a3aSHans de Goede #else 5373554c0a3aSHans de Goede tmp_level = padapter->recvpriv.signal_strength; 5374554c0a3aSHans de Goede #endif 5375554c0a3aSHans de Goede #endif 5376554c0a3aSHans de Goede 5377554c0a3aSHans de Goede tmp_qual = padapter->recvpriv.signal_qual; 5378554c0a3aSHans de Goede #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) 5379554c0a3aSHans de Goede if (rtw_linked_check(padapter)) { 5380554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5381554c0a3aSHans de Goede struct noise_info info; 5382554c0a3aSHans de Goede info.bPauseDIG = true; 5383554c0a3aSHans de Goede info.IGIValue = 0x1e; 5384554c0a3aSHans de Goede info.max_time = 100;/* ms */ 5385554c0a3aSHans de Goede info.chan = pmlmeext->cur_channel ;/* rtw_get_oper_ch(padapter); */ 5386554c0a3aSHans de Goede rtw_ps_deny(padapter, PS_DENY_IOCTL); 5387554c0a3aSHans de Goede LeaveAllPowerSaveModeDirect(padapter); 5388554c0a3aSHans de Goede 5389554c0a3aSHans de Goede rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&info, false); 5390554c0a3aSHans de Goede /* ODM_InbandNoise_Monitor(podmpriv, true, 0x20, 100); */ 5391554c0a3aSHans de Goede rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL); 5392554c0a3aSHans de Goede rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(info.chan), &(padapter->recvpriv.noise)); 5393554c0a3aSHans de Goede DBG_871X("chan:%d, noise_level:%d\n", info.chan, padapter->recvpriv.noise); 5394554c0a3aSHans de Goede } 5395554c0a3aSHans de Goede #endif 5396554c0a3aSHans de Goede tmp_noise = padapter->recvpriv.noise; 5397554c0a3aSHans de Goede DBG_871X("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise, padapter->recvpriv.rssi); 5398554c0a3aSHans de Goede 5399554c0a3aSHans de Goede piwstats->qual.level = tmp_level; 5400554c0a3aSHans de Goede piwstats->qual.qual = tmp_qual; 5401554c0a3aSHans de Goede piwstats->qual.noise = tmp_noise; 5402554c0a3aSHans de Goede } 5403554c0a3aSHans de Goede piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* IW_QUAL_DBM; */ 5404554c0a3aSHans de Goede 5405554c0a3aSHans de Goede #ifdef CONFIG_SIGNAL_DISPLAY_DBM 5406554c0a3aSHans de Goede piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM; 5407554c0a3aSHans de Goede #endif 5408554c0a3aSHans de Goede 5409554c0a3aSHans de Goede return &padapter->iwstats; 5410554c0a3aSHans de Goede } 5411554c0a3aSHans de Goede 5412554c0a3aSHans de Goede struct iw_handler_def rtw_handlers_def = 5413554c0a3aSHans de Goede { 5414554c0a3aSHans de Goede .standard = rtw_handlers, 5415554c0a3aSHans de Goede .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler), 5416554c0a3aSHans de Goede #if defined(CONFIG_WEXT_PRIV) 5417554c0a3aSHans de Goede .private = rtw_private_handler, 5418554c0a3aSHans de Goede .private_args = (struct iw_priv_args *)rtw_private_args, 5419554c0a3aSHans de Goede .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler), 5420554c0a3aSHans de Goede .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args), 5421554c0a3aSHans de Goede #endif 5422554c0a3aSHans de Goede .get_wireless_stats = rtw_get_wireless_stats, 5423554c0a3aSHans de Goede }; 5424554c0a3aSHans de Goede 5425554c0a3aSHans de Goede /* copy from net/wireless/wext.c start */ 5426554c0a3aSHans de Goede /* ---------------------------------------------------------------- */ 5427554c0a3aSHans de Goede /* 5428554c0a3aSHans de Goede * Calculate size of private arguments 5429554c0a3aSHans de Goede */ 5430554c0a3aSHans de Goede static const char iw_priv_type_size[] = { 5431554c0a3aSHans de Goede 0, /* IW_PRIV_TYPE_NONE */ 5432554c0a3aSHans de Goede 1, /* IW_PRIV_TYPE_BYTE */ 5433554c0a3aSHans de Goede 1, /* IW_PRIV_TYPE_CHAR */ 5434554c0a3aSHans de Goede 0, /* Not defined */ 5435554c0a3aSHans de Goede sizeof(__u32), /* IW_PRIV_TYPE_INT */ 5436554c0a3aSHans de Goede sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ 5437554c0a3aSHans de Goede sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 5438554c0a3aSHans de Goede 0, /* Not defined */ 5439554c0a3aSHans de Goede }; 5440554c0a3aSHans de Goede 5441554c0a3aSHans de Goede static int get_priv_size(__u16 args) 5442554c0a3aSHans de Goede { 5443554c0a3aSHans de Goede int num = args & IW_PRIV_SIZE_MASK; 5444554c0a3aSHans de Goede int type = (args & IW_PRIV_TYPE_MASK) >> 12; 5445554c0a3aSHans de Goede 5446554c0a3aSHans de Goede return num * iw_priv_type_size[type]; 5447554c0a3aSHans de Goede } 5448554c0a3aSHans de Goede /* copy from net/wireless/wext.c end */ 5449554c0a3aSHans de Goede 5450554c0a3aSHans de Goede static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data) 5451554c0a3aSHans de Goede { 5452554c0a3aSHans de Goede int err = 0; 5453554c0a3aSHans de Goede u8 *input = NULL; 5454554c0a3aSHans de Goede u32 input_len = 0; 5455554c0a3aSHans de Goede const char delim[] = " "; 5456554c0a3aSHans de Goede u8 *output = NULL; 5457554c0a3aSHans de Goede u32 output_len = 0; 5458554c0a3aSHans de Goede u32 count = 0; 5459554c0a3aSHans de Goede u8 *buffer = NULL; 5460554c0a3aSHans de Goede u32 buffer_len = 0; 5461554c0a3aSHans de Goede char *ptr = NULL; 5462554c0a3aSHans de Goede u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */ 5463554c0a3aSHans de Goede u32 cmdlen; 5464554c0a3aSHans de Goede s32 len; 5465554c0a3aSHans de Goede u8 *extra = NULL; 5466554c0a3aSHans de Goede u32 extra_size = 0; 5467554c0a3aSHans de Goede 5468554c0a3aSHans de Goede s32 k; 5469554c0a3aSHans de Goede const iw_handler *priv; /* Private ioctl */ 5470554c0a3aSHans de Goede const struct iw_priv_args *priv_args; /* Private ioctl description */ 5471554c0a3aSHans de Goede u32 num_priv; /* Number of ioctl */ 5472554c0a3aSHans de Goede u32 num_priv_args; /* Number of descriptions */ 5473554c0a3aSHans de Goede iw_handler handler; 5474554c0a3aSHans de Goede int temp; 5475554c0a3aSHans de Goede int subcmd = 0; /* sub-ioctl index */ 5476554c0a3aSHans de Goede int offset = 0; /* Space for sub-ioctl index */ 5477554c0a3aSHans de Goede 5478554c0a3aSHans de Goede union iwreq_data wdata; 5479554c0a3aSHans de Goede 5480554c0a3aSHans de Goede 5481554c0a3aSHans de Goede memcpy(&wdata, wrq_data, sizeof(wdata)); 5482554c0a3aSHans de Goede 5483554c0a3aSHans de Goede input_len = 2048; 5484554c0a3aSHans de Goede input = rtw_zmalloc(input_len); 5485554c0a3aSHans de Goede if (NULL == input) 5486554c0a3aSHans de Goede return -ENOMEM; 5487554c0a3aSHans de Goede if (copy_from_user(input, wdata.data.pointer, input_len)) { 5488554c0a3aSHans de Goede err = -EFAULT; 5489554c0a3aSHans de Goede goto exit; 5490554c0a3aSHans de Goede } 5491554c0a3aSHans de Goede ptr = input; 5492554c0a3aSHans de Goede len = strlen(input); 5493554c0a3aSHans de Goede 5494554c0a3aSHans de Goede sscanf(ptr, "%16s", cmdname); 5495554c0a3aSHans de Goede cmdlen = strlen(cmdname); 5496554c0a3aSHans de Goede DBG_8192C("%s: cmd =%s\n", __func__, cmdname); 5497554c0a3aSHans de Goede 5498554c0a3aSHans de Goede /* skip command string */ 5499554c0a3aSHans de Goede if (cmdlen > 0) 5500554c0a3aSHans de Goede cmdlen += 1; /* skip one space */ 5501554c0a3aSHans de Goede ptr += cmdlen; 5502554c0a3aSHans de Goede len -= cmdlen; 5503554c0a3aSHans de Goede DBG_8192C("%s: parameters =%s\n", __func__, ptr); 5504554c0a3aSHans de Goede 5505554c0a3aSHans de Goede priv = rtw_private_handler; 5506554c0a3aSHans de Goede priv_args = rtw_private_args; 5507554c0a3aSHans de Goede num_priv = sizeof(rtw_private_handler) / sizeof(iw_handler); 5508554c0a3aSHans de Goede num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args); 5509554c0a3aSHans de Goede 5510554c0a3aSHans de Goede if (num_priv_args == 0) { 5511554c0a3aSHans de Goede err = -EOPNOTSUPP; 5512554c0a3aSHans de Goede goto exit; 5513554c0a3aSHans de Goede } 5514554c0a3aSHans de Goede 5515554c0a3aSHans de Goede /* Search the correct ioctl */ 5516554c0a3aSHans de Goede k = -1; 5517554c0a3aSHans de Goede while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname)); 5518554c0a3aSHans de Goede 5519554c0a3aSHans de Goede /* If not found... */ 5520554c0a3aSHans de Goede if (k == num_priv_args) { 5521554c0a3aSHans de Goede err = -EOPNOTSUPP; 5522554c0a3aSHans de Goede goto exit; 5523554c0a3aSHans de Goede } 5524554c0a3aSHans de Goede 5525554c0a3aSHans de Goede /* Watch out for sub-ioctls ! */ 5526554c0a3aSHans de Goede if (priv_args[k].cmd < SIOCDEVPRIVATE) 5527554c0a3aSHans de Goede { 5528554c0a3aSHans de Goede int j = -1; 5529554c0a3aSHans de Goede 5530554c0a3aSHans de Goede /* Find the matching *real* ioctl */ 5531554c0a3aSHans de Goede while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') || 5532554c0a3aSHans de Goede (priv_args[j].set_args != priv_args[k].set_args) || 5533554c0a3aSHans de Goede (priv_args[j].get_args != priv_args[k].get_args))); 5534554c0a3aSHans de Goede 5535554c0a3aSHans de Goede /* If not found... */ 5536554c0a3aSHans de Goede if (j == num_priv_args) { 5537554c0a3aSHans de Goede err = -EINVAL; 5538554c0a3aSHans de Goede goto exit; 5539554c0a3aSHans de Goede } 5540554c0a3aSHans de Goede 5541554c0a3aSHans de Goede /* Save sub-ioctl number */ 5542554c0a3aSHans de Goede subcmd = priv_args[k].cmd; 5543554c0a3aSHans de Goede /* Reserve one int (simplify alignment issues) */ 5544554c0a3aSHans de Goede offset = sizeof(__u32); 5545554c0a3aSHans de Goede /* Use real ioctl definition from now on */ 5546554c0a3aSHans de Goede k = j; 5547554c0a3aSHans de Goede } 5548554c0a3aSHans de Goede 5549554c0a3aSHans de Goede buffer = rtw_zmalloc(4096); 5550554c0a3aSHans de Goede if (NULL == buffer) { 5551554c0a3aSHans de Goede err = -ENOMEM; 5552554c0a3aSHans de Goede goto exit; 5553554c0a3aSHans de Goede } 5554554c0a3aSHans de Goede 5555554c0a3aSHans de Goede /* If we have to set some data */ 5556554c0a3aSHans de Goede if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) && 5557554c0a3aSHans de Goede (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 5558554c0a3aSHans de Goede { 5559554c0a3aSHans de Goede u8 *str; 5560554c0a3aSHans de Goede 5561554c0a3aSHans de Goede switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) 5562554c0a3aSHans de Goede { 5563554c0a3aSHans de Goede case IW_PRIV_TYPE_BYTE: 5564554c0a3aSHans de Goede /* Fetch args */ 5565554c0a3aSHans de Goede count = 0; 5566554c0a3aSHans de Goede do { 5567554c0a3aSHans de Goede str = strsep(&ptr, delim); 5568554c0a3aSHans de Goede if (NULL == str) break; 5569554c0a3aSHans de Goede sscanf(str, "%i", &temp); 5570554c0a3aSHans de Goede buffer[count++] = (u8)temp; 5571554c0a3aSHans de Goede } while (1); 5572554c0a3aSHans de Goede buffer_len = count; 5573554c0a3aSHans de Goede 5574554c0a3aSHans de Goede /* Number of args to fetch */ 5575554c0a3aSHans de Goede wdata.data.length = count; 5576554c0a3aSHans de Goede if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 5577554c0a3aSHans de Goede wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK; 5578554c0a3aSHans de Goede 5579554c0a3aSHans de Goede break; 5580554c0a3aSHans de Goede 5581554c0a3aSHans de Goede case IW_PRIV_TYPE_INT: 5582554c0a3aSHans de Goede /* Fetch args */ 5583554c0a3aSHans de Goede count = 0; 5584554c0a3aSHans de Goede do { 5585554c0a3aSHans de Goede str = strsep(&ptr, delim); 5586554c0a3aSHans de Goede if (NULL == str) break; 5587554c0a3aSHans de Goede sscanf(str, "%i", &temp); 5588554c0a3aSHans de Goede ((s32*)buffer)[count++] = (s32)temp; 5589554c0a3aSHans de Goede } while (1); 5590554c0a3aSHans de Goede buffer_len = count * sizeof(s32); 5591554c0a3aSHans de Goede 5592554c0a3aSHans de Goede /* Number of args to fetch */ 5593554c0a3aSHans de Goede wdata.data.length = count; 5594554c0a3aSHans de Goede if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 5595554c0a3aSHans de Goede wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK; 5596554c0a3aSHans de Goede 5597554c0a3aSHans de Goede break; 5598554c0a3aSHans de Goede 5599554c0a3aSHans de Goede case IW_PRIV_TYPE_CHAR: 5600554c0a3aSHans de Goede if (len > 0) 5601554c0a3aSHans de Goede { 5602554c0a3aSHans de Goede /* Size of the string to fetch */ 5603554c0a3aSHans de Goede wdata.data.length = len; 5604554c0a3aSHans de Goede if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 5605554c0a3aSHans de Goede wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK; 5606554c0a3aSHans de Goede 5607554c0a3aSHans de Goede /* Fetch string */ 5608554c0a3aSHans de Goede memcpy(buffer, ptr, wdata.data.length); 5609554c0a3aSHans de Goede } 5610554c0a3aSHans de Goede else 5611554c0a3aSHans de Goede { 5612554c0a3aSHans de Goede wdata.data.length = 1; 5613554c0a3aSHans de Goede buffer[0] = '\0'; 5614554c0a3aSHans de Goede } 5615554c0a3aSHans de Goede buffer_len = wdata.data.length; 5616554c0a3aSHans de Goede break; 5617554c0a3aSHans de Goede 5618554c0a3aSHans de Goede default: 5619554c0a3aSHans de Goede DBG_8192C("%s: Not yet implemented...\n", __func__); 5620554c0a3aSHans de Goede err = -1; 5621554c0a3aSHans de Goede goto exit; 5622554c0a3aSHans de Goede } 5623554c0a3aSHans de Goede 5624554c0a3aSHans de Goede if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) && 5625554c0a3aSHans de Goede (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) 5626554c0a3aSHans de Goede { 5627554c0a3aSHans de Goede DBG_8192C("%s: The command %s needs exactly %d argument(s)...\n", 5628554c0a3aSHans de Goede __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK); 5629554c0a3aSHans de Goede err = -EINVAL; 5630554c0a3aSHans de Goede goto exit; 5631554c0a3aSHans de Goede } 5632554c0a3aSHans de Goede } /* if args to set */ 5633554c0a3aSHans de Goede else 5634554c0a3aSHans de Goede { 5635554c0a3aSHans de Goede wdata.data.length = 0L; 5636554c0a3aSHans de Goede } 5637554c0a3aSHans de Goede 5638554c0a3aSHans de Goede /* Those two tests are important. They define how the driver 5639554c0a3aSHans de Goede * will have to handle the data */ 5640554c0a3aSHans de Goede if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) && 5641554c0a3aSHans de Goede ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) 5642554c0a3aSHans de Goede { 5643554c0a3aSHans de Goede /* First case : all SET args fit within wrq */ 5644554c0a3aSHans de Goede if (offset) 5645554c0a3aSHans de Goede wdata.mode = subcmd; 5646554c0a3aSHans de Goede memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset); 5647554c0a3aSHans de Goede } 5648554c0a3aSHans de Goede else 5649554c0a3aSHans de Goede { 5650554c0a3aSHans de Goede if ((priv_args[k].set_args == 0) && 5651554c0a3aSHans de Goede (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) && 5652554c0a3aSHans de Goede (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) 5653554c0a3aSHans de Goede { 5654554c0a3aSHans de Goede /* Second case : no SET args, GET args fit within wrq */ 5655554c0a3aSHans de Goede if (offset) 5656554c0a3aSHans de Goede wdata.mode = subcmd; 5657554c0a3aSHans de Goede } 5658554c0a3aSHans de Goede else 5659554c0a3aSHans de Goede { 5660554c0a3aSHans de Goede /* Third case : args won't fit in wrq, or variable number of args */ 5661554c0a3aSHans de Goede if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) { 5662554c0a3aSHans de Goede err = -EFAULT; 5663554c0a3aSHans de Goede goto exit; 5664554c0a3aSHans de Goede } 5665554c0a3aSHans de Goede wdata.data.flags = subcmd; 5666554c0a3aSHans de Goede } 5667554c0a3aSHans de Goede } 5668554c0a3aSHans de Goede 5669554c0a3aSHans de Goede kfree(input); 5670554c0a3aSHans de Goede input = NULL; 5671554c0a3aSHans de Goede 5672554c0a3aSHans de Goede extra_size = 0; 5673554c0a3aSHans de Goede if (IW_IS_SET(priv_args[k].cmd)) 5674554c0a3aSHans de Goede { 5675554c0a3aSHans de Goede /* Size of set arguments */ 5676554c0a3aSHans de Goede extra_size = get_priv_size(priv_args[k].set_args); 5677554c0a3aSHans de Goede 5678554c0a3aSHans de Goede /* Does it fits in iwr ? */ 5679554c0a3aSHans de Goede if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) && 5680554c0a3aSHans de Goede ((extra_size + offset) <= IFNAMSIZ)) 5681554c0a3aSHans de Goede extra_size = 0; 5682554c0a3aSHans de Goede } else { 5683554c0a3aSHans de Goede /* Size of get arguments */ 5684554c0a3aSHans de Goede extra_size = get_priv_size(priv_args[k].get_args); 5685554c0a3aSHans de Goede 5686554c0a3aSHans de Goede /* Does it fits in iwr ? */ 5687554c0a3aSHans de Goede if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) && 5688554c0a3aSHans de Goede (extra_size <= IFNAMSIZ)) 5689554c0a3aSHans de Goede extra_size = 0; 5690554c0a3aSHans de Goede } 5691554c0a3aSHans de Goede 5692554c0a3aSHans de Goede if (extra_size == 0) { 5693554c0a3aSHans de Goede extra = (u8 *)&wdata; 5694554c0a3aSHans de Goede kfree(buffer); 5695554c0a3aSHans de Goede buffer = NULL; 5696554c0a3aSHans de Goede } else 5697554c0a3aSHans de Goede extra = buffer; 5698554c0a3aSHans de Goede 5699554c0a3aSHans de Goede handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV]; 5700554c0a3aSHans de Goede err = handler(dev, NULL, &wdata, extra); 5701554c0a3aSHans de Goede 5702554c0a3aSHans de Goede /* If we have to get some data */ 5703554c0a3aSHans de Goede if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) && 5704554c0a3aSHans de Goede (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) 5705554c0a3aSHans de Goede { 5706554c0a3aSHans de Goede int j; 5707554c0a3aSHans de Goede int n = 0; /* number of args */ 5708554c0a3aSHans de Goede u8 str[20] = {0}; 5709554c0a3aSHans de Goede 5710554c0a3aSHans de Goede /* Check where is the returned data */ 5711554c0a3aSHans de Goede if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) && 5712554c0a3aSHans de Goede (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) 5713554c0a3aSHans de Goede n = priv_args[k].get_args & IW_PRIV_SIZE_MASK; 5714554c0a3aSHans de Goede else 5715554c0a3aSHans de Goede n = wdata.data.length; 5716554c0a3aSHans de Goede 5717554c0a3aSHans de Goede output = rtw_zmalloc(4096); 5718554c0a3aSHans de Goede if (NULL == output) { 5719554c0a3aSHans de Goede err = -ENOMEM; 5720554c0a3aSHans de Goede goto exit; 5721554c0a3aSHans de Goede } 5722554c0a3aSHans de Goede 5723554c0a3aSHans de Goede switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) 5724554c0a3aSHans de Goede { 5725554c0a3aSHans de Goede case IW_PRIV_TYPE_BYTE: 5726554c0a3aSHans de Goede /* Display args */ 5727554c0a3aSHans de Goede for (j = 0; j < n; j++) 5728554c0a3aSHans de Goede { 5729554c0a3aSHans de Goede sprintf(str, "%d ", extra[j]); 5730554c0a3aSHans de Goede len = strlen(str); 5731554c0a3aSHans de Goede output_len = strlen(output); 5732554c0a3aSHans de Goede if ((output_len + len + 1) > 4096) { 5733554c0a3aSHans de Goede err = -E2BIG; 5734554c0a3aSHans de Goede goto exit; 5735554c0a3aSHans de Goede } 5736554c0a3aSHans de Goede memcpy(output+output_len, str, len); 5737554c0a3aSHans de Goede } 5738554c0a3aSHans de Goede break; 5739554c0a3aSHans de Goede 5740554c0a3aSHans de Goede case IW_PRIV_TYPE_INT: 5741554c0a3aSHans de Goede /* Display args */ 5742554c0a3aSHans de Goede for (j = 0; j < n; j++) 5743554c0a3aSHans de Goede { 5744554c0a3aSHans de Goede sprintf(str, "%d ", ((__s32*)extra)[j]); 5745554c0a3aSHans de Goede len = strlen(str); 5746554c0a3aSHans de Goede output_len = strlen(output); 5747554c0a3aSHans de Goede if ((output_len + len + 1) > 4096) { 5748554c0a3aSHans de Goede err = -E2BIG; 5749554c0a3aSHans de Goede goto exit; 5750554c0a3aSHans de Goede } 5751554c0a3aSHans de Goede memcpy(output+output_len, str, len); 5752554c0a3aSHans de Goede } 5753554c0a3aSHans de Goede break; 5754554c0a3aSHans de Goede 5755554c0a3aSHans de Goede case IW_PRIV_TYPE_CHAR: 5756554c0a3aSHans de Goede /* Display args */ 5757554c0a3aSHans de Goede memcpy(output, extra, n); 5758554c0a3aSHans de Goede break; 5759554c0a3aSHans de Goede 5760554c0a3aSHans de Goede default: 5761554c0a3aSHans de Goede DBG_8192C("%s: Not yet implemented...\n", __func__); 5762554c0a3aSHans de Goede err = -1; 5763554c0a3aSHans de Goede goto exit; 5764554c0a3aSHans de Goede } 5765554c0a3aSHans de Goede 5766554c0a3aSHans de Goede output_len = strlen(output) + 1; 5767554c0a3aSHans de Goede wrq_data->data.length = output_len; 5768554c0a3aSHans de Goede if (copy_to_user(wrq_data->data.pointer, output, output_len)) { 5769554c0a3aSHans de Goede err = -EFAULT; 5770554c0a3aSHans de Goede goto exit; 5771554c0a3aSHans de Goede } 5772554c0a3aSHans de Goede } /* if args to set */ 5773554c0a3aSHans de Goede else 5774554c0a3aSHans de Goede { 5775554c0a3aSHans de Goede wrq_data->data.length = 0; 5776554c0a3aSHans de Goede } 5777554c0a3aSHans de Goede 5778554c0a3aSHans de Goede exit: 5779554c0a3aSHans de Goede kfree(input); 5780554c0a3aSHans de Goede kfree(buffer); 5781554c0a3aSHans de Goede kfree(output); 5782554c0a3aSHans de Goede 5783554c0a3aSHans de Goede return err; 5784554c0a3aSHans de Goede } 5785554c0a3aSHans de Goede 5786554c0a3aSHans de Goede int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 5787554c0a3aSHans de Goede { 5788554c0a3aSHans de Goede struct iwreq *wrq = (struct iwreq *)rq; 5789554c0a3aSHans de Goede int ret = 0; 5790554c0a3aSHans de Goede 5791554c0a3aSHans de Goede switch (cmd) 5792554c0a3aSHans de Goede { 5793554c0a3aSHans de Goede case RTL_IOCTL_WPA_SUPPLICANT: 5794554c0a3aSHans de Goede ret = wpa_supplicant_ioctl(dev, &wrq->u.data); 5795554c0a3aSHans de Goede break; 5796554c0a3aSHans de Goede case RTL_IOCTL_HOSTAPD: 5797554c0a3aSHans de Goede ret = rtw_hostapd_ioctl(dev, &wrq->u.data); 5798554c0a3aSHans de Goede break; 5799554c0a3aSHans de Goede case SIOCDEVPRIVATE: 5800554c0a3aSHans de Goede ret = rtw_ioctl_wext_private(dev, &wrq->u); 5801554c0a3aSHans de Goede break; 5802554c0a3aSHans de Goede default: 5803554c0a3aSHans de Goede ret = -EOPNOTSUPP; 5804554c0a3aSHans de Goede break; 5805554c0a3aSHans de Goede } 5806554c0a3aSHans de Goede 5807554c0a3aSHans de Goede return ret; 5808554c0a3aSHans de Goede } 5809