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