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