ioctl_linux.c revision 2397c6e0927675d983b34a03401affdb64818d07
1/****************************************************************************** 2 * 3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 17 * 18 * 19 ******************************************************************************/ 20#define _IOCTL_LINUX_C_ 21 22#include <osdep_service.h> 23#include <drv_types.h> 24#include <wlan_bssdef.h> 25#include <rtw_debug.h> 26#include <wifi.h> 27#include <rtw_mlme.h> 28#include <rtw_mlme_ext.h> 29#include <rtw_ioctl.h> 30#include <rtw_ioctl_set.h> 31#include <rtw_mp_ioctl.h> 32#include <usb_ops.h> 33#include <rtw_version.h> 34#include <rtl8188e_hal.h> 35 36#include <rtw_mp.h> 37#include <rtw_iol.h> 38 39#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30) 40 41#define SCAN_ITEM_SIZE 768 42#define MAX_CUSTOM_LEN 64 43#define RATE_COUNT 4 44 45/* combo scan */ 46#define WEXT_CSCAN_AMOUNT 9 47#define WEXT_CSCAN_BUF_LEN 360 48#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" 49#define WEXT_CSCAN_HEADER_SIZE 12 50#define WEXT_CSCAN_SSID_SECTION 'S' 51#define WEXT_CSCAN_CHANNEL_SECTION 'C' 52#define WEXT_CSCAN_NPROBE_SECTION 'N' 53#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' 54#define WEXT_CSCAN_PASV_DWELL_SECTION 'P' 55#define WEXT_CSCAN_HOME_DWELL_SECTION 'H' 56#define WEXT_CSCAN_TYPE_SECTION 'T' 57 58static struct mp_ioctl_handler mp_ioctl_hdl[] = { 59/*0*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_start_test_hdl, OID_RT_PRO_START_TEST) 60 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_stop_test_hdl, OID_RT_PRO_STOP_TEST) 61 62 GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_read_register_hdl, OID_RT_PRO_READ_REGISTER) 63 GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_write_register_hdl, OID_RT_PRO_WRITE_REGISTER) 64 GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_read_bb_reg_hdl, OID_RT_PRO_READ_BB_REG) 65/*5*/ GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_write_bb_reg_hdl, OID_RT_PRO_WRITE_BB_REG) 66 GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_read_rf_reg_hdl, OID_RT_PRO_RF_READ_REGISTRY) 67 GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_write_rf_reg_hdl, OID_RT_PRO_RF_WRITE_REGISTRY) 68 69 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl, OID_RT_PRO_SET_CHANNEL_DIRECT_CALL) 70 GEN_HANDLER(sizeof(struct txpower_param), rtl8188eu_oid_rt_pro_set_tx_power_control_hdl, OID_RT_PRO_SET_TX_POWER_CONTROL) 71/*10*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_data_rate_hdl, OID_RT_PRO_SET_DATA_RATE) 72 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_bandwidth_hdl, OID_RT_SET_BANDWIDTH) 73 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_antenna_bb_hdl, OID_RT_PRO_SET_ANTENNA_BB) 74 75 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_continuous_tx_hdl, OID_RT_PRO_SET_CONTINUOUS_TX) 76 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl, OID_RT_PRO_SET_SINGLE_CARRIER_TX) 77/*15*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl, OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX) 78 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl, OID_RT_PRO_SET_SINGLE_TONE_TX) 79 80 EXT_MP_IOCTL_HANDLER(0, xmit_packet, 0) 81 82 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_rx_packet_type_hdl, OID_RT_SET_RX_PACKET_TYPE) 83 GEN_HANDLER(0, rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl, OID_RT_RESET_PHY_RX_PACKET_COUNT) 84/*20*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl, OID_RT_GET_PHY_RX_PACKET_RECEIVED) 85 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl, OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR) 86 87 GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0) 88 GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0) 89 GEN_HANDLER(sizeof(struct efuse_access_struct), rtl8188eu_oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE) 90/*25*/ GEN_HANDLER(0, rtl8188eu_oid_rt_pro_efuse_map_hdl, OID_RT_PRO_EFUSE_MAP) 91 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_max_size_hdl, OID_RT_GET_EFUSE_MAX_SIZE) 92 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_current_size_hdl, OID_RT_GET_EFUSE_CURRENT_SIZE) 93 94 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_thermal_meter_hdl, OID_RT_PRO_GET_THERMAL_METER) 95 GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_pro_set_power_tracking_hdl, OID_RT_PRO_SET_POWER_TRACKING) 96/*30*/ GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_set_power_down_hdl, OID_RT_SET_POWER_DOWN) 97/*31*/ GEN_HANDLER(0, rtl8188eu_oid_rt_pro_trigger_gpio_hdl, 0) 98}; 99 100static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000, 101 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 102 48000000, 54000000}; 103 104static const char * const iw_operation_mode[] = { 105 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", 106 "Secondary", "Monitor" 107}; 108 109static int hex2num_i(char c) 110{ 111 if (c >= '0' && c <= '9') 112 return c - '0'; 113 if (c >= 'a' && c <= 'f') 114 return c - 'a' + 10; 115 if (c >= 'A' && c <= 'F') 116 return c - 'A' + 10; 117 return -1; 118} 119 120/** 121 * hwaddr_aton - Convert ASCII string to MAC address 122 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 123 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 124 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 125 */ 126static int hwaddr_aton_i(const char *txt, u8 *addr) 127{ 128 int i; 129 130 for (i = 0; i < 6; i++) { 131 int a, b; 132 133 a = hex2num_i(*txt++); 134 if (a < 0) 135 return -1; 136 b = hex2num_i(*txt++); 137 if (b < 0) 138 return -1; 139 *addr++ = (a << 4) | b; 140 if (i < 5 && *txt++ != ':') 141 return -1; 142 } 143 144 return 0; 145} 146 147void indicate_wx_scan_complete_event(struct adapter *padapter) 148{ 149 union iwreq_data wrqu; 150 151 _rtw_memset(&wrqu, 0, sizeof(union iwreq_data)); 152 wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL); 153} 154 155void rtw_indicate_wx_assoc_event(struct adapter *padapter) 156{ 157 union iwreq_data wrqu; 158 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 159 160 _rtw_memset(&wrqu, 0, sizeof(union iwreq_data)); 161 162 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 163 164 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN); 165 166 DBG_88E_LEVEL(_drv_always_, "assoc success\n"); 167 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); 168} 169 170void rtw_indicate_wx_disassoc_event(struct adapter *padapter) 171{ 172 union iwreq_data wrqu; 173 174 _rtw_memset(&wrqu, 0, sizeof(union iwreq_data)); 175 176 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 177 _rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 178 179 DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n"); 180 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); 181} 182 183static char *translate_scan(struct adapter *padapter, 184 struct iw_request_info *info, 185 struct wlan_network *pnetwork, 186 char *start, char *stop) 187{ 188 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 189 struct iw_event iwe; 190 u16 cap; 191 __le16 le_tmp; 192 u32 ht_ielen = 0; 193 char custom[MAX_CUSTOM_LEN]; 194 char *p; 195 u16 max_rate = 0, rate, ht_cap = false; 196 u32 i = 0; 197 u8 bw_40MHz = 0, short_GI = 0; 198 u16 mcs_rate = 0; 199 u8 ss, sq; 200#ifdef CONFIG_88EU_P2P 201 struct wifidirect_info *pwdinfo = &padapter->wdinfo; 202 203 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { 204 u32 blnGotP2PIE = false; 205 206 /* User is doing the P2P device discovery */ 207 /* The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */ 208 /* If not, the driver should ignore this AP and go to the next AP. */ 209 210 /* Verifying the SSID */ 211 if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) { 212 u32 p2pielen = 0; 213 214 if (pnetwork->network.Reserved[0] == 2) {/* Probe Request */ 215 /* Verifying the P2P IE */ 216 if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen)) 217 blnGotP2PIE = true; 218 } else {/* Beacon or Probe Respones */ 219 /* Verifying the P2P IE */ 220 if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen)) 221 blnGotP2PIE = true; 222 } 223 } 224 225 if (!blnGotP2PIE) 226 return start; 227 } 228#endif /* CONFIG_88EU_P2P */ 229 230 /* AP MAC address */ 231 iwe.cmd = SIOCGIWAP; 232 iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 233 234 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN); 235 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); 236 237 /* Add the ESSID */ 238 iwe.cmd = SIOCGIWESSID; 239 iwe.u.data.flags = 1; 240 iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32); 241 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); 242 243 /* parsing HT_CAP_IE */ 244 p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12); 245 246 if (p && ht_ielen > 0) { 247 struct rtw_ieee80211_ht_cap *pht_capie; 248 ht_cap = true; 249 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); 250 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); 251 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; 252 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; 253 } 254 255 /* Add the protocol name */ 256 iwe.cmd = SIOCGIWNAME; 257 if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) { 258 if (ht_cap) 259 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn"); 260 else 261 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b"); 262 } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) { 263 if (ht_cap) 264 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn"); 265 else 266 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg"); 267 } else { 268 if (pnetwork->network.Configuration.DSConfig > 14) { 269 if (ht_cap) 270 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an"); 271 else 272 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a"); 273 } else { 274 if (ht_cap) 275 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn"); 276 else 277 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g"); 278 } 279 } 280 281 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); 282 283 /* Add mode */ 284 iwe.cmd = SIOCGIWMODE; 285 memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2); 286 287 cap = le16_to_cpu(le_tmp); 288 289 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) { 290 if (cap & WLAN_CAPABILITY_BSS) 291 iwe.u.mode = IW_MODE_MASTER; 292 else 293 iwe.u.mode = IW_MODE_ADHOC; 294 295 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); 296 } 297 298 if (pnetwork->network.Configuration.DSConfig < 1) 299 pnetwork->network.Configuration.DSConfig = 1; 300 301 /* Add frequency/channel */ 302 iwe.cmd = SIOCGIWFREQ; 303 iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000; 304 iwe.u.freq.e = 1; 305 iwe.u.freq.i = pnetwork->network.Configuration.DSConfig; 306 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); 307 308 /* Add encryption capability */ 309 iwe.cmd = SIOCGIWENCODE; 310 if (cap & WLAN_CAPABILITY_PRIVACY) 311 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 312 else 313 iwe.u.data.flags = IW_ENCODE_DISABLED; 314 iwe.u.data.length = 0; 315 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); 316 317 /*Add basic and extended rates */ 318 max_rate = 0; 319 p = custom; 320 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); 321 while (pnetwork->network.SupportedRates[i] != 0) { 322 rate = pnetwork->network.SupportedRates[i]&0x7F; 323 if (rate > max_rate) 324 max_rate = rate; 325 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), 326 "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); 327 i++; 328 } 329 330 if (ht_cap) { 331 if (mcs_rate&0x8000)/* MCS15 */ 332 max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130); 333 else if (mcs_rate&0x0080)/* MCS7 */ 334 ; 335 else/* default MCS7 */ 336 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65); 337 338 max_rate = max_rate*2;/* Mbps/2; */ 339 } 340 341 iwe.cmd = SIOCGIWRATE; 342 iwe.u.bitrate.fixed = 0; 343 iwe.u.bitrate.disabled = 0; 344 iwe.u.bitrate.value = max_rate * 500000; 345 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN); 346 347 /* parsing WPA/WPA2 IE */ 348 { 349 u8 buf[MAX_WPA_IE_LEN]; 350 u8 wpa_ie[255], rsn_ie[255]; 351 u16 wpa_len = 0, rsn_len = 0; 352 u8 *p; 353 354 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len); 355 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid)); 356 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); 357 358 if (wpa_len > 0) { 359 p = buf; 360 _rtw_memset(buf, 0, MAX_WPA_IE_LEN); 361 p += sprintf(p, "wpa_ie ="); 362 for (i = 0; i < wpa_len; i++) 363 p += sprintf(p, "%02x", wpa_ie[i]); 364 365 _rtw_memset(&iwe, 0, sizeof(iwe)); 366 iwe.cmd = IWEVCUSTOM; 367 iwe.u.data.length = strlen(buf); 368 start = iwe_stream_add_point(info, start, stop, &iwe, buf); 369 370 _rtw_memset(&iwe, 0, sizeof(iwe)); 371 iwe.cmd = IWEVGENIE; 372 iwe.u.data.length = wpa_len; 373 start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie); 374 } 375 if (rsn_len > 0) { 376 p = buf; 377 _rtw_memset(buf, 0, MAX_WPA_IE_LEN); 378 p += sprintf(p, "rsn_ie ="); 379 for (i = 0; i < rsn_len; i++) 380 p += sprintf(p, "%02x", rsn_ie[i]); 381 _rtw_memset(&iwe, 0, sizeof(iwe)); 382 iwe.cmd = IWEVCUSTOM; 383 iwe.u.data.length = strlen(buf); 384 start = iwe_stream_add_point(info, start, stop, &iwe, buf); 385 386 _rtw_memset(&iwe, 0, sizeof(iwe)); 387 iwe.cmd = IWEVGENIE; 388 iwe.u.data.length = rsn_len; 389 start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie); 390 } 391 } 392 393 {/* parsing WPS IE */ 394 uint cnt = 0, total_ielen; 395 u8 *wpsie_ptr = NULL; 396 uint wps_ielen = 0; 397 398 u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_; 399 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_; 400 401 while (cnt < total_ielen) { 402 if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) { 403 wpsie_ptr = &ie_ptr[cnt]; 404 iwe.cmd = IWEVGENIE; 405 iwe.u.data.length = (u16)wps_ielen; 406 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr); 407 } 408 cnt += ie_ptr[cnt+1]+2; /* goto next */ 409 } 410 } 411 412 /* Add quality statistics */ 413 iwe.cmd = IWEVQUAL; 414 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; 415 416 if (check_fwstate(pmlmepriv, _FW_LINKED) == true && 417 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) { 418 ss = padapter->recvpriv.signal_strength; 419 sq = padapter->recvpriv.signal_qual; 420 } else { 421 ss = pnetwork->network.PhyInfo.SignalStrength; 422 sq = pnetwork->network.PhyInfo.SignalQuality; 423 } 424 425 iwe.u.qual.level = (u8)ss; 426 iwe.u.qual.qual = (u8)sq; /* signal quality */ 427 iwe.u.qual.noise = 0; /* noise level */ 428 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); 429 return start; 430} 431 432static int wpa_set_auth_algs(struct net_device *dev, u32 value) 433{ 434 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 435 int ret = 0; 436 437 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) { 438 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value); 439 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 440 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch; 441 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; 442 } else if (value & AUTH_ALG_SHARED_KEY) { 443 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n", value); 444 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 445 446 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared; 447 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; 448 } else if (value & AUTH_ALG_OPEN_SYSTEM) { 449 DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n"); 450 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) { 451 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; 452 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; 453 } 454 } else if (value & AUTH_ALG_LEAP) { 455 DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n"); 456 } else { 457 DBG_88E("wpa_set_auth_algs, error!\n"); 458 ret = -EINVAL; 459 } 460 return ret; 461} 462 463static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) 464{ 465 int ret = 0; 466 u32 wep_key_idx, wep_key_len, wep_total_len; 467 struct ndis_802_11_wep *pwep = NULL; 468 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 469 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 470 struct security_priv *psecuritypriv = &padapter->securitypriv; 471#ifdef CONFIG_88EU_P2P 472 struct wifidirect_info *pwdinfo = &padapter->wdinfo; 473#endif /* CONFIG_88EU_P2P */ 474 475_func_enter_; 476 477 param->u.crypt.err = 0; 478 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; 479 480 if (param_len < (u32) ((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) { 481 ret = -EINVAL; 482 goto exit; 483 } 484 485 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 486 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 487 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { 488 if (param->u.crypt.idx >= WEP_KEYS) { 489 ret = -EINVAL; 490 goto exit; 491 } 492 } else { 493 ret = -EINVAL; 494 goto exit; 495 } 496 497 if (strcmp(param->u.crypt.alg, "WEP") == 0) { 498 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n")); 499 DBG_88E("wpa_set_encryption, crypt.alg = WEP\n"); 500 501 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 502 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 503 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; 504 505 wep_key_idx = param->u.crypt.idx; 506 wep_key_len = param->u.crypt.key_len; 507 508 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx)); 509 DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx); 510 511 if (wep_key_idx > WEP_KEYS) 512 return -EINVAL; 513 514 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx)); 515 516 if (wep_key_len > 0) { 517 wep_key_len = wep_key_len <= 5 ? 5 : 13; 518 wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); 519 pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); 520 if (pwep == NULL) { 521 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n")); 522 goto exit; 523 } 524 _rtw_memset(pwep, 0, wep_total_len); 525 pwep->KeyLength = wep_key_len; 526 pwep->Length = wep_total_len; 527 if (wep_key_len == 13) { 528 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; 529 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_; 530 } 531 } else { 532 ret = -EINVAL; 533 goto exit; 534 } 535 pwep->KeyIndex = wep_key_idx; 536 pwep->KeyIndex |= 0x80000000; 537 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); 538 if (param->u.crypt.set_tx) { 539 DBG_88E("wep, set_tx = 1\n"); 540 if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL) 541 ret = -EOPNOTSUPP; 542 } else { 543 DBG_88E("wep, set_tx = 0\n"); 544 if (wep_key_idx >= WEP_KEYS) { 545 ret = -EOPNOTSUPP; 546 goto exit; 547 } 548 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength); 549 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength; 550 rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0); 551 } 552 goto exit; 553 } 554 555 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */ 556 struct sta_info *psta, *pbcmc_sta; 557 struct sta_priv *pstapriv = &padapter->stapriv; 558 559 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */ 560 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); 561 if (psta == NULL) { 562 ; 563 } else { 564 if (strcmp(param->u.crypt.alg, "none") != 0) 565 psta->ieee8021x_blocked = false; 566 567 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) || 568 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) 569 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; 570 571 if (param->u.crypt.set_tx == 1) { /* pairwise key */ 572 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 573 574 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */ 575 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8); 576 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8); 577 padapter->securitypriv.busetkipkey = false; 578 } 579 580 DBG_88E(" ~~~~set sta key:unicastkey\n"); 581 582 rtw_setstakey_cmd(padapter, (unsigned char *)psta, true); 583 } else { /* group key */ 584 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)); 585 memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8); 586 memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8); 587 padapter->securitypriv.binstallGrpkey = true; 588 DBG_88E(" ~~~~set sta key:groupkey\n"); 589 590 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx; 591 592 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1); 593#ifdef CONFIG_88EU_P2P 594 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING)) 595 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE); 596#endif /* CONFIG_88EU_P2P */ 597 } 598 } 599 pbcmc_sta = rtw_get_bcmc_stainfo(padapter); 600 if (pbcmc_sta == NULL) { 601 ; 602 } else { 603 /* Jeff: don't disable ieee8021x_blocked while clearing key */ 604 if (strcmp(param->u.crypt.alg, "none") != 0) 605 pbcmc_sta->ieee8021x_blocked = false; 606 607 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) || 608 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) 609 pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; 610 } 611 } 612 } 613 614exit: 615 616 kfree(pwep); 617 618_func_exit_; 619 620 return ret; 621} 622 623static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen) 624{ 625 u8 *buf = NULL; 626 int group_cipher = 0, pairwise_cipher = 0; 627 int ret = 0; 628#ifdef CONFIG_88EU_P2P 629 struct wifidirect_info *pwdinfo = &padapter->wdinfo; 630#endif /* CONFIG_88EU_P2P */ 631 632 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) { 633 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); 634 if (pie == NULL) 635 return ret; 636 else 637 return -EINVAL; 638 } 639 640 if (ielen) { 641 buf = rtw_zmalloc(ielen); 642 if (buf == NULL) { 643 ret = -ENOMEM; 644 goto exit; 645 } 646 647 memcpy(buf, pie, ielen); 648 649 /* dump */ 650 { 651 int i; 652 DBG_88E("\n wpa_ie(length:%d):\n", ielen); 653 for (i = 0; i < ielen; i += 8) 654 DBG_88E("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]); 655 } 656 657 if (ielen < RSN_HEADER_LEN) { 658 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen)); 659 ret = -1; 660 goto exit; 661 } 662 663 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 664 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; 665 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; 666 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen); 667 } 668 669 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 670 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; 671 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; 672 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen); 673 } 674 675 switch (group_cipher) { 676 case WPA_CIPHER_NONE: 677 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 678 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; 679 break; 680 case WPA_CIPHER_WEP40: 681 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; 682 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 683 break; 684 case WPA_CIPHER_TKIP: 685 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_; 686 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; 687 break; 688 case WPA_CIPHER_CCMP: 689 padapter->securitypriv.dot118021XGrpPrivacy = _AES_; 690 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; 691 break; 692 case WPA_CIPHER_WEP104: 693 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_; 694 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 695 break; 696 } 697 698 switch (pairwise_cipher) { 699 case WPA_CIPHER_NONE: 700 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 701 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; 702 break; 703 case WPA_CIPHER_WEP40: 704 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 705 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 706 break; 707 case WPA_CIPHER_TKIP: 708 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_; 709 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; 710 break; 711 case WPA_CIPHER_CCMP: 712 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_; 713 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; 714 break; 715 case WPA_CIPHER_WEP104: 716 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; 717 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 718 break; 719 } 720 721 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); 722 {/* set wps_ie */ 723 u16 cnt = 0; 724 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 725 726 while (cnt < ielen) { 727 eid = buf[cnt]; 728 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) { 729 DBG_88E("SET WPS_IE\n"); 730 731 padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2) : (MAX_WPA_IE_LEN<<2); 732 733 memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len); 734 735 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); 736#ifdef CONFIG_88EU_P2P 737 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) 738 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING); 739#endif /* CONFIG_88EU_P2P */ 740 cnt += buf[cnt+1]+2; 741 break; 742 } else { 743 cnt += buf[cnt+1]+2; /* goto next */ 744 } 745 } 746 } 747 } 748 749 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 750 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n", 751 pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype)); 752exit: 753 kfree(buf); 754 return ret; 755} 756 757typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; 758 759static int rtw_wx_get_name(struct net_device *dev, 760 struct iw_request_info *info, 761 union iwreq_data *wrqu, char *extra) 762{ 763 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 764 u32 ht_ielen = 0; 765 char *p; 766 u8 ht_cap = false; 767 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 768 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 769 NDIS_802_11_RATES_EX *prates = NULL; 770 771 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd)); 772 773 _func_enter_; 774 775 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) { 776 /* parsing HT_CAP_IE */ 777 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12); 778 if (p && ht_ielen > 0) 779 ht_cap = true; 780 781 prates = &pcur_bss->SupportedRates; 782 783 if (rtw_is_cckratesonly_included((u8 *)prates) == true) { 784 if (ht_cap) 785 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn"); 786 else 787 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b"); 788 } else if ((rtw_is_cckrates_included((u8 *)prates)) == true) { 789 if (ht_cap) 790 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn"); 791 else 792 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg"); 793 } else { 794 if (pcur_bss->Configuration.DSConfig > 14) { 795 if (ht_cap) 796 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an"); 797 else 798 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a"); 799 } else { 800 if (ht_cap) 801 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn"); 802 else 803 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); 804 } 805 } 806 } else { 807 snprintf(wrqu->name, IFNAMSIZ, "unassociated"); 808 } 809 810 _func_exit_; 811 812 return 0; 813} 814 815static int rtw_wx_set_freq(struct net_device *dev, 816 struct iw_request_info *info, 817 union iwreq_data *wrqu, char *extra) 818{ 819 _func_enter_; 820 821 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n")); 822 823 _func_exit_; 824 825 return 0; 826} 827 828static int rtw_wx_get_freq(struct net_device *dev, 829 struct iw_request_info *info, 830 union iwreq_data *wrqu, char *extra) 831{ 832 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 833 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 834 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 835 836 if (check_fwstate(pmlmepriv, _FW_LINKED)) { 837 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */ 838 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000; 839 wrqu->freq.e = 1; 840 wrqu->freq.i = pcur_bss->Configuration.DSConfig; 841 } else { 842 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000; 843 wrqu->freq.e = 1; 844 wrqu->freq.i = padapter->mlmeextpriv.cur_channel; 845 } 846 847 return 0; 848} 849 850static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a, 851 union iwreq_data *wrqu, char *b) 852{ 853 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 854 enum ndis_802_11_network_infra networkType; 855 int ret = 0; 856 857 _func_enter_; 858 859 if (_FAIL == rtw_pwr_wakeup(padapter)) { 860 ret = -EPERM; 861 goto exit; 862 } 863 864 if (!padapter->hw_init_completed) { 865 ret = -EPERM; 866 goto exit; 867 } 868 869 switch (wrqu->mode) { 870 case IW_MODE_AUTO: 871 networkType = Ndis802_11AutoUnknown; 872 DBG_88E("set_mode = IW_MODE_AUTO\n"); 873 break; 874 case IW_MODE_ADHOC: 875 networkType = Ndis802_11IBSS; 876 DBG_88E("set_mode = IW_MODE_ADHOC\n"); 877 break; 878 case IW_MODE_MASTER: 879 networkType = Ndis802_11APMode; 880 DBG_88E("set_mode = IW_MODE_MASTER\n"); 881 break; 882 case IW_MODE_INFRA: 883 networkType = Ndis802_11Infrastructure; 884 DBG_88E("set_mode = IW_MODE_INFRA\n"); 885 break; 886 default: 887 ret = -EINVAL; 888 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode])); 889 goto exit; 890 } 891 if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) { 892 ret = -EPERM; 893 goto exit; 894 } 895 rtw_setopmode_cmd(padapter, networkType); 896exit: 897 _func_exit_; 898 return ret; 899} 900 901static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a, 902 union iwreq_data *wrqu, char *b) 903{ 904 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 905 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 906 907 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n")); 908 909 _func_enter_; 910 911 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 912 wrqu->mode = IW_MODE_INFRA; 913 else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) || 914 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) 915 wrqu->mode = IW_MODE_ADHOC; 916 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 917 wrqu->mode = IW_MODE_MASTER; 918 else 919 wrqu->mode = IW_MODE_AUTO; 920 921 _func_exit_; 922 923 return 0; 924} 925 926static int rtw_wx_set_pmkid(struct net_device *dev, 927 struct iw_request_info *a, 928 union iwreq_data *wrqu, char *extra) 929{ 930 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 931 u8 j, blInserted = false; 932 int ret = false; 933 struct security_priv *psecuritypriv = &padapter->securitypriv; 934 struct iw_pmksa *pPMK = (struct iw_pmksa *)extra; 935 u8 strZeroMacAddress[ETH_ALEN] = {0x00}; 936 u8 strIssueBssid[ETH_ALEN] = {0x00}; 937 938 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN); 939 if (pPMK->cmd == IW_PMKSA_ADD) { 940 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n"); 941 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN)) 942 return ret; 943 else 944 ret = true; 945 blInserted = false; 946 947 /* overwrite PMKID */ 948 for (j = 0; j < NUM_PMKID_CACHE; j++) { 949 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) { 950 /* BSSID is matched, the same AP => rewrite with new PMKID. */ 951 DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n"); 952 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); 953 psecuritypriv->PMKIDList[j].bUsed = true; 954 psecuritypriv->PMKIDIndex = j+1; 955 blInserted = true; 956 break; 957 } 958 } 959 960 if (!blInserted) { 961 /* Find a new entry */ 962 DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n", 963 psecuritypriv->PMKIDIndex); 964 965 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN); 966 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN); 967 968 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true; 969 psecuritypriv->PMKIDIndex++; 970 if (psecuritypriv->PMKIDIndex == 16) 971 psecuritypriv->PMKIDIndex = 0; 972 } 973 } else if (pPMK->cmd == IW_PMKSA_REMOVE) { 974 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n"); 975 ret = true; 976 for (j = 0; j < NUM_PMKID_CACHE; j++) { 977 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) { 978 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */ 979 _rtw_memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN); 980 psecuritypriv->PMKIDList[j].bUsed = false; 981 break; 982 } 983 } 984 } else if (pPMK->cmd == IW_PMKSA_FLUSH) { 985 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n"); 986 _rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); 987 psecuritypriv->PMKIDIndex = 0; 988 ret = true; 989 } 990 return ret; 991} 992 993static int rtw_wx_get_sens(struct net_device *dev, 994 struct iw_request_info *info, 995 union iwreq_data *wrqu, char *extra) 996{ 997 wrqu->sens.value = 0; 998 wrqu->sens.fixed = 0; /* no auto select */ 999 wrqu->sens.disabled = 1; 1000 return 0; 1001} 1002 1003static int rtw_wx_get_range(struct net_device *dev, 1004 struct iw_request_info *info, 1005 union iwreq_data *wrqu, char *extra) 1006{ 1007 struct iw_range *range = (struct iw_range *)extra; 1008 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1009 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1010 1011 u16 val; 1012 int i; 1013 1014 _func_enter_; 1015 1016 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd)); 1017 1018 wrqu->data.length = sizeof(*range); 1019 _rtw_memset(range, 0, sizeof(*range)); 1020 1021 /* Let's try to keep this struct in the same order as in 1022 * linux/include/wireless.h 1023 */ 1024 1025 /* TODO: See what values we can set, and remove the ones we can't 1026 * set, or fill them with some default data. 1027 */ 1028 1029 /* ~5 Mb/s real (802.11b) */ 1030 range->throughput = 5 * 1000 * 1000; 1031 1032 /* signal level threshold range */ 1033 1034 /* percent values between 0 and 100. */ 1035 range->max_qual.qual = 100; 1036 range->max_qual.level = 100; 1037 range->max_qual.noise = 100; 1038 range->max_qual.updated = 7; /* Updated all three */ 1039 1040 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ 1041 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ 1042 range->avg_qual.level = 178; /* -78 dBm */ 1043 range->avg_qual.noise = 0; 1044 range->avg_qual.updated = 7; /* Updated all three */ 1045 1046 range->num_bitrates = RATE_COUNT; 1047 1048 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) 1049 range->bitrate[i] = rtw_rates[i]; 1050 1051 range->min_frag = MIN_FRAG_THRESHOLD; 1052 range->max_frag = MAX_FRAG_THRESHOLD; 1053 1054 range->pm_capa = 0; 1055 1056 range->we_version_compiled = WIRELESS_EXT; 1057 range->we_version_source = 16; 1058 1059 for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) { 1060 /* Include only legal frequencies for some countries */ 1061 if (pmlmeext->channel_set[i].ChannelNum != 0) { 1062 range->freq[val].i = pmlmeext->channel_set[i].ChannelNum; 1063 range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000; 1064 range->freq[val].e = 1; 1065 val++; 1066 } 1067 1068 if (val == IW_MAX_FREQUENCIES) 1069 break; 1070 } 1071 1072 range->num_channels = val; 1073 range->num_frequency = val; 1074 1075/* The following code will proivde the security capability to network manager. */ 1076/* If the driver doesn't provide this capability to network manager, */ 1077/* the WPA/WPA2 routers can't be chosen in the network manager. */ 1078 1079/* 1080#define IW_SCAN_CAPA_NONE 0x00 1081#define IW_SCAN_CAPA_ESSID 0x01 1082#define IW_SCAN_CAPA_BSSID 0x02 1083#define IW_SCAN_CAPA_CHANNEL 0x04 1084#define IW_SCAN_CAPA_MODE 0x08 1085#define IW_SCAN_CAPA_RATE 0x10 1086#define IW_SCAN_CAPA_TYPE 0x20 1087#define IW_SCAN_CAPA_TIME 0x40 1088*/ 1089 1090 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | 1091 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; 1092 1093 range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | 1094 IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL | 1095 IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE; 1096 _func_exit_; 1097 1098 return 0; 1099} 1100 1101/* set bssid flow */ 1102/* s1. rtw_set_802_11_infrastructure_mode() */ 1103/* s2. rtw_set_802_11_authentication_mode() */ 1104/* s3. set_802_11_encryption_mode() */ 1105/* s4. rtw_set_802_11_bssid() */ 1106static int rtw_wx_set_wap(struct net_device *dev, 1107 struct iw_request_info *info, 1108 union iwreq_data *awrq, 1109 char *extra) 1110{ 1111 uint ret = 0; 1112 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1113 struct sockaddr *temp = (struct sockaddr *)awrq; 1114 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1115 struct list_head *phead; 1116 u8 *dst_bssid, *src_bssid; 1117 struct __queue *queue = &(pmlmepriv->scanned_queue); 1118 struct wlan_network *pnetwork = NULL; 1119 enum ndis_802_11_auth_mode authmode; 1120 1121 _func_enter_; 1122 1123 if (_FAIL == rtw_pwr_wakeup(padapter)) { 1124 ret = -1; 1125 goto exit; 1126 } 1127 1128 if (!padapter->bup) { 1129 ret = -1; 1130 goto exit; 1131 } 1132 1133 if (temp->sa_family != ARPHRD_ETHER) { 1134 ret = -EINVAL; 1135 goto exit; 1136 } 1137 1138 authmode = padapter->securitypriv.ndisauthtype; 1139 spin_lock_bh(&queue->lock); 1140 phead = get_list_head(queue); 1141 pmlmepriv->pscanned = get_next(phead); 1142 1143 while (1) { 1144 if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == true) 1145 break; 1146 1147 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list); 1148 1149 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); 1150 1151 dst_bssid = pnetwork->network.MacAddress; 1152 1153 src_bssid = temp->sa_data; 1154 1155 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) { 1156 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) { 1157 ret = -1; 1158 spin_unlock_bh(&queue->lock); 1159 goto exit; 1160 } 1161 1162 break; 1163 } 1164 } 1165 spin_unlock_bh(&queue->lock); 1166 1167 rtw_set_802_11_authentication_mode(padapter, authmode); 1168 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */ 1169 if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) { 1170 ret = -1; 1171 goto exit; 1172 } 1173 1174exit: 1175 1176 _func_exit_; 1177 1178 return ret; 1179} 1180 1181static int rtw_wx_get_wap(struct net_device *dev, 1182 struct iw_request_info *info, 1183 union iwreq_data *wrqu, char *extra) 1184{ 1185 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1186 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1187 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 1188 1189 wrqu->ap_addr.sa_family = ARPHRD_ETHER; 1190 1191 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); 1192 1193 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n")); 1194 1195 _func_enter_; 1196 1197 if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) || 1198 ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) || 1199 ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true)) 1200 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN); 1201 else 1202 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); 1203 1204 _func_exit_; 1205 1206 return 0; 1207} 1208 1209static int rtw_wx_set_mlme(struct net_device *dev, 1210 struct iw_request_info *info, 1211 union iwreq_data *wrqu, char *extra) 1212{ 1213 int ret = 0; 1214 u16 reason; 1215 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1216 struct iw_mlme *mlme = (struct iw_mlme *)extra; 1217 1218 if (mlme == NULL) 1219 return -1; 1220 1221 DBG_88E("%s\n", __func__); 1222 1223 reason = mlme->reason_code; 1224 1225 DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason); 1226 1227 switch (mlme->cmd) { 1228 case IW_MLME_DEAUTH: 1229 if (!rtw_set_802_11_disassociate(padapter)) 1230 ret = -1; 1231 break; 1232 case IW_MLME_DISASSOC: 1233 if (!rtw_set_802_11_disassociate(padapter)) 1234 ret = -1; 1235 break; 1236 default: 1237 return -EOPNOTSUPP; 1238 } 1239 return ret; 1240} 1241 1242static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, 1243 union iwreq_data *wrqu, char *extra) 1244{ 1245 u8 _status = false; 1246 int ret = 0; 1247 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1248 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1249 struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT]; 1250#ifdef CONFIG_88EU_P2P 1251 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 1252#endif /* CONFIG_88EU_P2P */ 1253 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n")); 1254 1255_func_enter_; 1256 if (padapter->registrypriv.mp_mode == 1) { 1257 if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { 1258 ret = -1; 1259 goto exit; 1260 } 1261 } 1262 if (_FAIL == rtw_pwr_wakeup(padapter)) { 1263 ret = -1; 1264 goto exit; 1265 } 1266 1267 if (padapter->bDriverStopped) { 1268 DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped); 1269 ret = -1; 1270 goto exit; 1271 } 1272 1273 if (!padapter->bup) { 1274 ret = -1; 1275 goto exit; 1276 } 1277 1278 if (!padapter->hw_init_completed) { 1279 ret = -1; 1280 goto exit; 1281 } 1282 1283 /* When Busy Traffic, driver do not site survey. So driver return success. */ 1284 /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */ 1285 /* modify by thomas 2011-02-22. */ 1286 if (pmlmepriv->LinkDetectInfo.bBusyTraffic) { 1287 indicate_wx_scan_complete_event(padapter); 1288 goto exit; 1289 } 1290 1291 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) { 1292 indicate_wx_scan_complete_event(padapter); 1293 goto exit; 1294 } 1295 1296/* For the DMP WiFi Display project, the driver won't to scan because */ 1297/* the pmlmepriv->scan_interval is always equal to 3. */ 1298/* So, the wpa_supplicant won't find out the WPS SoftAP. */ 1299 1300#ifdef CONFIG_88EU_P2P 1301 if (pwdinfo->p2p_state != P2P_STATE_NONE) { 1302 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); 1303 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH); 1304 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL); 1305 rtw_free_network_queue(padapter, true); 1306 } 1307#endif /* CONFIG_88EU_P2P */ 1308 1309 _rtw_memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT); 1310 1311 if (wrqu->data.length == sizeof(struct iw_scan_req)) { 1312 struct iw_scan_req *req = (struct iw_scan_req *)extra; 1313 1314 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 1315 int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE); 1316 1317 memcpy(ssid[0].Ssid, req->essid, len); 1318 ssid[0].SsidLength = len; 1319 1320 DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len); 1321 1322 spin_lock_bh(&pmlmepriv->lock); 1323 1324 _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0); 1325 1326 spin_unlock_bh(&pmlmepriv->lock); 1327 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { 1328 DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n"); 1329 } 1330 } else { 1331 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE && 1332 !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) { 1333 int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE; 1334 char *pos = extra+WEXT_CSCAN_HEADER_SIZE; 1335 char section; 1336 char sec_len; 1337 int ssid_index = 0; 1338 1339 while (len >= 1) { 1340 section = *(pos++); 1341 len -= 1; 1342 1343 switch (section) { 1344 case WEXT_CSCAN_SSID_SECTION: 1345 if (len < 1) { 1346 len = 0; 1347 break; 1348 } 1349 sec_len = *(pos++); len -= 1; 1350 if (sec_len > 0 && sec_len <= len) { 1351 ssid[ssid_index].SsidLength = sec_len; 1352 memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength); 1353 ssid_index++; 1354 } 1355 pos += sec_len; 1356 len -= sec_len; 1357 break; 1358 case WEXT_CSCAN_TYPE_SECTION: 1359 case WEXT_CSCAN_CHANNEL_SECTION: 1360 pos += 1; 1361 len -= 1; 1362 break; 1363 case WEXT_CSCAN_PASV_DWELL_SECTION: 1364 case WEXT_CSCAN_HOME_DWELL_SECTION: 1365 case WEXT_CSCAN_ACTV_DWELL_SECTION: 1366 pos += 2; 1367 len -= 2; 1368 break; 1369 default: 1370 len = 0; /* stop parsing */ 1371 } 1372 } 1373 1374 /* it has still some scan parameter to parse, we only do this now... */ 1375 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT); 1376 } else { 1377 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0); 1378 } 1379 } 1380 1381 if (!_status) 1382 ret = -1; 1383 1384exit: 1385 1386_func_exit_; 1387 return ret; 1388} 1389 1390static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 1391 union iwreq_data *wrqu, char *extra) 1392{ 1393 struct list_head *plist, *phead; 1394 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1395 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1396 struct __queue *queue = &(pmlmepriv->scanned_queue); 1397 struct wlan_network *pnetwork = NULL; 1398 char *ev = extra; 1399 char *stop = ev + wrqu->data.length; 1400 u32 ret = 0; 1401 u32 cnt = 0; 1402 u32 wait_for_surveydone; 1403 int wait_status; 1404#ifdef CONFIG_88EU_P2P 1405 struct wifidirect_info *pwdinfo = &padapter->wdinfo; 1406#endif /* CONFIG_88EU_P2P */ 1407 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n")); 1408 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n")); 1409 1410 _func_enter_; 1411 1412 if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) { 1413 ret = -EINVAL; 1414 goto exit; 1415 } 1416 1417#ifdef CONFIG_88EU_P2P 1418 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { 1419 /* P2P is enabled */ 1420 wait_for_surveydone = 200; 1421 } else { 1422 /* P2P is disabled */ 1423 wait_for_surveydone = 100; 1424 } 1425#else 1426 { 1427 wait_for_surveydone = 100; 1428 } 1429#endif /* CONFIG_88EU_P2P */ 1430 1431 wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING; 1432 1433 while (check_fwstate(pmlmepriv, wait_status)) { 1434 msleep(30); 1435 cnt++; 1436 if (cnt > wait_for_surveydone) 1437 break; 1438 } 1439 1440 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 1441 1442 phead = get_list_head(queue); 1443 plist = get_next(phead); 1444 1445 while (1) { 1446 if (rtw_end_of_queue_search(phead, plist)) 1447 break; 1448 1449 if ((stop - ev) < SCAN_ITEM_SIZE) { 1450 ret = -E2BIG; 1451 break; 1452 } 1453 1454 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 1455 1456 /* report network only if the current channel set contains the channel to which this network belongs */ 1457 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0) 1458 ev = translate_scan(padapter, a, pnetwork, ev, stop); 1459 1460 plist = get_next(plist); 1461 } 1462 1463 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 1464 1465 wrqu->data.length = ev-extra; 1466 wrqu->data.flags = 0; 1467 1468exit: 1469 _func_exit_; 1470 return ret; 1471} 1472 1473/* set ssid flow */ 1474/* s1. rtw_set_802_11_infrastructure_mode() */ 1475/* s2. set_802_11_authenticaion_mode() */ 1476/* s3. set_802_11_encryption_mode() */ 1477/* s4. rtw_set_802_11_ssid() */ 1478static int rtw_wx_set_essid(struct net_device *dev, 1479 struct iw_request_info *a, 1480 union iwreq_data *wrqu, char *extra) 1481{ 1482 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1483 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1484 struct __queue *queue = &pmlmepriv->scanned_queue; 1485 struct list_head *phead; 1486 struct wlan_network *pnetwork = NULL; 1487 enum ndis_802_11_auth_mode authmode; 1488 struct ndis_802_11_ssid ndis_ssid; 1489 u8 *dst_ssid, *src_ssid; 1490 1491 uint ret = 0, len; 1492 1493 _func_enter_; 1494 1495 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1496 ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv))); 1497 if (_FAIL == rtw_pwr_wakeup(padapter)) { 1498 ret = -1; 1499 goto exit; 1500 } 1501 1502 if (!padapter->bup) { 1503 ret = -1; 1504 goto exit; 1505 } 1506 1507 if (wrqu->essid.length > IW_ESSID_MAX_SIZE) { 1508 ret = -E2BIG; 1509 goto exit; 1510 } 1511 1512 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1513 ret = -1; 1514 goto exit; 1515 } 1516 1517 authmode = padapter->securitypriv.ndisauthtype; 1518 DBG_88E("=>%s\n", __func__); 1519 if (wrqu->essid.flags && wrqu->essid.length) { 1520 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE; 1521 1522 if (wrqu->essid.length != 33) 1523 DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length); 1524 1525 _rtw_memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid)); 1526 ndis_ssid.SsidLength = len; 1527 memcpy(ndis_ssid.Ssid, extra, len); 1528 src_ssid = ndis_ssid.Ssid; 1529 1530 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid)); 1531 spin_lock_bh(&queue->lock); 1532 phead = get_list_head(queue); 1533 pmlmepriv->pscanned = get_next(phead); 1534 1535 while (1) { 1536 if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == true) { 1537 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_, 1538 ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n")); 1539 1540 break; 1541 } 1542 1543 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list); 1544 1545 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); 1546 1547 dst_ssid = pnetwork->network.Ssid.Ssid; 1548 1549 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1550 ("rtw_wx_set_essid: dst_ssid =%s\n", 1551 pnetwork->network.Ssid.Ssid)); 1552 1553 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) && 1554 (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) { 1555 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1556 ("rtw_wx_set_essid: find match, set infra mode\n")); 1557 1558 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) { 1559 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode) 1560 continue; 1561 } 1562 1563 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) { 1564 ret = -1; 1565 spin_unlock_bh(&queue->lock); 1566 goto exit; 1567 } 1568 1569 break; 1570 } 1571 } 1572 spin_unlock_bh(&queue->lock); 1573 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 1574 ("set ssid: set_802_11_auth. mode =%d\n", authmode)); 1575 rtw_set_802_11_authentication_mode(padapter, authmode); 1576 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) { 1577 ret = -1; 1578 goto exit; 1579 } 1580 } 1581 1582exit: 1583 1584 DBG_88E("<=%s, ret %d\n", __func__, ret); 1585 1586 _func_exit_; 1587 1588 return ret; 1589} 1590 1591static int rtw_wx_get_essid(struct net_device *dev, 1592 struct iw_request_info *a, 1593 union iwreq_data *wrqu, char *extra) 1594{ 1595 u32 len, ret = 0; 1596 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1597 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1598 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 1599 1600 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n")); 1601 1602 _func_enter_; 1603 1604 if ((check_fwstate(pmlmepriv, _FW_LINKED)) || 1605 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) { 1606 len = pcur_bss->Ssid.SsidLength; 1607 1608 wrqu->essid.length = len; 1609 1610 memcpy(extra, pcur_bss->Ssid.Ssid, len); 1611 1612 wrqu->essid.flags = 1; 1613 } else { 1614 ret = -1; 1615 goto exit; 1616 } 1617 1618exit: 1619 1620 _func_exit_; 1621 1622 return ret; 1623} 1624 1625static int rtw_wx_set_rate(struct net_device *dev, 1626 struct iw_request_info *a, 1627 union iwreq_data *wrqu, char *extra) 1628{ 1629 int i, ret = 0; 1630 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1631 u8 datarates[NumRates]; 1632 u32 target_rate = wrqu->bitrate.value; 1633 u32 fixed = wrqu->bitrate.fixed; 1634 u32 ratevalue = 0; 1635 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; 1636 1637_func_enter_; 1638 1639 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n")); 1640 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed)); 1641 1642 if (target_rate == -1) { 1643 ratevalue = 11; 1644 goto set_rate; 1645 } 1646 target_rate = target_rate/100000; 1647 1648 switch (target_rate) { 1649 case 10: 1650 ratevalue = 0; 1651 break; 1652 case 20: 1653 ratevalue = 1; 1654 break; 1655 case 55: 1656 ratevalue = 2; 1657 break; 1658 case 60: 1659 ratevalue = 3; 1660 break; 1661 case 90: 1662 ratevalue = 4; 1663 break; 1664 case 110: 1665 ratevalue = 5; 1666 break; 1667 case 120: 1668 ratevalue = 6; 1669 break; 1670 case 180: 1671 ratevalue = 7; 1672 break; 1673 case 240: 1674 ratevalue = 8; 1675 break; 1676 case 360: 1677 ratevalue = 9; 1678 break; 1679 case 480: 1680 ratevalue = 10; 1681 break; 1682 case 540: 1683 ratevalue = 11; 1684 break; 1685 default: 1686 ratevalue = 11; 1687 break; 1688 } 1689 1690set_rate: 1691 1692 for (i = 0; i < NumRates; i++) { 1693 if (ratevalue == mpdatarate[i]) { 1694 datarates[i] = mpdatarate[i]; 1695 if (fixed == 0) 1696 break; 1697 } else { 1698 datarates[i] = 0xff; 1699 } 1700 1701 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i])); 1702 } 1703 1704 if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) { 1705 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n")); 1706 ret = -1; 1707 } 1708 1709_func_exit_; 1710 1711 return ret; 1712} 1713 1714static int rtw_wx_get_rate(struct net_device *dev, 1715 struct iw_request_info *info, 1716 union iwreq_data *wrqu, char *extra) 1717{ 1718 u16 max_rate = 0; 1719 1720 max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev)); 1721 1722 if (max_rate == 0) 1723 return -EPERM; 1724 1725 wrqu->bitrate.fixed = 0; /* no auto select */ 1726 wrqu->bitrate.value = max_rate * 100000; 1727 1728 return 0; 1729} 1730 1731static int rtw_wx_set_rts(struct net_device *dev, 1732 struct iw_request_info *info, 1733 union iwreq_data *wrqu, char *extra) 1734{ 1735 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1736 1737 _func_enter_; 1738 1739 if (wrqu->rts.disabled) { 1740 padapter->registrypriv.rts_thresh = 2347; 1741 } else { 1742 if (wrqu->rts.value < 0 || 1743 wrqu->rts.value > 2347) 1744 return -EINVAL; 1745 1746 padapter->registrypriv.rts_thresh = wrqu->rts.value; 1747 } 1748 1749 DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh); 1750 1751 _func_exit_; 1752 1753 return 0; 1754} 1755 1756static int rtw_wx_get_rts(struct net_device *dev, 1757 struct iw_request_info *info, 1758 union iwreq_data *wrqu, char *extra) 1759{ 1760 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1761 1762 _func_enter_; 1763 1764 DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh); 1765 1766 wrqu->rts.value = padapter->registrypriv.rts_thresh; 1767 wrqu->rts.fixed = 0; /* no auto select */ 1768 /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */ 1769 1770 _func_exit_; 1771 1772 return 0; 1773} 1774 1775static int rtw_wx_set_frag(struct net_device *dev, 1776 struct iw_request_info *info, 1777 union iwreq_data *wrqu, char *extra) 1778{ 1779 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1780 1781 _func_enter_; 1782 1783 if (wrqu->frag.disabled) { 1784 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD; 1785 } else { 1786 if (wrqu->frag.value < MIN_FRAG_THRESHOLD || 1787 wrqu->frag.value > MAX_FRAG_THRESHOLD) 1788 return -EINVAL; 1789 1790 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1; 1791 } 1792 1793 DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len); 1794 1795 _func_exit_; 1796 1797 return 0; 1798} 1799 1800static int rtw_wx_get_frag(struct net_device *dev, 1801 struct iw_request_info *info, 1802 union iwreq_data *wrqu, char *extra) 1803{ 1804 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1805 1806 _func_enter_; 1807 1808 DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len); 1809 1810 wrqu->frag.value = padapter->xmitpriv.frag_len; 1811 wrqu->frag.fixed = 0; /* no auto select */ 1812 1813 _func_exit_; 1814 1815 return 0; 1816} 1817 1818static int rtw_wx_get_retry(struct net_device *dev, 1819 struct iw_request_info *info, 1820 union iwreq_data *wrqu, char *extra) 1821{ 1822 wrqu->retry.value = 7; 1823 wrqu->retry.fixed = 0; /* no auto select */ 1824 wrqu->retry.disabled = 1; 1825 1826 return 0; 1827} 1828 1829static int rtw_wx_set_enc(struct net_device *dev, 1830 struct iw_request_info *info, 1831 union iwreq_data *wrqu, char *keybuf) 1832{ 1833 u32 key, ret = 0; 1834 u32 keyindex_provided; 1835 struct ndis_802_11_wep wep; 1836 enum ndis_802_11_auth_mode authmode; 1837 1838 struct iw_point *erq = &(wrqu->encoding); 1839 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1840 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; 1841 DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags); 1842 1843 _rtw_memset(&wep, 0, sizeof(struct ndis_802_11_wep)); 1844 1845 key = erq->flags & IW_ENCODE_INDEX; 1846 1847 _func_enter_; 1848 1849 if (erq->flags & IW_ENCODE_DISABLED) { 1850 DBG_88E("EncryptionDisabled\n"); 1851 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; 1852 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 1853 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 1854 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ 1855 authmode = Ndis802_11AuthModeOpen; 1856 padapter->securitypriv.ndisauthtype = authmode; 1857 1858 goto exit; 1859 } 1860 1861 if (key) { 1862 if (key > WEP_KEYS) 1863 return -EINVAL; 1864 key--; 1865 keyindex_provided = 1; 1866 } else { 1867 keyindex_provided = 0; 1868 key = padapter->securitypriv.dot11PrivacyKeyIndex; 1869 DBG_88E("rtw_wx_set_enc, key =%d\n", key); 1870 } 1871 1872 /* set authentication mode */ 1873 if (erq->flags & IW_ENCODE_OPEN) { 1874 DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n"); 1875 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ 1876 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; 1877 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 1878 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 1879 authmode = Ndis802_11AuthModeOpen; 1880 padapter->securitypriv.ndisauthtype = authmode; 1881 } else if (erq->flags & IW_ENCODE_RESTRICTED) { 1882 DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n"); 1883 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; 1884 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; 1885 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 1886 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; 1887 authmode = Ndis802_11AuthModeShared; 1888 padapter->securitypriv.ndisauthtype = authmode; 1889 } else { 1890 DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags); 1891 1892 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ 1893 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ 1894 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 1895 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 1896 authmode = Ndis802_11AuthModeOpen; 1897 padapter->securitypriv.ndisauthtype = authmode; 1898 } 1899 1900 wep.KeyIndex = key; 1901 if (erq->length > 0) { 1902 wep.KeyLength = erq->length <= 5 ? 5 : 13; 1903 1904 wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); 1905 } else { 1906 wep.KeyLength = 0; 1907 1908 if (keyindex_provided == 1) { 1909 /* set key_id only, no given KeyMaterial(erq->length == 0). */ 1910 padapter->securitypriv.dot11PrivacyKeyIndex = key; 1911 1912 DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]); 1913 1914 switch (padapter->securitypriv.dot11DefKeylen[key]) { 1915 case 5: 1916 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; 1917 break; 1918 case 13: 1919 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_; 1920 break; 1921 default: 1922 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 1923 break; 1924 } 1925 1926 goto exit; 1927 } 1928 } 1929 1930 wep.KeyIndex |= 0x80000000; 1931 1932 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); 1933 1934 if (rtw_set_802_11_add_wep(padapter, &wep) == false) { 1935 if (rf_on == pwrpriv->rf_pwrstate) 1936 ret = -EOPNOTSUPP; 1937 goto exit; 1938 } 1939 1940exit: 1941 1942 _func_exit_; 1943 1944 return ret; 1945} 1946 1947static int rtw_wx_get_enc(struct net_device *dev, 1948 struct iw_request_info *info, 1949 union iwreq_data *wrqu, char *keybuf) 1950{ 1951 uint key, ret = 0; 1952 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 1953 struct iw_point *erq = &(wrqu->encoding); 1954 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1955 1956 _func_enter_; 1957 1958 if (check_fwstate(pmlmepriv, _FW_LINKED) != true) { 1959 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { 1960 erq->length = 0; 1961 erq->flags |= IW_ENCODE_DISABLED; 1962 return 0; 1963 } 1964 } 1965 1966 key = erq->flags & IW_ENCODE_INDEX; 1967 1968 if (key) { 1969 if (key > WEP_KEYS) 1970 return -EINVAL; 1971 key--; 1972 } else { 1973 key = padapter->securitypriv.dot11PrivacyKeyIndex; 1974 } 1975 1976 erq->flags = key + 1; 1977 1978 switch (padapter->securitypriv.ndisencryptstatus) { 1979 case Ndis802_11EncryptionNotSupported: 1980 case Ndis802_11EncryptionDisabled: 1981 erq->length = 0; 1982 erq->flags |= IW_ENCODE_DISABLED; 1983 break; 1984 case Ndis802_11Encryption1Enabled: 1985 erq->length = padapter->securitypriv.dot11DefKeylen[key]; 1986 if (erq->length) { 1987 memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]); 1988 1989 erq->flags |= IW_ENCODE_ENABLED; 1990 1991 if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) 1992 erq->flags |= IW_ENCODE_OPEN; 1993 else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared) 1994 erq->flags |= IW_ENCODE_RESTRICTED; 1995 } else { 1996 erq->length = 0; 1997 erq->flags |= IW_ENCODE_DISABLED; 1998 } 1999 break; 2000 case Ndis802_11Encryption2Enabled: 2001 case Ndis802_11Encryption3Enabled: 2002 erq->length = 16; 2003 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY); 2004 break; 2005 default: 2006 erq->length = 0; 2007 erq->flags |= IW_ENCODE_DISABLED; 2008 break; 2009 } 2010 _func_exit_; 2011 2012 return ret; 2013} 2014 2015static int rtw_wx_get_power(struct net_device *dev, 2016 struct iw_request_info *info, 2017 union iwreq_data *wrqu, char *extra) 2018{ 2019 wrqu->power.value = 0; 2020 wrqu->power.fixed = 0; /* no auto select */ 2021 wrqu->power.disabled = 1; 2022 2023 return 0; 2024} 2025 2026static int rtw_wx_set_gen_ie(struct net_device *dev, 2027 struct iw_request_info *info, 2028 union iwreq_data *wrqu, char *extra) 2029{ 2030 int ret; 2031 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2032 2033 ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length); 2034 return ret; 2035} 2036 2037static int rtw_wx_set_auth(struct net_device *dev, 2038 struct iw_request_info *info, 2039 union iwreq_data *wrqu, char *extra) 2040{ 2041 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2042 struct iw_param *param = (struct iw_param *)&(wrqu->param); 2043 int ret = 0; 2044 2045 switch (param->flags & IW_AUTH_INDEX) { 2046 case IW_AUTH_WPA_VERSION: 2047 break; 2048 case IW_AUTH_CIPHER_PAIRWISE: 2049 2050 break; 2051 case IW_AUTH_CIPHER_GROUP: 2052 2053 break; 2054 case IW_AUTH_KEY_MGMT: 2055 /* 2056 * ??? does not use these parameters 2057 */ 2058 break; 2059 case IW_AUTH_TKIP_COUNTERMEASURES: 2060 if (param->value) { 2061 /* wpa_supplicant is enabling the tkip countermeasure. */ 2062 padapter->securitypriv.btkip_countermeasure = true; 2063 } else { 2064 /* wpa_supplicant is disabling the tkip countermeasure. */ 2065 padapter->securitypriv.btkip_countermeasure = false; 2066 } 2067 break; 2068 case IW_AUTH_DROP_UNENCRYPTED: 2069 /* HACK: 2070 * 2071 * wpa_supplicant calls set_wpa_enabled when the driver 2072 * is loaded and unloaded, regardless of if WPA is being 2073 * used. No other calls are made which can be used to 2074 * determine if encryption will be used or not prior to 2075 * association being expected. If encryption is not being 2076 * used, drop_unencrypted is set to false, else true -- we 2077 * can use this to determine if the CAP_PRIVACY_ON bit should 2078 * be set. 2079 */ 2080 2081 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled) 2082 break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */ 2083 /* then it needn't reset it; */ 2084 2085 if (param->value) { 2086 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; 2087 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; 2088 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; 2089 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */ 2090 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; 2091 } 2092 2093 break; 2094 case IW_AUTH_80211_AUTH_ALG: 2095 /* 2096 * It's the starting point of a link layer connection using wpa_supplicant 2097 */ 2098 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { 2099 LeaveAllPowerSaveMode(padapter); 2100 rtw_disassoc_cmd(padapter, 500, false); 2101 DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__); 2102 rtw_indicate_disconnect(padapter); 2103 rtw_free_assoc_resources(padapter, 1); 2104 } 2105 ret = wpa_set_auth_algs(dev, (u32)param->value); 2106 break; 2107 case IW_AUTH_WPA_ENABLED: 2108 break; 2109 case IW_AUTH_RX_UNENCRYPTED_EAPOL: 2110 break; 2111 case IW_AUTH_PRIVACY_INVOKED: 2112 break; 2113 default: 2114 return -EOPNOTSUPP; 2115 } 2116 2117 return ret; 2118} 2119 2120static int rtw_wx_set_enc_ext(struct net_device *dev, 2121 struct iw_request_info *info, 2122 union iwreq_data *wrqu, char *extra) 2123{ 2124 char *alg_name; 2125 u32 param_len; 2126 struct ieee_param *param = NULL; 2127 struct iw_point *pencoding = &wrqu->encoding; 2128 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra; 2129 int ret = 0; 2130 2131 param_len = sizeof(struct ieee_param) + pext->key_len; 2132 param = (struct ieee_param *)rtw_malloc(param_len); 2133 if (param == NULL) 2134 return -1; 2135 2136 _rtw_memset(param, 0, param_len); 2137 2138 param->cmd = IEEE_CMD_SET_ENCRYPTION; 2139 _rtw_memset(param->sta_addr, 0xff, ETH_ALEN); 2140 2141 switch (pext->alg) { 2142 case IW_ENCODE_ALG_NONE: 2143 /* todo: remove key */ 2144 /* remove = 1; */ 2145 alg_name = "none"; 2146 break; 2147 case IW_ENCODE_ALG_WEP: 2148 alg_name = "WEP"; 2149 break; 2150 case IW_ENCODE_ALG_TKIP: 2151 alg_name = "TKIP"; 2152 break; 2153 case IW_ENCODE_ALG_CCMP: 2154 alg_name = "CCMP"; 2155 break; 2156 default: 2157 return -1; 2158 } 2159 2160 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); 2161 2162 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 2163 param->u.crypt.set_tx = 1; 2164 2165 /* cliW: WEP does not have group key 2166 * just not checking GROUP key setting 2167 */ 2168 if ((pext->alg != IW_ENCODE_ALG_WEP) && 2169 (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) 2170 param->u.crypt.set_tx = 0; 2171 2172 param->u.crypt.idx = (pencoding->flags&0x00FF) - 1; 2173 2174 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) 2175 memcpy(param->u.crypt.seq, pext->rx_seq, 8); 2176 2177 if (pext->key_len) { 2178 param->u.crypt.key_len = pext->key_len; 2179 memcpy(param->u.crypt.key, pext + 1, pext->key_len); 2180 } 2181 2182 ret = wpa_set_encryption(dev, param, param_len); 2183 2184 kfree(param); 2185 return ret; 2186} 2187 2188static int rtw_wx_get_nick(struct net_device *dev, 2189 struct iw_request_info *info, 2190 union iwreq_data *wrqu, char *extra) 2191{ 2192 if (extra) { 2193 wrqu->data.length = 14; 2194 wrqu->data.flags = 1; 2195 memcpy(extra, "<WIFI@REALTEK>", 14); 2196 } 2197 2198 /* dump debug info here */ 2199 return 0; 2200} 2201 2202static int rtw_wx_read32(struct net_device *dev, 2203 struct iw_request_info *info, 2204 union iwreq_data *wrqu, char *extra) 2205{ 2206 struct adapter *padapter; 2207 struct iw_point *p; 2208 u16 len; 2209 u32 addr; 2210 u32 data32; 2211 u32 bytes; 2212 u8 *ptmp; 2213 2214 padapter = (struct adapter *)rtw_netdev_priv(dev); 2215 p = &wrqu->data; 2216 len = p->length; 2217 ptmp = (u8 *)rtw_malloc(len); 2218 if (NULL == ptmp) 2219 return -ENOMEM; 2220 2221 if (copy_from_user(ptmp, p->pointer, len)) { 2222 kfree(ptmp); 2223 return -EFAULT; 2224 } 2225 2226 bytes = 0; 2227 addr = 0; 2228 sscanf(ptmp, "%d,%x", &bytes, &addr); 2229 2230 switch (bytes) { 2231 case 1: 2232 data32 = rtw_read8(padapter, addr); 2233 sprintf(extra, "0x%02X", data32); 2234 break; 2235 case 2: 2236 data32 = rtw_read16(padapter, addr); 2237 sprintf(extra, "0x%04X", data32); 2238 break; 2239 case 4: 2240 data32 = rtw_read32(padapter, addr); 2241 sprintf(extra, "0x%08X", data32); 2242 break; 2243 default: 2244 DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__); 2245 return -EINVAL; 2246 } 2247 DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra); 2248 2249 kfree(ptmp); 2250 return 0; 2251} 2252 2253static int rtw_wx_write32(struct net_device *dev, 2254 struct iw_request_info *info, 2255 union iwreq_data *wrqu, char *extra) 2256{ 2257 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2258 2259 u32 addr; 2260 u32 data32; 2261 u32 bytes; 2262 2263 bytes = 0; 2264 addr = 0; 2265 data32 = 0; 2266 sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32); 2267 2268 switch (bytes) { 2269 case 1: 2270 rtw_write8(padapter, addr, (u8)data32); 2271 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32); 2272 break; 2273 case 2: 2274 rtw_write16(padapter, addr, (u16)data32); 2275 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32); 2276 break; 2277 case 4: 2278 rtw_write32(padapter, addr, data32); 2279 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32); 2280 break; 2281 default: 2282 DBG_88E(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__); 2283 return -EINVAL; 2284 } 2285 2286 return 0; 2287} 2288 2289static int rtw_wx_read_rf(struct net_device *dev, 2290 struct iw_request_info *info, 2291 union iwreq_data *wrqu, char *extra) 2292{ 2293 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2294 u32 path, addr, data32; 2295 2296 path = *(u32 *)extra; 2297 addr = *((u32 *)extra + 1); 2298 data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF); 2299 /* 2300 * IMPORTANT!! 2301 * Only when wireless private ioctl is at odd order, 2302 * "extra" would be copied to user space. 2303 */ 2304 sprintf(extra, "0x%05x", data32); 2305 2306 return 0; 2307} 2308 2309static int rtw_wx_write_rf(struct net_device *dev, 2310 struct iw_request_info *info, 2311 union iwreq_data *wrqu, char *extra) 2312{ 2313 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2314 u32 path, addr, data32; 2315 2316 path = *(u32 *)extra; 2317 addr = *((u32 *)extra + 1); 2318 data32 = *((u32 *)extra + 2); 2319 rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32); 2320 2321 return 0; 2322} 2323 2324static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a, 2325 union iwreq_data *wrqu, char *b) 2326{ 2327 return -1; 2328} 2329 2330static int dummy(struct net_device *dev, struct iw_request_info *a, 2331 union iwreq_data *wrqu, char *b) 2332{ 2333 return -1; 2334} 2335 2336static int rtw_wx_set_channel_plan(struct net_device *dev, 2337 struct iw_request_info *info, 2338 union iwreq_data *wrqu, char *extra) 2339{ 2340 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2341 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2342 u8 channel_plan_req = (u8) (*((int *)wrqu)); 2343 2344 if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1)) 2345 DBG_88E("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan); 2346 else 2347 return -EPERM; 2348 2349 return 0; 2350} 2351 2352static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev, 2353 struct iw_request_info *a, 2354 union iwreq_data *wrqu, char *b) 2355{ 2356 return 0; 2357} 2358 2359static int rtw_wx_get_sensitivity(struct net_device *dev, 2360 struct iw_request_info *info, 2361 union iwreq_data *wrqu, char *buf) 2362{ 2363 return 0; 2364} 2365 2366static int rtw_wx_set_mtk_wps_ie(struct net_device *dev, 2367 struct iw_request_info *info, 2368 union iwreq_data *wrqu, char *extra) 2369{ 2370 return 0; 2371} 2372 2373/* 2374 * For all data larger than 16 octets, we need to use a 2375 * pointer to memory allocated in user space. 2376 */ 2377static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info, 2378 union iwreq_data *wrqu, char *extra) 2379{ 2380 return 0; 2381} 2382 2383static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len) 2384{ 2385 struct mp_rw_reg *RegRWStruct; 2386 struct rf_reg_param *prfreg; 2387 u8 path; 2388 u8 offset; 2389 u32 value; 2390 2391 DBG_88E("%s\n", __func__); 2392 2393 switch (id) { 2394 case GEN_MP_IOCTL_SUBCODE(MP_START): 2395 DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n"); 2396 break; 2397 case GEN_MP_IOCTL_SUBCODE(READ_REG): 2398 RegRWStruct = (struct mp_rw_reg *)pdata; 2399 switch (RegRWStruct->width) { 2400 case 1: 2401 RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset); 2402 break; 2403 case 2: 2404 RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset); 2405 break; 2406 case 4: 2407 RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset); 2408 break; 2409 default: 2410 break; 2411 } 2412 2413 break; 2414 case GEN_MP_IOCTL_SUBCODE(WRITE_REG): 2415 RegRWStruct = (struct mp_rw_reg *)pdata; 2416 switch (RegRWStruct->width) { 2417 case 1: 2418 rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value); 2419 break; 2420 case 2: 2421 rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value); 2422 break; 2423 case 4: 2424 rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value); 2425 break; 2426 default: 2427 break; 2428 } 2429 2430 break; 2431 case GEN_MP_IOCTL_SUBCODE(READ_RF_REG): 2432 2433 prfreg = (struct rf_reg_param *)pdata; 2434 2435 path = (u8)prfreg->path; 2436 offset = (u8)prfreg->offset; 2437 2438 value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff); 2439 2440 prfreg->value = value; 2441 2442 break; 2443 case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG): 2444 2445 prfreg = (struct rf_reg_param *)pdata; 2446 2447 path = (u8)prfreg->path; 2448 offset = (u8)prfreg->offset; 2449 value = prfreg->value; 2450 2451 rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value); 2452 2453 break; 2454 case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO): 2455 DBG_88E("==> trigger gpio 0\n"); 2456 rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL); 2457 break; 2458 case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS): 2459 *pdata = rtw_hal_sreset_get_wifi_status(padapter); 2460 break; 2461 default: 2462 break; 2463 } 2464} 2465 2466static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info, 2467 union iwreq_data *wrqu, char *extra) 2468{ 2469 int ret = 0; 2470 u32 BytesRead, BytesWritten, BytesNeeded; 2471 struct oid_par_priv oid_par; 2472 struct mp_ioctl_handler *phandler; 2473 struct mp_ioctl_param *poidparam; 2474 uint status = 0; 2475 u16 len; 2476 u8 *pparmbuf = NULL, bset; 2477 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2478 struct iw_point *p = &wrqu->data; 2479 2480 if ((!p->length) || (!p->pointer)) { 2481 ret = -EINVAL; 2482 goto _rtw_mp_ioctl_hdl_exit; 2483 } 2484 pparmbuf = NULL; 2485 bset = (u8)(p->flags & 0xFFFF); 2486 len = p->length; 2487 pparmbuf = (u8 *)rtw_malloc(len); 2488 if (pparmbuf == NULL) { 2489 ret = -ENOMEM; 2490 goto _rtw_mp_ioctl_hdl_exit; 2491 } 2492 2493 if (copy_from_user(pparmbuf, p->pointer, len)) { 2494 ret = -EFAULT; 2495 goto _rtw_mp_ioctl_hdl_exit; 2496 } 2497 2498 poidparam = (struct mp_ioctl_param *)pparmbuf; 2499 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 2500 ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n", 2501 poidparam->subcode, poidparam->len, len)); 2502 2503 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) { 2504 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n")); 2505 ret = -EINVAL; 2506 goto _rtw_mp_ioctl_hdl_exit; 2507 } 2508 2509 if (padapter->registrypriv.mp_mode == 1) { 2510 phandler = mp_ioctl_hdl + poidparam->subcode; 2511 2512 if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) { 2513 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, 2514 ("no matching drvext param size %d vs %d\r\n", 2515 poidparam->len, phandler->paramsize)); 2516 ret = -EINVAL; 2517 goto _rtw_mp_ioctl_hdl_exit; 2518 } 2519 2520 if (phandler->handler) { 2521 oid_par.adapter_context = padapter; 2522 oid_par.oid = phandler->oid; 2523 oid_par.information_buf = poidparam->data; 2524 oid_par.information_buf_len = poidparam->len; 2525 oid_par.dbg = 0; 2526 2527 BytesWritten = 0; 2528 BytesNeeded = 0; 2529 2530 if (bset) { 2531 oid_par.bytes_rw = &BytesRead; 2532 oid_par.bytes_needed = &BytesNeeded; 2533 oid_par.type_of_oid = SET_OID; 2534 } else { 2535 oid_par.bytes_rw = &BytesWritten; 2536 oid_par.bytes_needed = &BytesNeeded; 2537 oid_par.type_of_oid = QUERY_OID; 2538 } 2539 2540 status = phandler->handler(&oid_par); 2541 } else { 2542 DBG_88E("rtw_mp_ioctl_hdl(): err!, subcode =%d, oid =%d, handler =%p\n", 2543 poidparam->subcode, phandler->oid, phandler->handler); 2544 ret = -EFAULT; 2545 goto _rtw_mp_ioctl_hdl_exit; 2546 } 2547 } else { 2548 rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len); 2549 } 2550 2551 if (bset == 0x00) {/* query info */ 2552 if (copy_to_user(p->pointer, pparmbuf, len)) 2553 ret = -EFAULT; 2554 } 2555 2556 if (status) { 2557 ret = -EFAULT; 2558 goto _rtw_mp_ioctl_hdl_exit; 2559 } 2560 2561_rtw_mp_ioctl_hdl_exit: 2562 2563 kfree(pparmbuf); 2564 return ret; 2565} 2566 2567static int rtw_get_ap_info(struct net_device *dev, 2568 struct iw_request_info *info, 2569 union iwreq_data *wrqu, char *extra) 2570{ 2571 int ret = 0; 2572 u32 cnt = 0, wpa_ielen; 2573 struct list_head *plist, *phead; 2574 unsigned char *pbuf; 2575 u8 bssid[ETH_ALEN]; 2576 char data[32]; 2577 struct wlan_network *pnetwork = NULL; 2578 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2579 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2580 struct __queue *queue = &(pmlmepriv->scanned_queue); 2581 struct iw_point *pdata = &wrqu->data; 2582 2583 DBG_88E("+rtw_get_aplist_info\n"); 2584 2585 if ((padapter->bDriverStopped) || (pdata == NULL)) { 2586 ret = -EINVAL; 2587 goto exit; 2588 } 2589 2590 while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) { 2591 msleep(30); 2592 cnt++; 2593 if (cnt > 100) 2594 break; 2595 } 2596 pdata->flags = 0; 2597 if (pdata->length >= 32) { 2598 if (copy_from_user(data, pdata->pointer, 32)) { 2599 ret = -EINVAL; 2600 goto exit; 2601 } 2602 } else { 2603 ret = -EINVAL; 2604 goto exit; 2605 } 2606 2607 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 2608 2609 phead = get_list_head(queue); 2610 plist = get_next(phead); 2611 2612 while (1) { 2613 if (rtw_end_of_queue_search(phead, plist) == true) 2614 break; 2615 2616 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 2617 2618 if (hwaddr_aton_i(data, bssid)) { 2619 DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data); 2620 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 2621 return -EINVAL; 2622 } 2623 2624 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) { 2625 /* BSSID match, then check if supporting wpa/wpa2 */ 2626 DBG_88E("BSSID:%pM\n", (bssid)); 2627 2628 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 2629 if (pbuf && (wpa_ielen > 0)) { 2630 pdata->flags = 1; 2631 break; 2632 } 2633 2634 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 2635 if (pbuf && (wpa_ielen > 0)) { 2636 pdata->flags = 2; 2637 break; 2638 } 2639 } 2640 2641 plist = get_next(plist); 2642 } 2643 2644 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 2645 2646 if (pdata->length >= 34) { 2647 if (copy_to_user(pdata->pointer+32, (u8 *)&pdata->flags, 1)) { 2648 ret = -EINVAL; 2649 goto exit; 2650 } 2651 } 2652 2653exit: 2654 2655 return ret; 2656} 2657 2658static int rtw_set_pid(struct net_device *dev, 2659 struct iw_request_info *info, 2660 union iwreq_data *wrqu, char *extra) 2661{ 2662 int ret = 0; 2663 struct adapter *padapter = rtw_netdev_priv(dev); 2664 int *pdata = (int *)wrqu; 2665 int selector; 2666 2667 if ((padapter->bDriverStopped) || (pdata == NULL)) { 2668 ret = -EINVAL; 2669 goto exit; 2670 } 2671 2672 selector = *pdata; 2673 if (selector < 3 && selector >= 0) { 2674 padapter->pid[selector] = *(pdata+1); 2675 ui_pid[selector] = *(pdata+1); 2676 DBG_88E("%s set pid[%d] =%d\n", __func__, selector, padapter->pid[selector]); 2677 } else { 2678 DBG_88E("%s selector %d error\n", __func__, selector); 2679 } 2680exit: 2681 return ret; 2682} 2683 2684static int rtw_wps_start(struct net_device *dev, 2685 struct iw_request_info *info, 2686 union iwreq_data *wrqu, char *extra) 2687{ 2688 int ret = 0; 2689 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2690 struct iw_point *pdata = &wrqu->data; 2691 u32 u32wps_start = 0; 2692 2693 ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4); 2694 if (ret) { 2695 ret = -EINVAL; 2696 goto exit; 2697 } 2698 2699 if ((padapter->bDriverStopped) || (pdata == NULL)) { 2700 ret = -EINVAL; 2701 goto exit; 2702 } 2703 2704 if (u32wps_start == 0) 2705 u32wps_start = *extra; 2706 2707 DBG_88E("[%s] wps_start = %d\n", __func__, u32wps_start); 2708 2709 if (u32wps_start == 1) /* WPS Start */ 2710 rtw_led_control(padapter, LED_CTL_START_WPS); 2711 else if (u32wps_start == 2) /* WPS Stop because of wps success */ 2712 rtw_led_control(padapter, LED_CTL_STOP_WPS); 2713 else if (u32wps_start == 3) /* WPS Stop because of wps fail */ 2714 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL); 2715 2716exit: 2717 return ret; 2718} 2719 2720#ifdef CONFIG_88EU_P2P 2721static int rtw_wext_p2p_enable(struct net_device *dev, 2722 struct iw_request_info *info, 2723 union iwreq_data *wrqu, char *extra) 2724{ 2725 int ret = 0; 2726 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2727 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2728 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 2729 enum P2P_ROLE init_role = P2P_ROLE_DISABLE; 2730 2731 if (*extra == '0') 2732 init_role = P2P_ROLE_DISABLE; 2733 else if (*extra == '1') 2734 init_role = P2P_ROLE_DEVICE; 2735 else if (*extra == '2') 2736 init_role = P2P_ROLE_CLIENT; 2737 else if (*extra == '3') 2738 init_role = P2P_ROLE_GO; 2739 2740 if (_FAIL == rtw_p2p_enable(padapter, init_role)) { 2741 ret = -EFAULT; 2742 goto exit; 2743 } 2744 2745 /* set channel/bandwidth */ 2746 if (init_role != P2P_ROLE_DISABLE) { 2747 u8 channel, ch_offset; 2748 u16 bwmode; 2749 2750 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) { 2751 /* Stay at the listen state and wait for discovery. */ 2752 channel = pwdinfo->listen_channel; 2753 pwdinfo->operating_channel = pwdinfo->listen_channel; 2754 ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 2755 bwmode = HT_CHANNEL_WIDTH_20; 2756 } else { 2757 pwdinfo->operating_channel = pmlmeext->cur_channel; 2758 2759 channel = pwdinfo->operating_channel; 2760 ch_offset = pmlmeext->cur_ch_offset; 2761 bwmode = pmlmeext->cur_bwmode; 2762 } 2763 2764 set_channel_bwmode(padapter, channel, ch_offset, bwmode); 2765 } 2766 2767exit: 2768 return ret; 2769} 2770 2771static int rtw_p2p_set_go_nego_ssid(struct net_device *dev, 2772 struct iw_request_info *info, 2773 union iwreq_data *wrqu, char *extra) 2774{ 2775 int ret = 0; 2776 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2777 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2778 2779 DBG_88E("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra)); 2780 memcpy(pwdinfo->nego_ssid, extra, strlen(extra)); 2781 pwdinfo->nego_ssidlen = strlen(extra); 2782 2783 return ret; 2784} 2785 2786static int rtw_p2p_set_intent(struct net_device *dev, 2787 struct iw_request_info *info, 2788 union iwreq_data *wrqu, char *extra) 2789{ 2790 int ret = 0; 2791 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2792 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2793 u8 intent = pwdinfo->intent; 2794 2795 switch (wrqu->data.length) { 2796 case 1: 2797 intent = extra[0] - '0'; 2798 break; 2799 case 2: 2800 intent = str_2char2num(extra[0], extra[1]); 2801 break; 2802 } 2803 if (intent <= 15) 2804 pwdinfo->intent = intent; 2805 else 2806 ret = -1; 2807 DBG_88E("[%s] intent = %d\n", __func__, intent); 2808 return ret; 2809} 2810 2811static int rtw_p2p_set_listen_ch(struct net_device *dev, 2812 struct iw_request_info *info, 2813 union iwreq_data *wrqu, char *extra) 2814{ 2815 int ret = 0; 2816 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2817 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2818 u8 listen_ch = pwdinfo->listen_channel; /* Listen channel number */ 2819 2820 switch (wrqu->data.length) { 2821 case 1: 2822 listen_ch = extra[0] - '0'; 2823 break; 2824 case 2: 2825 listen_ch = str_2char2num(extra[0], extra[1]); 2826 break; 2827 } 2828 2829 if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) { 2830 pwdinfo->listen_channel = listen_ch; 2831 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); 2832 } else { 2833 ret = -1; 2834 } 2835 2836 DBG_88E("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel); 2837 2838 return ret; 2839} 2840 2841static int rtw_p2p_set_op_ch(struct net_device *dev, 2842 struct iw_request_info *info, 2843 union iwreq_data *wrqu, char *extra) 2844{ 2845/* Commented by Albert 20110524 */ 2846/* This function is used to set the operating channel if the driver will become the group owner */ 2847 2848 int ret = 0; 2849 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2850 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2851 u8 op_ch = pwdinfo->operating_channel; /* Operating channel number */ 2852 2853 switch (wrqu->data.length) { 2854 case 1: 2855 op_ch = extra[0] - '0'; 2856 break; 2857 case 2: 2858 op_ch = str_2char2num(extra[0], extra[1]); 2859 break; 2860 } 2861 2862 if (op_ch > 0) 2863 pwdinfo->operating_channel = op_ch; 2864 else 2865 ret = -1; 2866 2867 DBG_88E("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel); 2868 2869 return ret; 2870} 2871 2872static int rtw_p2p_profilefound(struct net_device *dev, 2873 struct iw_request_info *info, 2874 union iwreq_data *wrqu, char *extra) 2875{ 2876 int ret = 0; 2877 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2878 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2879 2880 /* Comment by Albert 2010/10/13 */ 2881 /* Input data format: */ 2882 /* Ex: 0 */ 2883 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */ 2884 /* 0 => Reflush the profile record list. */ 2885 /* 1 => Add the profile list */ 2886 /* XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */ 2887 /* YY => SSID Length */ 2888 /* SSID => SSID for persistence group */ 2889 2890 DBG_88E("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1); 2891 2892 /* The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */ 2893 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { 2894 if (extra[0] == '0') { 2895 /* Remove all the profile information of wifidirect_info structure. */ 2896 _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM); 2897 pwdinfo->profileindex = 0; 2898 } else { 2899 if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) { 2900 ret = -1; 2901 } else { 2902 int jj, kk; 2903 2904 /* Add this profile information into pwdinfo->profileinfo */ 2905 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */ 2906 for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3) 2907 pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]); 2908 2909 pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0'); 2910 memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen); 2911 pwdinfo->profileindex++; 2912 } 2913 } 2914 } 2915 2916 return ret; 2917} 2918 2919static int rtw_p2p_setDN(struct net_device *dev, 2920 struct iw_request_info *info, 2921 union iwreq_data *wrqu, char *extra) 2922{ 2923 int ret = 0; 2924 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2925 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2926 2927 DBG_88E("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1); 2928 _rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN); 2929 memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1); 2930 pwdinfo->device_name_len = wrqu->data.length - 1; 2931 2932 return ret; 2933} 2934 2935static int rtw_p2p_get_status(struct net_device *dev, 2936 struct iw_request_info *info, 2937 union iwreq_data *wrqu, char *extra) 2938{ 2939 int ret = 0; 2940 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2941 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2942 2943 if (padapter->bShowGetP2PState) 2944 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), 2945 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2], 2946 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]); 2947 2948 /* Commented by Albert 2010/10/12 */ 2949 /* Because of the output size limitation, I had removed the "Role" information. */ 2950 /* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */ 2951 sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo)); 2952 wrqu->data.length = strlen(extra); 2953 2954 return ret; 2955} 2956 2957/* Commented by Albert 20110520 */ 2958/* This function will return the config method description */ 2959/* This config method description will show us which config method the remote P2P device is intended to use */ 2960/* by sending the provisioning discovery request frame. */ 2961 2962static int rtw_p2p_get_req_cm(struct net_device *dev, 2963 struct iw_request_info *info, 2964 union iwreq_data *wrqu, char *extra) 2965{ 2966 int ret = 0; 2967 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2968 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2969 2970 sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req); 2971 wrqu->data.length = strlen(extra); 2972 return ret; 2973} 2974 2975static int rtw_p2p_get_role(struct net_device *dev, 2976 struct iw_request_info *info, 2977 union iwreq_data *wrqu, char *extra) 2978{ 2979 int ret = 0; 2980 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2981 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2982 2983 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), 2984 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2], 2985 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]); 2986 2987 sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo)); 2988 wrqu->data.length = strlen(extra); 2989 return ret; 2990} 2991 2992static int rtw_p2p_get_peer_ifaddr(struct net_device *dev, 2993 struct iw_request_info *info, 2994 union iwreq_data *wrqu, char *extra) 2995{ 2996 int ret = 0; 2997 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 2998 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 2999 3000 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__, 3001 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), 3002 pwdinfo->p2p_peer_interface_addr); 3003 sprintf(extra, "\nMAC %pM", 3004 pwdinfo->p2p_peer_interface_addr); 3005 wrqu->data.length = strlen(extra); 3006 return ret; 3007} 3008 3009static int rtw_p2p_get_peer_devaddr(struct net_device *dev, 3010 struct iw_request_info *info, 3011 union iwreq_data *wrqu, char *extra) 3012 3013{ 3014 int ret = 0; 3015 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3016 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3017 3018 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__, 3019 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), 3020 pwdinfo->rx_prov_disc_info.peerDevAddr); 3021 sprintf(extra, "\n%pM", 3022 pwdinfo->rx_prov_disc_info.peerDevAddr); 3023 wrqu->data.length = strlen(extra); 3024 return ret; 3025} 3026 3027static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev, 3028 struct iw_request_info *info, 3029 union iwreq_data *wrqu, char *extra) 3030 3031{ 3032 int ret = 0; 3033 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3034 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3035 3036 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", 3037 __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), 3038 pwdinfo->p2p_peer_device_addr); 3039 sprintf(extra, "\nMAC %pM", 3040 pwdinfo->p2p_peer_device_addr); 3041 wrqu->data.length = strlen(extra); 3042 return ret; 3043} 3044 3045static int rtw_p2p_get_groupid(struct net_device *dev, 3046 struct iw_request_info *info, 3047 union iwreq_data *wrqu, char *extra) 3048 3049{ 3050 int ret = 0; 3051 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3052 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3053 3054 sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s", 3055 pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1], 3056 pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3], 3057 pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5], 3058 pwdinfo->groupid_info.ssid); 3059 wrqu->data.length = strlen(extra); 3060 return ret; 3061} 3062 3063static int rtw_p2p_get_op_ch(struct net_device *dev, 3064 struct iw_request_info *info, 3065 union iwreq_data *wrqu, char *extra) 3066 3067{ 3068 int ret = 0; 3069 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3070 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3071 3072 DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel); 3073 3074 sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel); 3075 wrqu->data.length = strlen(extra); 3076 return ret; 3077} 3078 3079static int rtw_p2p_get_wps_configmethod(struct net_device *dev, 3080 struct iw_request_info *info, 3081 union iwreq_data *wrqu, char *extra) 3082{ 3083 int ret = 0; 3084 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3085 u8 peerMAC[ETH_ALEN] = {0x00}; 3086 int jj, kk; 3087 u8 peerMACStr[17] = {0x00}; 3088 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3089 struct list_head *plist, *phead; 3090 struct __queue *queue = &(pmlmepriv->scanned_queue); 3091 struct wlan_network *pnetwork = NULL; 3092 u8 blnMatch = 0; 3093 u16 attr_content = 0; 3094 uint attr_contentlen = 0; 3095 /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */ 3096 u8 attr_content_str[6 + 17] = {0x00}; 3097 3098 /* Commented by Albert 20110727 */ 3099 /* The input data is the MAC address which the application wants to know its WPS config method. */ 3100 /* After knowing its WPS config method, the application can decide the config method for provisioning discovery. */ 3101 /* Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */ 3102 3103 DBG_88E("[%s] data = %s\n", __func__, (char *)extra); 3104 if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17)) 3105 return -EFAULT; 3106 3107 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3108 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); 3109 3110 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3111 3112 phead = get_list_head(queue); 3113 plist = get_next(phead); 3114 3115 while (1) { 3116 if (rtw_end_of_queue_search(phead, plist) == true) 3117 break; 3118 3119 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3120 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { 3121 u8 *wpsie; 3122 uint wpsie_len = 0; 3123 __be16 be_tmp; 3124 3125 /* The mac address is matched. */ 3126 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len); 3127 if (wpsie) { 3128 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen); 3129 if (attr_contentlen) { 3130 attr_content = be16_to_cpu(be_tmp); 3131 sprintf(attr_content_str, "\n\nM =%.4d", attr_content); 3132 blnMatch = 1; 3133 } 3134 } 3135 break; 3136 } 3137 plist = get_next(plist); 3138 } 3139 3140 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3141 3142 if (!blnMatch) 3143 sprintf(attr_content_str, "\n\nM = 0000"); 3144 3145 if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17)) 3146 return -EFAULT; 3147 return ret; 3148} 3149 3150static int rtw_p2p_get_go_device_address(struct net_device *dev, 3151 struct iw_request_info *info, 3152 union iwreq_data *wrqu, char *extra) 3153{ 3154 int ret = 0; 3155 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3156 u8 peerMAC[ETH_ALEN] = {0x00}; 3157 int jj, kk; 3158 u8 peerMACStr[17] = {0x00}; 3159 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3160 struct list_head *plist, *phead; 3161 struct __queue *queue = &(pmlmepriv->scanned_queue); 3162 struct wlan_network *pnetwork = NULL; 3163 u8 blnMatch = 0; 3164 u8 *p2pie; 3165 uint p2pielen = 0, attr_contentlen = 0; 3166 u8 attr_content[100] = {0x00}; 3167 3168 u8 go_devadd_str[17 + 10] = {0x00}; 3169 /* +10 is for the str "go_devadd =", we have to clear it at wrqu->data.pointer */ 3170 3171 /* Commented by Albert 20121209 */ 3172 /* The input data is the GO's interface address which the application wants to know its device address. */ 3173 /* Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */ 3174 3175 DBG_88E("[%s] data = %s\n", __func__, (char *)extra); 3176 if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17)) 3177 return -EFAULT; 3178 3179 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3180 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); 3181 3182 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3183 3184 phead = get_list_head(queue); 3185 plist = get_next(phead); 3186 3187 while (1) { 3188 if (rtw_end_of_queue_search(phead, plist) == true) 3189 break; 3190 3191 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3192 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { 3193 /* Commented by Albert 2011/05/18 */ 3194 /* Match the device address located in the P2P IE */ 3195 /* This is for the case that the P2P device address is not the same as the P2P interface address. */ 3196 3197 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); 3198 if (p2pie) { 3199 while (p2pie) { 3200 /* The P2P Device ID attribute is included in the Beacon frame. */ 3201 /* The P2P Device Info attribute is included in the probe response frame. */ 3202 3203 _rtw_memset(attr_content, 0x00, 100); 3204 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) { 3205 /* Handle the P2P Device ID attribute of Beacon first */ 3206 blnMatch = 1; 3207 break; 3208 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) { 3209 /* Handle the P2P Device Info attribute of probe response */ 3210 blnMatch = 1; 3211 break; 3212 } 3213 3214 /* Get the next P2P IE */ 3215 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen); 3216 } 3217 } 3218 } 3219 3220 plist = get_next(plist); 3221 } 3222 3223 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3224 3225 if (!blnMatch) 3226 sprintf(go_devadd_str, "\n\ndev_add = NULL"); 3227 else 3228 sprintf(go_devadd_str, "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", 3229 attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]); 3230 3231 if (copy_to_user(wrqu->data.pointer, go_devadd_str, 10 + 17)) 3232 return -EFAULT; 3233 return ret; 3234} 3235 3236static int rtw_p2p_get_device_type(struct net_device *dev, 3237 struct iw_request_info *info, 3238 union iwreq_data *wrqu, char *extra) 3239{ 3240 int ret = 0; 3241 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3242 u8 peerMAC[ETH_ALEN] = {0x00}; 3243 int jj, kk; 3244 u8 peerMACStr[17] = {0x00}; 3245 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3246 struct list_head *plist, *phead; 3247 struct __queue *queue = &(pmlmepriv->scanned_queue); 3248 struct wlan_network *pnetwork = NULL; 3249 u8 blnMatch = 0; 3250 u8 dev_type[8] = {0x00}; 3251 uint dev_type_len = 0; 3252 u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */ 3253 3254 /* Commented by Albert 20121209 */ 3255 /* The input data is the MAC address which the application wants to know its device type. */ 3256 /* Such user interface could know the device type. */ 3257 /* Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */ 3258 3259 DBG_88E("[%s] data = %s\n", __func__, (char *)extra); 3260 if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17)) 3261 return -EFAULT; 3262 3263 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3264 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); 3265 3266 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3267 3268 phead = get_list_head(queue); 3269 plist = get_next(phead); 3270 3271 while (1) { 3272 if (rtw_end_of_queue_search(phead, plist) == true) 3273 break; 3274 3275 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3276 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { 3277 u8 *wpsie; 3278 uint wpsie_len = 0; 3279 3280 /* The mac address is matched. */ 3281 3282 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], 3283 pnetwork->network.IELength - 12, 3284 NULL, &wpsie_len); 3285 if (wpsie) { 3286 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len); 3287 if (dev_type_len) { 3288 u16 type = 0; 3289 __be16 be_tmp; 3290 3291 memcpy(&be_tmp, dev_type, 2); 3292 type = be16_to_cpu(be_tmp); 3293 sprintf(dev_type_str, "\n\nN =%.2d", type); 3294 blnMatch = 1; 3295 } 3296 } 3297 break; 3298 } 3299 3300 plist = get_next(plist); 3301 } 3302 3303 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3304 3305 if (!blnMatch) 3306 sprintf(dev_type_str, "\n\nN = 00"); 3307 3308 if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) { 3309 return -EFAULT; 3310 } 3311 3312 return ret; 3313} 3314 3315static int rtw_p2p_get_device_name(struct net_device *dev, 3316 struct iw_request_info *info, 3317 union iwreq_data *wrqu, char *extra) 3318{ 3319 int ret = 0; 3320 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3321 u8 peerMAC[ETH_ALEN] = {0x00}; 3322 int jj, kk; 3323 u8 peerMACStr[17] = {0x00}; 3324 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3325 struct list_head *plist, *phead; 3326 struct __queue *queue = &(pmlmepriv->scanned_queue); 3327 struct wlan_network *pnetwork = NULL; 3328 u8 blnMatch = 0; 3329 u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00}; 3330 uint dev_len = 0; 3331 u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */ 3332 3333 /* Commented by Albert 20121225 */ 3334 /* The input data is the MAC address which the application wants to know its device name. */ 3335 /* Such user interface could show peer device's device name instead of ssid. */ 3336 /* Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */ 3337 3338 DBG_88E("[%s] data = %s\n", __func__, (char *)extra); 3339 if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17)) 3340 return -EFAULT; 3341 3342 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3343 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); 3344 3345 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3346 3347 phead = get_list_head(queue); 3348 plist = get_next(phead); 3349 3350 while (1) { 3351 if (rtw_end_of_queue_search(phead, plist) == true) 3352 break; 3353 3354 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3355 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { 3356 u8 *wpsie; 3357 uint wpsie_len = 0; 3358 3359 /* The mac address is matched. */ 3360 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len); 3361 if (wpsie) { 3362 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len); 3363 if (dev_len) { 3364 sprintf(dev_name_str, "\n\nN =%s", dev_name); 3365 blnMatch = 1; 3366 } 3367 } 3368 break; 3369 } 3370 3371 plist = get_next(plist); 3372 } 3373 3374 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3375 3376 if (!blnMatch) 3377 sprintf(dev_name_str, "\n\nN = 0000"); 3378 3379 if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17))) 3380 return -EFAULT; 3381 return ret; 3382} 3383 3384static int rtw_p2p_get_invitation_procedure(struct net_device *dev, 3385 struct iw_request_info *info, 3386 union iwreq_data *wrqu, char *extra) 3387{ 3388 int ret = 0; 3389 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3390 u8 peerMAC[ETH_ALEN] = {0x00}; 3391 int jj, kk; 3392 u8 peerMACStr[17] = {0x00}; 3393 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3394 struct list_head *plist, *phead; 3395 struct __queue *queue = &(pmlmepriv->scanned_queue); 3396 struct wlan_network *pnetwork = NULL; 3397 u8 blnMatch = 0; 3398 u8 *p2pie; 3399 uint p2pielen = 0, attr_contentlen = 0; 3400 u8 attr_content[2] = {0x00}; 3401 3402 u8 inv_proc_str[17 + 8] = {0x00}; 3403 /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */ 3404 3405 /* Commented by Ouden 20121226 */ 3406 /* The application wants to know P2P initiation procedure is supported or not. */ 3407 /* Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */ 3408 3409 DBG_88E("[%s] data = %s\n", __func__, (char *)extra); 3410 if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17)) 3411 return -EFAULT; 3412 3413 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3414 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]); 3415 3416 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3417 3418 phead = get_list_head(queue); 3419 plist = get_next(phead); 3420 3421 while (1) { 3422 if (rtw_end_of_queue_search(phead, plist) == true) 3423 break; 3424 3425 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3426 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { 3427 /* Commented by Albert 20121226 */ 3428 /* Match the device address located in the P2P IE */ 3429 /* This is for the case that the P2P device address is not the same as the P2P interface address. */ 3430 3431 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); 3432 if (p2pie) { 3433 while (p2pie) { 3434 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) { 3435 /* Handle the P2P capability attribute */ 3436 blnMatch = 1; 3437 break; 3438 } 3439 3440 /* Get the next P2P IE */ 3441 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen); 3442 } 3443 } 3444 } 3445 plist = get_next(plist); 3446 } 3447 3448 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3449 3450 if (!blnMatch) { 3451 sprintf(inv_proc_str, "\nIP =-1"); 3452 } else { 3453 if (attr_content[0] & 0x20) 3454 sprintf(inv_proc_str, "\nIP = 1"); 3455 else 3456 sprintf(inv_proc_str, "\nIP = 0"); 3457 } 3458 if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17)) 3459 return -EFAULT; 3460 return ret; 3461} 3462 3463static int rtw_p2p_connect(struct net_device *dev, 3464 struct iw_request_info *info, 3465 union iwreq_data *wrqu, char *extra) 3466{ 3467 int ret = 0; 3468 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3469 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3470 u8 peerMAC[ETH_ALEN] = {0x00}; 3471 int jj, kk; 3472 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3473 struct list_head *plist, *phead; 3474 struct __queue *queue = &(pmlmepriv->scanned_queue); 3475 struct wlan_network *pnetwork = NULL; 3476 uint uintPeerChannel = 0; 3477 3478 /* Commented by Albert 20110304 */ 3479 /* The input data contains two informations. */ 3480 /* 1. First information is the MAC address which wants to formate with */ 3481 /* 2. Second information is the WPS PINCode or "pbc" string for push button method */ 3482 /* Format: 00:E0:4C:00:00:05 */ 3483 /* Format: 00:E0:4C:00:00:05 */ 3484 3485 DBG_88E("[%s] data = %s\n", __func__, extra); 3486 3487 if (pwdinfo->p2p_state == P2P_STATE_NONE) { 3488 DBG_88E("[%s] WiFi Direct is disable!\n", __func__); 3489 return ret; 3490 } 3491 3492 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) 3493 return -1; 3494 3495 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3496 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]); 3497 3498 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3499 3500 phead = get_list_head(queue); 3501 plist = get_next(phead); 3502 3503 while (1) { 3504 if (rtw_end_of_queue_search(phead, plist) == true) 3505 break; 3506 3507 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3508 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) { 3509 uintPeerChannel = pnetwork->network.Configuration.DSConfig; 3510 break; 3511 } 3512 3513 plist = get_next(plist); 3514 } 3515 3516 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3517 3518 if (uintPeerChannel) { 3519 _rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info)); 3520 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info)); 3521 3522 pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel; 3523 memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN); 3524 pwdinfo->nego_req_info.benable = true; 3525 3526 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); 3527 if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) { 3528 /* Restore to the listen state if the current p2p state is not nego OK */ 3529 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); 3530 } 3531 3532 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); 3533 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING); 3534 3535 DBG_88E("[%s] Start PreTx Procedure!\n", __func__); 3536 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); 3537 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT); 3538 } else { 3539 DBG_88E("[%s] Not Found in Scanning Queue~\n", __func__); 3540 ret = -1; 3541 } 3542 return ret; 3543} 3544 3545static int rtw_p2p_invite_req(struct net_device *dev, 3546 struct iw_request_info *info, 3547 union iwreq_data *wrqu, char *extra) 3548{ 3549 int ret = 0; 3550 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3551 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3552 int jj, kk; 3553 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3554 struct list_head *plist, *phead; 3555 struct __queue *queue = &(pmlmepriv->scanned_queue); 3556 struct wlan_network *pnetwork = NULL; 3557 uint uintPeerChannel = 0; 3558 u8 attr_content[50] = {0x00}; 3559 u8 *p2pie; 3560 uint p2pielen = 0, attr_contentlen = 0; 3561 struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info; 3562 3563 /* The input data contains two informations. */ 3564 /* 1. First information is the P2P device address which you want to send to. */ 3565 /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */ 3566 /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */ 3567 /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */ 3568 3569 DBG_88E("[%s] data = %s\n", __func__, extra); 3570 3571 if (wrqu->data.length <= 37) { 3572 DBG_88E("[%s] Wrong format!\n", __func__); 3573 return ret; 3574 } 3575 3576 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { 3577 DBG_88E("[%s] WiFi Direct is disable!\n", __func__); 3578 return ret; 3579 } else { 3580 /* Reset the content of struct tx_invite_req_info */ 3581 pinvite_req_info->benable = false; 3582 _rtw_memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN); 3583 _rtw_memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN); 3584 pinvite_req_info->ssidlen = 0x00; 3585 pinvite_req_info->operating_ch = pwdinfo->operating_channel; 3586 _rtw_memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN); 3587 pinvite_req_info->token = 3; 3588 } 3589 3590 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3591 pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]); 3592 3593 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3594 3595 phead = get_list_head(queue); 3596 plist = get_next(phead); 3597 3598 while (1) { 3599 if (rtw_end_of_queue_search(phead, plist) == true) 3600 break; 3601 3602 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3603 3604 /* Commented by Albert 2011/05/18 */ 3605 /* Match the device address located in the P2P IE */ 3606 /* This is for the case that the P2P device address is not the same as the P2P interface address. */ 3607 3608 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); 3609 if (p2pie) { 3610 /* The P2P Device ID attribute is included in the Beacon frame. */ 3611 /* The P2P Device Info attribute is included in the probe response frame. */ 3612 3613 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) { 3614 /* Handle the P2P Device ID attribute of Beacon first */ 3615 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) { 3616 uintPeerChannel = pnetwork->network.Configuration.DSConfig; 3617 break; 3618 } 3619 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) { 3620 /* Handle the P2P Device Info attribute of probe response */ 3621 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) { 3622 uintPeerChannel = pnetwork->network.Configuration.DSConfig; 3623 break; 3624 } 3625 } 3626 } 3627 plist = get_next(plist); 3628 } 3629 3630 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3631 3632 if (uintPeerChannel) { 3633 /* Store the GO's bssid */ 3634 for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3) 3635 pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]); 3636 3637 /* Store the GO's ssid */ 3638 pinvite_req_info->ssidlen = wrqu->data.length - 36; 3639 memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen); 3640 pinvite_req_info->benable = true; 3641 pinvite_req_info->peer_ch = uintPeerChannel; 3642 3643 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); 3644 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ); 3645 3646 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); 3647 3648 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); 3649 3650 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT); 3651 } else { 3652 DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__); 3653 } 3654 return ret; 3655} 3656 3657static int rtw_p2p_set_persistent(struct net_device *dev, 3658 struct iw_request_info *info, 3659 union iwreq_data *wrqu, char *extra) 3660{ 3661 int ret = 0; 3662 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3663 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3664 3665 /* The input data is 0 or 1 */ 3666 /* 0: disable persistent group functionality */ 3667 /* 1: enable persistent group founctionality */ 3668 3669 DBG_88E("[%s] data = %s\n", __func__, extra); 3670 3671 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) { 3672 DBG_88E("[%s] WiFi Direct is disable!\n", __func__); 3673 return ret; 3674 } else { 3675 if (extra[0] == '0') /* Disable the persistent group function. */ 3676 pwdinfo->persistent_supported = false; 3677 else if (extra[0] == '1') /* Enable the persistent group function. */ 3678 pwdinfo->persistent_supported = true; 3679 else 3680 pwdinfo->persistent_supported = false; 3681 } 3682 pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported); 3683 return ret; 3684} 3685 3686static int rtw_p2p_prov_disc(struct net_device *dev, 3687 struct iw_request_info *info, 3688 union iwreq_data *wrqu, char *extra) 3689{ 3690 int ret = 0; 3691 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3692 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3693 u8 peerMAC[ETH_ALEN] = {0x00}; 3694 int jj, kk; 3695 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3696 struct list_head *plist, *phead; 3697 struct __queue *queue = &(pmlmepriv->scanned_queue); 3698 struct wlan_network *pnetwork = NULL; 3699 uint uintPeerChannel = 0; 3700 u8 attr_content[100] = {0x00}; 3701 u8 *p2pie; 3702 uint p2pielen = 0, attr_contentlen = 0; 3703 3704 /* The input data contains two informations. */ 3705 /* 1. First information is the MAC address which wants to issue the provisioning discovery request frame. */ 3706 /* 2. Second information is the WPS configuration method which wants to discovery */ 3707 /* Format: 00:E0:4C:00:00:05_display */ 3708 /* Format: 00:E0:4C:00:00:05_keypad */ 3709 /* Format: 00:E0:4C:00:00:05_pbc */ 3710 /* Format: 00:E0:4C:00:00:05_label */ 3711 3712 DBG_88E("[%s] data = %s\n", __func__, extra); 3713 3714 if (pwdinfo->p2p_state == P2P_STATE_NONE) { 3715 DBG_88E("[%s] WiFi Direct is disable!\n", __func__); 3716 return ret; 3717 } else { 3718 /* Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */ 3719 _rtw_memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN); 3720 _rtw_memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN); 3721 _rtw_memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid)); 3722 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0; 3723 pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0; 3724 pwdinfo->tx_prov_disc_info.benable = false; 3725 } 3726 3727 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) 3728 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]); 3729 3730 if (!memcmp(&extra[18], "display", 7)) { 3731 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA; 3732 } else if (!memcmp(&extra[18], "keypad", 7)) { 3733 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD; 3734 } else if (!memcmp(&extra[18], "pbc", 3)) { 3735 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON; 3736 } else if (!memcmp(&extra[18], "label", 5)) { 3737 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL; 3738 } else { 3739 DBG_88E("[%s] Unknown WPS config methodn", __func__); 3740 return ret; 3741 } 3742 3743 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3744 3745 phead = get_list_head(queue); 3746 plist = get_next(phead); 3747 3748 while (1) { 3749 if (rtw_end_of_queue_search(phead, plist) == true) 3750 break; 3751 3752 if (uintPeerChannel != 0) 3753 break; 3754 3755 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 3756 3757 /* Commented by Albert 2011/05/18 */ 3758 /* Match the device address located in the P2P IE */ 3759 /* This is for the case that the P2P device address is not the same as the P2P interface address. */ 3760 3761 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen); 3762 if (p2pie) { 3763 while (p2pie) { 3764 /* The P2P Device ID attribute is included in the Beacon frame. */ 3765 /* The P2P Device Info attribute is included in the probe response frame. */ 3766 3767 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) { 3768 /* Handle the P2P Device ID attribute of Beacon first */ 3769 if (!memcmp(attr_content, peerMAC, ETH_ALEN)) { 3770 uintPeerChannel = pnetwork->network.Configuration.DSConfig; 3771 break; 3772 } 3773 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) { 3774 /* Handle the P2P Device Info attribute of probe response */ 3775 if (!memcmp(attr_content, peerMAC, ETH_ALEN)) { 3776 uintPeerChannel = pnetwork->network.Configuration.DSConfig; 3777 break; 3778 } 3779 } 3780 3781 /* Get the next P2P IE */ 3782 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen); 3783 } 3784 } 3785 3786 plist = get_next(plist); 3787 } 3788 3789 spin_unlock_bh(&pmlmepriv->scanned_queue.lock); 3790 3791 if (uintPeerChannel) { 3792 DBG_88E("[%s] peer channel: %d!\n", __func__, uintPeerChannel); 3793 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN); 3794 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN); 3795 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel; 3796 pwdinfo->tx_prov_disc_info.benable = true; 3797 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); 3798 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ); 3799 3800 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { 3801 memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid)); 3802 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { 3803 memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN); 3804 pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN; 3805 } 3806 3807 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); 3808 3809 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); 3810 3811 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT); 3812 } else { 3813 DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__); 3814 } 3815 return ret; 3816} 3817 3818/* This function is used to inform the driver the user had specified the pin code value or pbc */ 3819/* to application. */ 3820 3821static int rtw_p2p_got_wpsinfo(struct net_device *dev, 3822 struct iw_request_info *info, 3823 union iwreq_data *wrqu, char *extra) 3824{ 3825 int ret = 0; 3826 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3827 struct wifidirect_info *pwdinfo = &(padapter->wdinfo); 3828 3829 DBG_88E("[%s] data = %s\n", __func__, extra); 3830 /* Added by Albert 20110328 */ 3831 /* if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */ 3832 /* if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */ 3833 /* if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */ 3834 /* if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */ 3835 3836 if (*extra == '0') 3837 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO; 3838 else if (*extra == '1') 3839 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN; 3840 else if (*extra == '2') 3841 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN; 3842 else if (*extra == '3') 3843 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC; 3844 else 3845 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO; 3846 return ret; 3847} 3848 3849#endif /* CONFIG_88EU_P2P */ 3850 3851static int rtw_p2p_set(struct net_device *dev, 3852 struct iw_request_info *info, 3853 union iwreq_data *wrqu, char *extra) 3854{ 3855 int ret = 0; 3856 3857#ifdef CONFIG_88EU_P2P 3858 DBG_88E("[%s] extra = %s\n", __func__, extra); 3859 if (!memcmp(extra, "enable =", 7)) { 3860 rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]); 3861 } else if (!memcmp(extra, "setDN =", 6)) { 3862 wrqu->data.length -= 6; 3863 rtw_p2p_setDN(dev, info, wrqu, &extra[6]); 3864 } else if (!memcmp(extra, "profilefound =", 13)) { 3865 wrqu->data.length -= 13; 3866 rtw_p2p_profilefound(dev, info, wrqu, &extra[13]); 3867 } else if (!memcmp(extra, "prov_disc =", 10)) { 3868 wrqu->data.length -= 10; 3869 rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]); 3870 } else if (!memcmp(extra, "nego =", 5)) { 3871 wrqu->data.length -= 5; 3872 rtw_p2p_connect(dev, info, wrqu, &extra[5]); 3873 } else if (!memcmp(extra, "intent =", 7)) { 3874 /* Commented by Albert 2011/03/23 */ 3875 /* The wrqu->data.length will include the null character */ 3876 /* So, we will decrease 7 + 1 */ 3877 wrqu->data.length -= 8; 3878 rtw_p2p_set_intent(dev, info, wrqu, &extra[7]); 3879 } else if (!memcmp(extra, "ssid =", 5)) { 3880 wrqu->data.length -= 5; 3881 rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]); 3882 } else if (!memcmp(extra, "got_wpsinfo =", 12)) { 3883 wrqu->data.length -= 12; 3884 rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]); 3885 } else if (!memcmp(extra, "listen_ch =", 10)) { 3886 /* Commented by Albert 2011/05/24 */ 3887 /* The wrqu->data.length will include the null character */ 3888 /* So, we will decrease (10 + 1) */ 3889 wrqu->data.length -= 11; 3890 rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]); 3891 } else if (!memcmp(extra, "op_ch =", 6)) { 3892 /* Commented by Albert 2011/05/24 */ 3893 /* The wrqu->data.length will include the null character */ 3894 /* So, we will decrease (6 + 1) */ 3895 wrqu->data.length -= 7; 3896 rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]); 3897 } else if (!memcmp(extra, "invite =", 7)) { 3898 wrqu->data.length -= 8; 3899 rtw_p2p_invite_req(dev, info, wrqu, &extra[7]); 3900 } else if (!memcmp(extra, "persistent =", 11)) { 3901 wrqu->data.length -= 11; 3902 rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]); 3903 } 3904#endif /* CONFIG_88EU_P2P */ 3905 3906 return ret; 3907} 3908 3909static int rtw_p2p_get(struct net_device *dev, 3910 struct iw_request_info *info, 3911 union iwreq_data *wrqu, char *extra) 3912{ 3913 int ret = 0; 3914 3915#ifdef CONFIG_88EU_P2P 3916 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3917 3918 if (padapter->bShowGetP2PState) 3919 DBG_88E("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer); 3920 if (!memcmp(wrqu->data.pointer, "status", 6)) { 3921 rtw_p2p_get_status(dev, info, wrqu, extra); 3922 } else if (!memcmp(wrqu->data.pointer, "role", 4)) { 3923 rtw_p2p_get_role(dev, info, wrqu, extra); 3924 } else if (!memcmp(wrqu->data.pointer, "peer_ifa", 8)) { 3925 rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra); 3926 } else if (!memcmp(wrqu->data.pointer, "req_cm", 6)) { 3927 rtw_p2p_get_req_cm(dev, info, wrqu, extra); 3928 } else if (!memcmp(wrqu->data.pointer, "peer_deva", 9)) { 3929 /* Get the P2P device address when receiving the provision discovery request frame. */ 3930 rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra); 3931 } else if (!memcmp(wrqu->data.pointer, "group_id", 8)) { 3932 rtw_p2p_get_groupid(dev, info, wrqu, extra); 3933 } else if (!memcmp(wrqu->data.pointer, "peer_deva_inv", 9)) { 3934 /* Get the P2P device address when receiving the P2P Invitation request frame. */ 3935 rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra); 3936 } else if (!memcmp(wrqu->data.pointer, "op_ch", 5)) { 3937 rtw_p2p_get_op_ch(dev, info, wrqu, extra); 3938 } 3939#endif /* CONFIG_88EU_P2P */ 3940 return ret; 3941} 3942 3943static int rtw_p2p_get2(struct net_device *dev, 3944 struct iw_request_info *info, 3945 union iwreq_data *wrqu, char *extra) 3946{ 3947 int ret = 0; 3948 3949#ifdef CONFIG_88EU_P2P 3950 DBG_88E("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer); 3951 if (!memcmp(extra, "wpsCM =", 6)) { 3952 wrqu->data.length -= 6; 3953 rtw_p2p_get_wps_configmethod(dev, info, wrqu, &extra[6]); 3954 } else if (!memcmp(extra, "devN =", 5)) { 3955 wrqu->data.length -= 5; 3956 rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]); 3957 } else if (!memcmp(extra, "dev_type =", 9)) { 3958 wrqu->data.length -= 9; 3959 rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]); 3960 } else if (!memcmp(extra, "go_devadd =", 10)) { 3961 wrqu->data.length -= 10; 3962 rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]); 3963 } else if (!memcmp(extra, "InvProc =", 8)) { 3964 wrqu->data.length -= 8; 3965 rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]); 3966 } 3967 3968#endif /* CONFIG_88EU_P2P */ 3969 3970 return ret; 3971} 3972 3973static int rtw_cta_test_start(struct net_device *dev, 3974 struct iw_request_info *info, 3975 union iwreq_data *wrqu, char *extra) 3976{ 3977 int ret = 0; 3978 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 3979 DBG_88E("%s %s\n", __func__, extra); 3980 if (!strcmp(extra, "1")) 3981 padapter->in_cta_test = 1; 3982 else 3983 padapter->in_cta_test = 0; 3984 3985 if (padapter->in_cta_test) { 3986 u32 v = rtw_read32(padapter, REG_RCR); 3987 v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */ 3988 rtw_write32(padapter, REG_RCR, v); 3989 DBG_88E("enable RCR_ADF\n"); 3990 } else { 3991 u32 v = rtw_read32(padapter, REG_RCR); 3992 v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;/* RCR_ADF */ 3993 rtw_write32(padapter, REG_RCR, v); 3994 DBG_88E("disable RCR_ADF\n"); 3995 } 3996 return ret; 3997} 3998 3999static int rtw_rereg_nd_name(struct net_device *dev, 4000 struct iw_request_info *info, 4001 union iwreq_data *wrqu, char *extra) 4002{ 4003 int ret = 0; 4004 struct adapter *padapter = rtw_netdev_priv(dev); 4005 struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv; 4006 char new_ifname[IFNAMSIZ]; 4007 4008 if (rereg_priv->old_ifname[0] == 0) { 4009 char *reg_ifname; 4010 reg_ifname = padapter->registrypriv.if2name; 4011 4012 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ); 4013 rereg_priv->old_ifname[IFNAMSIZ-1] = 0; 4014 } 4015 4016 if (wrqu->data.length > IFNAMSIZ) 4017 return -EFAULT; 4018 4019 if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ)) 4020 return -EFAULT; 4021 4022 if (0 == strcmp(rereg_priv->old_ifname, new_ifname)) 4023 return ret; 4024 4025 DBG_88E("%s new_ifname:%s\n", __func__, new_ifname); 4026 ret = rtw_change_ifname(padapter, new_ifname); 4027 if (0 != ret) 4028 goto exit; 4029 4030 if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) { 4031 padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed; 4032 rtw_hal_sw_led_init(padapter); 4033 rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode); 4034 } 4035 4036 strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ); 4037 rereg_priv->old_ifname[IFNAMSIZ-1] = 0; 4038 4039 if (!memcmp(new_ifname, "disable%d", 9)) { 4040 DBG_88E("%s disable\n", __func__); 4041 /* free network queue for Android's timming issue */ 4042 rtw_free_network_queue(padapter, true); 4043 4044 /* close led */ 4045 rtw_led_control(padapter, LED_CTL_POWER_OFF); 4046 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed; 4047 padapter->ledpriv.bRegUseLed = false; 4048 rtw_hal_sw_led_deinit(padapter); 4049 4050 /* the interface is being "disabled", we can do deeper IPS */ 4051 rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); 4052 rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); 4053 } 4054exit: 4055 return ret; 4056} 4057 4058static void mac_reg_dump(struct adapter *padapter) 4059{ 4060 int i, j = 1; 4061 pr_info("\n ======= MAC REG =======\n"); 4062 for (i = 0x0; i < 0x300; i += 4) { 4063 if (j%4 == 1) 4064 pr_info("0x%02x", i); 4065 pr_info(" 0x%08x ", rtw_read32(padapter, i)); 4066 if ((j++)%4 == 0) 4067 pr_info("\n"); 4068 } 4069 for (i = 0x400; i < 0x800; i += 4) { 4070 if (j%4 == 1) 4071 pr_info("0x%02x", i); 4072 pr_info(" 0x%08x ", rtw_read32(padapter, i)); 4073 if ((j++)%4 == 0) 4074 pr_info("\n"); 4075 } 4076} 4077 4078static void bb_reg_dump(struct adapter *padapter) 4079{ 4080 int i, j = 1; 4081 pr_info("\n ======= BB REG =======\n"); 4082 for (i = 0x800; i < 0x1000; i += 4) { 4083 if (j%4 == 1) 4084 pr_info("0x%02x", i); 4085 4086 pr_info(" 0x%08x ", rtw_read32(padapter, i)); 4087 if ((j++)%4 == 0) 4088 pr_info("\n"); 4089 } 4090} 4091 4092static void rf_reg_dump(struct adapter *padapter) 4093{ 4094 int i, j = 1, path; 4095 u32 value; 4096 u8 rf_type, path_nums = 0; 4097 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); 4098 4099 pr_info("\n ======= RF REG =======\n"); 4100 if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) 4101 path_nums = 1; 4102 else 4103 path_nums = 2; 4104 4105 for (path = 0; path < path_nums; path++) { 4106 pr_info("\nRF_Path(%x)\n", path); 4107 for (i = 0; i < 0x100; i++) { 4108 value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); 4109 if (j%4 == 1) 4110 pr_info("0x%02x ", i); 4111 pr_info(" 0x%08x ", value); 4112 if ((j++)%4 == 0) 4113 pr_info("\n"); 4114 } 4115 } 4116} 4117 4118static int rtw_dbg_port(struct net_device *dev, 4119 struct iw_request_info *info, 4120 union iwreq_data *wrqu, char *extra) 4121{ 4122 int ret = 0; 4123 u8 major_cmd, minor_cmd; 4124 u16 arg; 4125 s32 extra_arg; 4126 u32 *pdata, val32; 4127 struct sta_info *psta; 4128 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4129 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4130 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4131 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4132 struct security_priv *psecuritypriv = &padapter->securitypriv; 4133 struct wlan_network *cur_network = &(pmlmepriv->cur_network); 4134 struct sta_priv *pstapriv = &padapter->stapriv; 4135 4136 pdata = (u32 *)&wrqu->data; 4137 4138 val32 = *pdata; 4139 arg = (u16)(val32 & 0x0000ffff); 4140 major_cmd = (u8)(val32 >> 24); 4141 minor_cmd = (u8)((val32 >> 16) & 0x00ff); 4142 4143 extra_arg = *(pdata+1); 4144 4145 switch (major_cmd) { 4146 case 0x70:/* read_reg */ 4147 switch (minor_cmd) { 4148 case 1: 4149 DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg)); 4150 break; 4151 case 2: 4152 DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg)); 4153 break; 4154 case 4: 4155 DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg)); 4156 break; 4157 } 4158 break; 4159 case 0x71:/* write_reg */ 4160 switch (minor_cmd) { 4161 case 1: 4162 rtw_write8(padapter, arg, extra_arg); 4163 DBG_88E("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg)); 4164 break; 4165 case 2: 4166 rtw_write16(padapter, arg, extra_arg); 4167 DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg)); 4168 break; 4169 case 4: 4170 rtw_write32(padapter, arg, extra_arg); 4171 DBG_88E("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg)); 4172 break; 4173 } 4174 break; 4175 case 0x72:/* read_bb */ 4176 DBG_88E("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff)); 4177 break; 4178 case 0x73:/* write_bb */ 4179 rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg); 4180 DBG_88E("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff)); 4181 break; 4182 case 0x74:/* read_rf */ 4183 DBG_88E("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)); 4184 break; 4185 case 0x75:/* write_rf */ 4186 rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg); 4187 DBG_88E("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)); 4188 break; 4189 4190 case 0x76: 4191 switch (minor_cmd) { 4192 case 0x00: /* normal mode, */ 4193 padapter->recvpriv.is_signal_dbg = 0; 4194 break; 4195 case 0x01: /* dbg mode */ 4196 padapter->recvpriv.is_signal_dbg = 1; 4197 extra_arg = extra_arg > 100 ? 100 : extra_arg; 4198 extra_arg = extra_arg < 0 ? 0 : extra_arg; 4199 padapter->recvpriv.signal_strength_dbg = extra_arg; 4200 break; 4201 } 4202 break; 4203 case 0x78: /* IOL test */ 4204 switch (minor_cmd) { 4205 case 0x04: /* LLT table initialization test */ 4206 { 4207 u8 page_boundary = 0xf9; 4208 struct xmit_frame *xmit_frame; 4209 4210 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); 4211 if (xmit_frame == NULL) { 4212 ret = -ENOMEM; 4213 break; 4214 } 4215 4216 rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary); 4217 4218 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0)) 4219 ret = -EPERM; 4220 } 4221 break; 4222 case 0x05: /* blink LED test */ 4223 { 4224 u16 reg = 0x4c; 4225 u32 blink_num = 50; 4226 u32 blink_delay_ms = 200; 4227 int i; 4228 struct xmit_frame *xmit_frame; 4229 4230 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); 4231 if (xmit_frame == NULL) { 4232 ret = -ENOMEM; 4233 break; 4234 } 4235 4236 for (i = 0; i < blink_num; i++) { 4237 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff); 4238 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms); 4239 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff); 4240 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms); 4241 } 4242 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200, 0)) 4243 ret = -EPERM; 4244 } 4245 break; 4246 4247 case 0x06: /* continuous write byte test */ 4248 { 4249 u16 reg = arg; 4250 u16 start_value = 0; 4251 u32 write_num = extra_arg; 4252 int i; 4253 u8 final; 4254 struct xmit_frame *xmit_frame; 4255 4256 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); 4257 if (xmit_frame == NULL) { 4258 ret = -ENOMEM; 4259 break; 4260 } 4261 4262 for (i = 0; i < write_num; i++) 4263 rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value, 0xFF); 4264 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0)) 4265 ret = -EPERM; 4266 4267 final = rtw_read8(padapter, reg); 4268 if (start_value+write_num-1 == final) 4269 DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final); 4270 else 4271 DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final); 4272 } 4273 break; 4274 4275 case 0x07: /* continuous write word test */ 4276 { 4277 u16 reg = arg; 4278 u16 start_value = 200; 4279 u32 write_num = extra_arg; 4280 4281 int i; 4282 u16 final; 4283 struct xmit_frame *xmit_frame; 4284 4285 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); 4286 if (xmit_frame == NULL) { 4287 ret = -ENOMEM; 4288 break; 4289 } 4290 4291 for (i = 0; i < write_num; i++) 4292 rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value, 0xFFFF); 4293 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0)) 4294 ret = -EPERM; 4295 4296 final = rtw_read16(padapter, reg); 4297 if (start_value+write_num-1 == final) 4298 DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final); 4299 else 4300 DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final); 4301 } 4302 break; 4303 case 0x08: /* continuous write dword test */ 4304 { 4305 u16 reg = arg; 4306 u32 start_value = 0x110000c7; 4307 u32 write_num = extra_arg; 4308 4309 int i; 4310 u32 final; 4311 struct xmit_frame *xmit_frame; 4312 4313 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter); 4314 if (xmit_frame == NULL) { 4315 ret = -ENOMEM; 4316 break; 4317 } 4318 4319 for (i = 0; i < write_num; i++) 4320 rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value, 0xFFFFFFFF); 4321 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0)) 4322 ret = -EPERM; 4323 4324 final = rtw_read32(padapter, reg); 4325 if (start_value+write_num-1 == final) 4326 DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", 4327 reg, write_num, start_value, final); 4328 else 4329 DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", 4330 reg, write_num, start_value, final); 4331 } 4332 break; 4333 } 4334 break; 4335 case 0x79: 4336 { 4337 /* 4338 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15 4339 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15 4340 */ 4341 u8 value = extra_arg & 0x0f; 4342 u8 sign = minor_cmd; 4343 u16 write_value = 0; 4344 4345 DBG_88E("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value); 4346 4347 if (sign) 4348 value = value | 0x10; 4349 4350 write_value = value | (value << 5); 4351 rtw_write16(padapter, 0x6d9, write_value); 4352 } 4353 break; 4354 case 0x7a: 4355 receive_disconnect(padapter, pmlmeinfo->network.MacAddress 4356 , WLAN_REASON_EXPIRATION_CHK); 4357 break; 4358 case 0x7F: 4359 switch (minor_cmd) { 4360 case 0x0: 4361 DBG_88E("fwstate = 0x%x\n", get_fwstate(pmlmepriv)); 4362 break; 4363 case 0x01: 4364 DBG_88E("auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n", 4365 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, 4366 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus); 4367 break; 4368 case 0x02: 4369 DBG_88E("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state); 4370 break; 4371 case 0x03: 4372 DBG_88E("qos_option =%d\n", pmlmepriv->qospriv.qos_option); 4373 DBG_88E("ht_option =%d\n", pmlmepriv->htpriv.ht_option); 4374 break; 4375 case 0x04: 4376 DBG_88E("cur_ch =%d\n", pmlmeext->cur_channel); 4377 DBG_88E("cur_bw =%d\n", pmlmeext->cur_bwmode); 4378 DBG_88E("cur_ch_off =%d\n", pmlmeext->cur_ch_offset); 4379 break; 4380 case 0x05: 4381 psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); 4382 if (psta) { 4383 int i; 4384 struct recv_reorder_ctrl *preorder_ctrl; 4385 4386 DBG_88E("SSID =%s\n", cur_network->network.Ssid.Ssid); 4387 DBG_88E("sta's macaddr: %pM\n", psta->hwaddr); 4388 DBG_88E("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); 4389 DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self); 4390 DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); 4391 DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); 4392 DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); 4393 DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable); 4394 DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); 4395 for (i = 0; i < 16; i++) { 4396 preorder_ctrl = &psta->recvreorder_ctrl[i]; 4397 if (preorder_ctrl->enable) 4398 DBG_88E("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq); 4399 } 4400 } else { 4401 DBG_88E("can't get sta's macaddr, cur_network's macaddr:%pM\n", (cur_network->network.MacAddress)); 4402 } 4403 break; 4404 case 0x06: 4405 { 4406 u32 ODMFlag; 4407 rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag)); 4408 DBG_88E("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg); 4409 ODMFlag = (u32)(0x0f&arg); 4410 DBG_88E("(A)DMFlag = 0x%x\n", ODMFlag); 4411 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag)); 4412 } 4413 break; 4414 case 0x07: 4415 DBG_88E("bSurpriseRemoved =%d, bDriverStopped =%d\n", 4416 padapter->bSurpriseRemoved, padapter->bDriverStopped); 4417 break; 4418 case 0x08: 4419 { 4420 struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 4421 struct recv_priv *precvpriv = &padapter->recvpriv; 4422 4423 DBG_88E("free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d, free_xmit_extbuf_cnt =%d\n", 4424 pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt); 4425 DBG_88E("rx_urb_pending_cn =%d\n", precvpriv->rx_pending_cnt); 4426 } 4427 break; 4428 case 0x09: 4429 { 4430 int i, j; 4431 struct list_head *plist, *phead; 4432 struct recv_reorder_ctrl *preorder_ctrl; 4433 4434#ifdef CONFIG_88EU_AP_MODE 4435 DBG_88E("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); 4436#endif 4437 spin_lock_bh(&pstapriv->sta_hash_lock); 4438 4439 for (i = 0; i < NUM_STA; i++) { 4440 phead = &(pstapriv->sta_hash[i]); 4441 plist = get_next(phead); 4442 4443 while ((rtw_end_of_queue_search(phead, plist)) == false) { 4444 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); 4445 4446 plist = get_next(plist); 4447 4448 if (extra_arg == psta->aid) { 4449 DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr)); 4450 DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self); 4451 DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); 4452 DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); 4453 DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); 4454 DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable); 4455 DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); 4456 4457#ifdef CONFIG_88EU_AP_MODE 4458 DBG_88E("capability = 0x%x\n", psta->capability); 4459 DBG_88E("flags = 0x%x\n", psta->flags); 4460 DBG_88E("wpa_psk = 0x%x\n", psta->wpa_psk); 4461 DBG_88E("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher); 4462 DBG_88E("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher); 4463 DBG_88E("qos_info = 0x%x\n", psta->qos_info); 4464#endif 4465 DBG_88E("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy); 4466 4467 for (j = 0; j < 16; j++) { 4468 preorder_ctrl = &psta->recvreorder_ctrl[j]; 4469 if (preorder_ctrl->enable) 4470 DBG_88E("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq); 4471 } 4472 } 4473 } 4474 } 4475 spin_unlock_bh(&pstapriv->sta_hash_lock); 4476 } 4477 break; 4478 case 0x0c:/* dump rx/tx packet */ 4479 if (arg == 0) { 4480 DBG_88E("dump rx packet (%d)\n", extra_arg); 4481 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg)); 4482 } else if (arg == 1) { 4483 DBG_88E("dump tx packet (%d)\n", extra_arg); 4484 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg)); 4485 } 4486 break; 4487 case 0x0f: 4488 if (extra_arg == 0) { 4489 DBG_88E("###### silent reset test.......#####\n"); 4490 rtw_hal_sreset_reset(padapter); 4491 } 4492 break; 4493 case 0x15: 4494 { 4495 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; 4496 DBG_88E("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts); 4497 } 4498 break; 4499 case 0x10:/* driver version display */ 4500 DBG_88E("rtw driver version =%s\n", DRIVERVERSION); 4501 break; 4502 case 0x11: 4503 DBG_88E("turn %s Rx RSSI display function\n", (extra_arg == 1) ? "on" : "off"); 4504 padapter->bRxRSSIDisplay = extra_arg; 4505 rtw_hal_set_def_var(padapter, HW_DEF_FA_CNT_DUMP, &extra_arg); 4506 break; 4507 case 0x12: /* set rx_stbc */ 4508 { 4509 struct registry_priv *pregpriv = &padapter->registrypriv; 4510 /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */ 4511 /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */ 4512 if (pregpriv && 4513 (extra_arg == 0 || 4514 extra_arg == 1 || 4515 extra_arg == 2 || 4516 extra_arg == 3)) { 4517 pregpriv->rx_stbc = extra_arg; 4518 DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc); 4519 } else { 4520 DBG_88E("get rx_stbc =%d\n", pregpriv->rx_stbc); 4521 } 4522 } 4523 break; 4524 case 0x13: /* set ampdu_enable */ 4525 { 4526 struct registry_priv *pregpriv = &padapter->registrypriv; 4527 /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */ 4528 if (pregpriv && extra_arg >= 0 && extra_arg < 3) { 4529 pregpriv->ampdu_enable = extra_arg; 4530 DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable); 4531 } else { 4532 DBG_88E("get ampdu_enable =%d\n", pregpriv->ampdu_enable); 4533 } 4534 } 4535 break; 4536 case 0x14: /* get wifi_spec */ 4537 { 4538 struct registry_priv *pregpriv = &padapter->registrypriv; 4539 DBG_88E("get wifi_spec =%d\n", pregpriv->wifi_spec); 4540 } 4541 break; 4542 case 0x16: 4543 if (arg == 0xff) { 4544 pr_info("ODM_COMP_DIG\t\tBIT0\n"); 4545 pr_info("ODM_COMP_RA_MASK\t\tBIT1\n"); 4546 pr_info("ODM_COMP_DYNAMIC_TXPWR\tBIT2\n"); 4547 pr_info("ODM_COMP_FA_CNT\t\tBIT3\n"); 4548 pr_info("ODM_COMP_RSSI_MONITOR\tBIT4\n"); 4549 pr_info("ODM_COMP_CCK_PD\t\tBIT5\n"); 4550 pr_info("ODM_COMP_ANT_DIV\t\tBIT6\n"); 4551 pr_info("ODM_COMP_PWR_SAVE\t\tBIT7\n"); 4552 pr_info("ODM_COMP_PWR_TRAIN\tBIT8\n"); 4553 pr_info("ODM_COMP_RATE_ADAPTIVE\tBIT9\n"); 4554 pr_info("ODM_COMP_PATH_DIV\t\tBIT10\n"); 4555 pr_info("ODM_COMP_PSD \tBIT11\n"); 4556 pr_info("ODM_COMP_DYNAMIC_PRICCA\tBIT12\n"); 4557 pr_info("ODM_COMP_RXHP\t\tBIT13\n"); 4558 pr_info("ODM_COMP_EDCA_TURBO\tBIT16\n"); 4559 pr_info("ODM_COMP_EARLY_MODE\tBIT17\n"); 4560 pr_info("ODM_COMP_TX_PWR_TRACK\tBIT24\n"); 4561 pr_info("ODM_COMP_RX_GAIN_TRACK\tBIT25\n"); 4562 pr_info("ODM_COMP_CALIBRATION\tBIT26\n"); 4563 rtw_hal_get_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg); 4564 } else { 4565 rtw_hal_set_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg); 4566 } 4567 break; 4568 case 0x23: 4569 DBG_88E("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off"); 4570 padapter->bNotifyChannelChange = extra_arg; 4571 break; 4572 case 0x24: 4573#ifdef CONFIG_88EU_P2P 4574 DBG_88E("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off"); 4575 padapter->bShowGetP2PState = extra_arg; 4576#endif /* CONFIG_88EU_P2P */ 4577 break; 4578 case 0xaa: 4579 if (extra_arg > 0x13) 4580 extra_arg = 0xFF; 4581 DBG_88E("chang data rate to :0x%02x\n", extra_arg); 4582 padapter->fix_rate = extra_arg; 4583 break; 4584 case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */ 4585 if (extra_arg == 0) 4586 mac_reg_dump(padapter); 4587 else if (extra_arg == 1) 4588 bb_reg_dump(padapter); 4589 else if (extra_arg == 2) 4590 rf_reg_dump(padapter); 4591 break; 4592 case 0xee:/* turn on/off dynamic funcs */ 4593 { 4594 u32 odm_flag; 4595 4596 if (0xf == extra_arg) { 4597 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag); 4598 DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag); 4599 DBG_88E("extra_arg = 0 - disable all dynamic func\n"); 4600 DBG_88E("extra_arg = 1 - disable DIG- BIT(0)\n"); 4601 DBG_88E("extra_arg = 2 - disable High power - BIT(1)\n"); 4602 DBG_88E("extra_arg = 3 - disable tx power tracking - BIT(2)\n"); 4603 DBG_88E("extra_arg = 4 - disable BT coexistence - BIT(3)\n"); 4604 DBG_88E("extra_arg = 5 - disable antenna diversity - BIT(4)\n"); 4605 DBG_88E("extra_arg = 6 - enable all dynamic func\n"); 4606 } else { 4607 /* extra_arg = 0 - disable all dynamic func 4608 extra_arg = 1 - disable DIG 4609 extra_arg = 2 - disable tx power tracking 4610 extra_arg = 3 - turn on all dynamic func 4611 */ 4612 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg)); 4613 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag); 4614 DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag); 4615 } 4616 } 4617 break; 4618 4619 case 0xfd: 4620 rtw_write8(padapter, 0xc50, arg); 4621 DBG_88E("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50)); 4622 rtw_write8(padapter, 0xc58, arg); 4623 DBG_88E("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58)); 4624 break; 4625 case 0xfe: 4626 DBG_88E("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50)); 4627 DBG_88E("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58)); 4628 break; 4629 case 0xff: 4630 DBG_88E("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210)); 4631 DBG_88E("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608)); 4632 DBG_88E("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280)); 4633 DBG_88E("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284)); 4634 DBG_88E("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288)); 4635 4636 DBG_88E("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664)); 4637 4638 DBG_88E("\n"); 4639 4640 DBG_88E("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430)); 4641 DBG_88E("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438)); 4642 4643 DBG_88E("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440)); 4644 4645 DBG_88E("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458)); 4646 4647 DBG_88E("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484)); 4648 DBG_88E("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488)); 4649 4650 DBG_88E("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444)); 4651 DBG_88E("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448)); 4652 DBG_88E("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c)); 4653 DBG_88E("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450)); 4654 break; 4655 } 4656 break; 4657 default: 4658 DBG_88E("error dbg cmd!\n"); 4659 break; 4660 } 4661 return ret; 4662} 4663 4664static int wpa_set_param(struct net_device *dev, u8 name, u32 value) 4665{ 4666 uint ret = 0; 4667 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4668 4669 switch (name) { 4670 case IEEE_PARAM_WPA_ENABLED: 4671 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */ 4672 switch ((value)&0xff) { 4673 case 1: /* WPA */ 4674 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */ 4675 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; 4676 break; 4677 case 2: /* WPA2 */ 4678 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */ 4679 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; 4680 break; 4681 } 4682 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, 4683 ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype)); 4684 break; 4685 case IEEE_PARAM_TKIP_COUNTERMEASURES: 4686 break; 4687 case IEEE_PARAM_DROP_UNENCRYPTED: { 4688 /* HACK: 4689 * 4690 * wpa_supplicant calls set_wpa_enabled when the driver 4691 * is loaded and unloaded, regardless of if WPA is being 4692 * used. No other calls are made which can be used to 4693 * determine if encryption will be used or not prior to 4694 * association being expected. If encryption is not being 4695 * used, drop_unencrypted is set to false, else true -- we 4696 * can use this to determine if the CAP_PRIVACY_ON bit should 4697 * be set. 4698 */ 4699 4700 break; 4701 } 4702 case IEEE_PARAM_PRIVACY_INVOKED: 4703 break; 4704 4705 case IEEE_PARAM_AUTH_ALGS: 4706 ret = wpa_set_auth_algs(dev, value); 4707 break; 4708 case IEEE_PARAM_IEEE_802_1X: 4709 break; 4710 case IEEE_PARAM_WPAX_SELECT: 4711 break; 4712 default: 4713 ret = -EOPNOTSUPP; 4714 break; 4715 } 4716 return ret; 4717} 4718 4719static int wpa_mlme(struct net_device *dev, u32 command, u32 reason) 4720{ 4721 int ret = 0; 4722 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4723 4724 switch (command) { 4725 case IEEE_MLME_STA_DEAUTH: 4726 if (!rtw_set_802_11_disassociate(padapter)) 4727 ret = -1; 4728 break; 4729 case IEEE_MLME_STA_DISASSOC: 4730 if (!rtw_set_802_11_disassociate(padapter)) 4731 ret = -1; 4732 break; 4733 default: 4734 ret = -EOPNOTSUPP; 4735 break; 4736 } 4737 4738 return ret; 4739} 4740 4741static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) 4742{ 4743 struct ieee_param *param; 4744 uint ret = 0; 4745 4746 if (p->length < sizeof(struct ieee_param) || !p->pointer) { 4747 ret = -EINVAL; 4748 goto out; 4749 } 4750 4751 param = (struct ieee_param *)rtw_malloc(p->length); 4752 if (param == NULL) { 4753 ret = -ENOMEM; 4754 goto out; 4755 } 4756 4757 if (copy_from_user(param, p->pointer, p->length)) { 4758 kfree(param); 4759 ret = -EFAULT; 4760 goto out; 4761 } 4762 4763 switch (param->cmd) { 4764 case IEEE_CMD_SET_WPA_PARAM: 4765 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value); 4766 break; 4767 4768 case IEEE_CMD_SET_WPA_IE: 4769 ret = rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev), 4770 (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len); 4771 break; 4772 4773 case IEEE_CMD_SET_ENCRYPTION: 4774 ret = wpa_set_encryption(dev, param, p->length); 4775 break; 4776 4777 case IEEE_CMD_MLME: 4778 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code); 4779 break; 4780 4781 default: 4782 DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd); 4783 ret = -EOPNOTSUPP; 4784 break; 4785 } 4786 4787 if (ret == 0 && copy_to_user(p->pointer, param, p->length)) 4788 ret = -EFAULT; 4789 4790 kfree(param); 4791 4792out: 4793 4794 return ret; 4795} 4796 4797#ifdef CONFIG_88EU_AP_MODE 4798static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta) 4799{ 4800 struct cmd_obj *ph2c; 4801 struct set_stakey_parm *psetstakey_para; 4802 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4803 u8 res = _SUCCESS; 4804 4805 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 4806 if (ph2c == NULL) { 4807 res = _FAIL; 4808 goto exit; 4809 } 4810 4811 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); 4812 if (psetstakey_para == NULL) { 4813 kfree(ph2c); 4814 res = _FAIL; 4815 goto exit; 4816 } 4817 4818 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 4819 4820 psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy; 4821 4822 memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN); 4823 4824 memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16); 4825 4826 res = rtw_enqueue_cmd(pcmdpriv, ph2c); 4827 4828exit: 4829 4830 return res; 4831} 4832 4833static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid) 4834{ 4835 u8 keylen; 4836 struct cmd_obj *pcmd; 4837 struct setkey_parm *psetkeyparm; 4838 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 4839 int res = _SUCCESS; 4840 4841 DBG_88E("%s\n", __func__); 4842 4843 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); 4844 if (pcmd == NULL) { 4845 res = _FAIL; 4846 goto exit; 4847 } 4848 psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm)); 4849 if (psetkeyparm == NULL) { 4850 kfree(pcmd); 4851 res = _FAIL; 4852 goto exit; 4853 } 4854 4855 _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm)); 4856 4857 psetkeyparm->keyid = (u8)keyid; 4858 4859 psetkeyparm->algorithm = alg; 4860 4861 psetkeyparm->set_tx = 1; 4862 4863 switch (alg) { 4864 case _WEP40_: 4865 keylen = 5; 4866 break; 4867 case _WEP104_: 4868 keylen = 13; 4869 break; 4870 case _TKIP_: 4871 case _TKIP_WTMIC_: 4872 case _AES_: 4873 default: 4874 keylen = 16; 4875 } 4876 4877 memcpy(&(psetkeyparm->key[0]), key, keylen); 4878 4879 pcmd->cmdcode = _SetKey_CMD_; 4880 pcmd->parmbuf = (u8 *)psetkeyparm; 4881 pcmd->cmdsz = (sizeof(struct setkey_parm)); 4882 pcmd->rsp = NULL; 4883 pcmd->rspsz = 0; 4884 4885 _rtw_init_listhead(&pcmd->list); 4886 4887 res = rtw_enqueue_cmd(pcmdpriv, pcmd); 4888 4889exit: 4890 4891 return res; 4892} 4893 4894static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid) 4895{ 4896 u8 alg; 4897 4898 switch (keylen) { 4899 case 5: 4900 alg = _WEP40_; 4901 break; 4902 case 13: 4903 alg = _WEP104_; 4904 break; 4905 default: 4906 alg = _NO_PRIVACY_; 4907 } 4908 4909 return set_group_key(padapter, key, alg, keyid); 4910} 4911 4912static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) 4913{ 4914 int ret = 0; 4915 u32 wep_key_idx, wep_key_len, wep_total_len; 4916 struct ndis_802_11_wep *pwep = NULL; 4917 struct sta_info *psta = NULL, *pbcmc_sta = NULL; 4918 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 4919 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4920 struct security_priv *psecuritypriv = &(padapter->securitypriv); 4921 struct sta_priv *pstapriv = &padapter->stapriv; 4922 4923 DBG_88E("%s\n", __func__); 4924 param->u.crypt.err = 0; 4925 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; 4926 if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) { 4927 ret = -EINVAL; 4928 goto exit; 4929 } 4930 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 4931 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 4932 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { 4933 if (param->u.crypt.idx >= WEP_KEYS) { 4934 ret = -EINVAL; 4935 goto exit; 4936 } 4937 } else { 4938 psta = rtw_get_stainfo(pstapriv, param->sta_addr); 4939 if (!psta) { 4940 DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n"); 4941 goto exit; 4942 } 4943 } 4944 4945 if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) { 4946 /* todo:clear default encryption keys */ 4947 4948 DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx); 4949 goto exit; 4950 } 4951 if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) { 4952 DBG_88E("r871x_set_encryption, crypt.alg = WEP\n"); 4953 wep_key_idx = param->u.crypt.idx; 4954 wep_key_len = param->u.crypt.key_len; 4955 DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len); 4956 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) { 4957 ret = -EINVAL; 4958 goto exit; 4959 } 4960 4961 if (wep_key_len > 0) { 4962 wep_key_len = wep_key_len <= 5 ? 5 : 13; 4963 wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); 4964 pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); 4965 if (pwep == NULL) { 4966 DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n"); 4967 goto exit; 4968 } 4969 4970 _rtw_memset(pwep, 0, wep_total_len); 4971 4972 pwep->KeyLength = wep_key_len; 4973 pwep->Length = wep_total_len; 4974 } 4975 4976 pwep->KeyIndex = wep_key_idx; 4977 4978 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); 4979 4980 if (param->u.crypt.set_tx) { 4981 DBG_88E("wep, set_tx = 1\n"); 4982 4983 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; 4984 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; 4985 psecuritypriv->dot118021XGrpPrivacy = _WEP40_; 4986 4987 if (pwep->KeyLength == 13) { 4988 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_; 4989 psecuritypriv->dot118021XGrpPrivacy = _WEP104_; 4990 } 4991 4992 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx; 4993 4994 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength); 4995 4996 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength; 4997 4998 set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx); 4999 } else { 5000 DBG_88E("wep, set_tx = 0\n"); 5001 5002 /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */ 5003 /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */ 5004 5005 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength); 5006 5007 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength; 5008 5009 set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx); 5010 } 5011 5012 goto exit; 5013 } 5014 5015 if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */ 5016 if (param->u.crypt.set_tx == 1) { 5017 if (strcmp(param->u.crypt.alg, "WEP") == 0) { 5018 DBG_88E("%s, set group_key, WEP\n", __func__); 5019 5020 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, 5021 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5022 5023 psecuritypriv->dot118021XGrpPrivacy = _WEP40_; 5024 if (param->u.crypt.key_len == 13) 5025 psecuritypriv->dot118021XGrpPrivacy = _WEP104_; 5026 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { 5027 DBG_88E("%s, set group_key, TKIP\n", __func__); 5028 psecuritypriv->dot118021XGrpPrivacy = _TKIP_; 5029 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, 5030 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5031 /* set mic key */ 5032 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8); 5033 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8); 5034 5035 psecuritypriv->busetkipkey = true; 5036 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { 5037 DBG_88E("%s, set group_key, CCMP\n", __func__); 5038 psecuritypriv->dot118021XGrpPrivacy = _AES_; 5039 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, 5040 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5041 } else { 5042 DBG_88E("%s, set group_key, none\n", __func__); 5043 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; 5044 } 5045 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx; 5046 psecuritypriv->binstallGrpkey = true; 5047 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */ 5048 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx); 5049 pbcmc_sta = rtw_get_bcmc_stainfo(padapter); 5050 if (pbcmc_sta) { 5051 pbcmc_sta->ieee8021x_blocked = false; 5052 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */ 5053 } 5054 } 5055 goto exit; 5056 } 5057 5058 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */ 5059 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 5060 if (param->u.crypt.set_tx == 1) { 5061 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5062 5063 if (strcmp(param->u.crypt.alg, "WEP") == 0) { 5064 DBG_88E("%s, set pairwise key, WEP\n", __func__); 5065 5066 psta->dot118021XPrivacy = _WEP40_; 5067 if (param->u.crypt.key_len == 13) 5068 psta->dot118021XPrivacy = _WEP104_; 5069 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { 5070 DBG_88E("%s, set pairwise key, TKIP\n", __func__); 5071 5072 psta->dot118021XPrivacy = _TKIP_; 5073 5074 /* set mic key */ 5075 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8); 5076 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8); 5077 5078 psecuritypriv->busetkipkey = true; 5079 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { 5080 DBG_88E("%s, set pairwise key, CCMP\n", __func__); 5081 5082 psta->dot118021XPrivacy = _AES_; 5083 } else { 5084 DBG_88E("%s, set pairwise key, none\n", __func__); 5085 5086 psta->dot118021XPrivacy = _NO_PRIVACY_; 5087 } 5088 5089 set_pairwise_key(padapter, psta); 5090 5091 psta->ieee8021x_blocked = false; 5092 } else { /* group key??? */ 5093 if (strcmp(param->u.crypt.alg, "WEP") == 0) { 5094 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, 5095 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5096 psecuritypriv->dot118021XGrpPrivacy = _WEP40_; 5097 if (param->u.crypt.key_len == 13) 5098 psecuritypriv->dot118021XGrpPrivacy = _WEP104_; 5099 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { 5100 psecuritypriv->dot118021XGrpPrivacy = _TKIP_; 5101 5102 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, 5103 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5104 5105 /* set mic key */ 5106 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8); 5107 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8); 5108 5109 psecuritypriv->busetkipkey = true; 5110 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { 5111 psecuritypriv->dot118021XGrpPrivacy = _AES_; 5112 5113 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, 5114 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); 5115 } else { 5116 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; 5117 } 5118 5119 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx; 5120 5121 psecuritypriv->binstallGrpkey = true; 5122 5123 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */ 5124 5125 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx); 5126 5127 pbcmc_sta = rtw_get_bcmc_stainfo(padapter); 5128 if (pbcmc_sta) { 5129 pbcmc_sta->ieee8021x_blocked = false; 5130 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */ 5131 } 5132 } 5133 } 5134 } 5135 5136exit: 5137 5138 kfree(pwep); 5139 5140 return ret; 5141} 5142 5143static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len) 5144{ 5145 int ret = 0; 5146 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5147 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5148 struct sta_priv *pstapriv = &padapter->stapriv; 5149 unsigned char *pbuf = param->u.bcn_ie.buf; 5150 5151 DBG_88E("%s, len =%d\n", __func__, len); 5152 5153 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5154 return -EINVAL; 5155 5156 memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2); 5157 5158 if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0)) 5159 pstapriv->max_num_sta = NUM_STA; 5160 5161 if (rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)/* 12 = param header, 2:no packed */ 5162 ret = 0; 5163 else 5164 ret = -EINVAL; 5165 5166 return ret; 5167} 5168 5169static int rtw_hostapd_sta_flush(struct net_device *dev) 5170{ 5171 int ret = 0; 5172 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5173 5174 DBG_88E("%s\n", __func__); 5175 5176 flush_all_cam_entry(padapter); /* clear CAM */ 5177 5178 ret = rtw_sta_flush(padapter); 5179 5180 return ret; 5181} 5182 5183static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) 5184{ 5185 int ret = 0; 5186 struct sta_info *psta = NULL; 5187 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5188 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5189 struct sta_priv *pstapriv = &padapter->stapriv; 5190 5191 DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr)); 5192 5193 if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) 5194 return -EINVAL; 5195 5196 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 5197 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 5198 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 5199 return -EINVAL; 5200 5201 psta = rtw_get_stainfo(pstapriv, param->sta_addr); 5202 if (psta) { 5203 int flags = param->u.add_sta.flags; 5204 5205 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */ 5206 5207 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16); 5208 5209 /* check wmm cap. */ 5210 if (WLAN_STA_WME&flags) 5211 psta->qos_option = 1; 5212 else 5213 psta->qos_option = 0; 5214 5215 if (pmlmepriv->qospriv.qos_option == 0) 5216 psta->qos_option = 0; 5217 5218 /* chec 802.11n ht cap. */ 5219 if (WLAN_STA_HT&flags) { 5220 psta->htpriv.ht_option = true; 5221 psta->qos_option = 1; 5222 memcpy((void *)&psta->htpriv.ht_cap, (void *)¶m->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); 5223 } else { 5224 psta->htpriv.ht_option = false; 5225 } 5226 5227 if (pmlmepriv->htpriv.ht_option == false) 5228 psta->htpriv.ht_option = false; 5229 5230 update_sta_info_apmode(padapter, psta); 5231 } else { 5232 ret = -ENOMEM; 5233 } 5234 5235 return ret; 5236} 5237 5238static int rtw_del_sta(struct net_device *dev, struct ieee_param *param) 5239{ 5240 int ret = 0; 5241 struct sta_info *psta = NULL; 5242 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5243 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5244 struct sta_priv *pstapriv = &padapter->stapriv; 5245 int updated = 0; 5246 5247 DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr)); 5248 5249 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 5250 return -EINVAL; 5251 5252 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 5253 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 5254 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 5255 return -EINVAL; 5256 5257 psta = rtw_get_stainfo(pstapriv, param->sta_addr); 5258 if (psta) { 5259 spin_lock_bh(&pstapriv->asoc_list_lock); 5260 if (!rtw_is_list_empty(&psta->asoc_list)) { 5261 rtw_list_delete(&psta->asoc_list); 5262 pstapriv->asoc_list_cnt--; 5263 updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); 5264 } 5265 spin_unlock_bh(&pstapriv->asoc_list_lock); 5266 associated_clients_update(padapter, updated); 5267 psta = NULL; 5268 } else { 5269 DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n"); 5270 } 5271 5272 return ret; 5273} 5274 5275static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len) 5276{ 5277 int ret = 0; 5278 struct sta_info *psta = NULL; 5279 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5280 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5281 struct sta_priv *pstapriv = &padapter->stapriv; 5282 struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param; 5283 struct sta_data *psta_data = (struct sta_data *)param_ex->data; 5284 5285 DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr)); 5286 5287 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 5288 return -EINVAL; 5289 5290 if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff && 5291 param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff && 5292 param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) 5293 return -EINVAL; 5294 5295 psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr); 5296 if (psta) { 5297 psta_data->aid = (u16)psta->aid; 5298 psta_data->capability = psta->capability; 5299 psta_data->flags = psta->flags; 5300 5301/* 5302 nonerp_set : BIT(0) 5303 no_short_slot_time_set : BIT(1) 5304 no_short_preamble_set : BIT(2) 5305 no_ht_gf_set : BIT(3) 5306 no_ht_set : BIT(4) 5307 ht_20mhz_set : BIT(5) 5308*/ 5309 5310 psta_data->sta_set = ((psta->nonerp_set) | 5311 (psta->no_short_slot_time_set << 1) | 5312 (psta->no_short_preamble_set << 2) | 5313 (psta->no_ht_gf_set << 3) | 5314 (psta->no_ht_set << 4) | 5315 (psta->ht_20mhz_set << 5)); 5316 psta_data->tx_supp_rates_len = psta->bssratelen; 5317 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen); 5318 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); 5319 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts; 5320 psta_data->rx_bytes = psta->sta_stats.rx_bytes; 5321 psta_data->rx_drops = psta->sta_stats.rx_drops; 5322 psta_data->tx_pkts = psta->sta_stats.tx_pkts; 5323 psta_data->tx_bytes = psta->sta_stats.tx_bytes; 5324 psta_data->tx_drops = psta->sta_stats.tx_drops; 5325 } else { 5326 ret = -1; 5327 } 5328 5329 return ret; 5330} 5331 5332static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param) 5333{ 5334 int ret = 0; 5335 struct sta_info *psta = NULL; 5336 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5337 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5338 struct sta_priv *pstapriv = &padapter->stapriv; 5339 5340 DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr)); 5341 5342 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true) 5343 return -EINVAL; 5344 5345 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 5346 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 5347 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 5348 return -EINVAL; 5349 5350 psta = rtw_get_stainfo(pstapriv, param->sta_addr); 5351 if (psta) { 5352 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) { 5353 int wpa_ie_len; 5354 int copy_len; 5355 5356 wpa_ie_len = psta->wpa_ie[1]; 5357 copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2); 5358 param->u.wpa_ie.len = copy_len; 5359 memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len); 5360 } else { 5361 DBG_88E("sta's wpa_ie is NONE\n"); 5362 } 5363 } else { 5364 ret = -1; 5365 } 5366 5367 return ret; 5368} 5369 5370static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len) 5371{ 5372 int ret = 0; 5373 unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 5374 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5375 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5376 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 5377 int ie_len; 5378 5379 DBG_88E("%s, len =%d\n", __func__, len); 5380 5381 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5382 return -EINVAL; 5383 5384 ie_len = len-12-2;/* 12 = param header, 2:no packed */ 5385 5386 if (pmlmepriv->wps_beacon_ie) { 5387 kfree(pmlmepriv->wps_beacon_ie); 5388 pmlmepriv->wps_beacon_ie = NULL; 5389 } 5390 5391 if (ie_len > 0) { 5392 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len); 5393 pmlmepriv->wps_beacon_ie_len = ie_len; 5394 if (pmlmepriv->wps_beacon_ie == NULL) { 5395 DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 5396 return -EINVAL; 5397 } 5398 5399 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len); 5400 5401 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true); 5402 5403 pmlmeext->bstart_bss = true; 5404 } 5405 5406 return ret; 5407} 5408 5409static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len) 5410{ 5411 int ret = 0; 5412 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5413 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5414 int ie_len; 5415 5416 DBG_88E("%s, len =%d\n", __func__, len); 5417 5418 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5419 return -EINVAL; 5420 5421 ie_len = len-12-2;/* 12 = param header, 2:no packed */ 5422 5423 if (pmlmepriv->wps_probe_resp_ie) { 5424 kfree(pmlmepriv->wps_probe_resp_ie); 5425 pmlmepriv->wps_probe_resp_ie = NULL; 5426 } 5427 5428 if (ie_len > 0) { 5429 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len); 5430 pmlmepriv->wps_probe_resp_ie_len = ie_len; 5431 if (pmlmepriv->wps_probe_resp_ie == NULL) { 5432 DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 5433 return -EINVAL; 5434 } 5435 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len); 5436 } 5437 5438 return ret; 5439} 5440 5441static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len) 5442{ 5443 int ret = 0; 5444 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5445 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5446 int ie_len; 5447 5448 DBG_88E("%s, len =%d\n", __func__, len); 5449 5450 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5451 return -EINVAL; 5452 5453 ie_len = len-12-2;/* 12 = param header, 2:no packed */ 5454 5455 if (pmlmepriv->wps_assoc_resp_ie) { 5456 kfree(pmlmepriv->wps_assoc_resp_ie); 5457 pmlmepriv->wps_assoc_resp_ie = NULL; 5458 } 5459 5460 if (ie_len > 0) { 5461 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len); 5462 pmlmepriv->wps_assoc_resp_ie_len = ie_len; 5463 if (pmlmepriv->wps_assoc_resp_ie == NULL) { 5464 DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 5465 return -EINVAL; 5466 } 5467 5468 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len); 5469 } 5470 5471 return ret; 5472} 5473 5474static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len) 5475{ 5476 int ret = 0; 5477 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5478 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5479 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 5480 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5481 5482 u8 value; 5483 5484 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5485 return -EINVAL; 5486 5487 if (param->u.wpa_param.name != 0) /* dummy test... */ 5488 DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name); 5489 value = param->u.wpa_param.value; 5490 5491 /* use the same definition of hostapd's ignore_broadcast_ssid */ 5492 if (value != 1 && value != 2) 5493 value = 0; 5494 DBG_88E("%s value(%u)\n", __func__, value); 5495 pmlmeinfo->hidden_ssid_mode = value; 5496 return ret; 5497} 5498 5499static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len) 5500{ 5501 int ret = 0; 5502 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5503 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5504 5505 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5506 return -EINVAL; 5507 5508 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 5509 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 5510 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 5511 return -EINVAL; 5512 ret = rtw_acl_remove_sta(padapter, param->sta_addr); 5513 return ret; 5514} 5515 5516static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len) 5517{ 5518 int ret = 0; 5519 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5520 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5521 5522 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5523 return -EINVAL; 5524 5525 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 5526 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 5527 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 5528 return -EINVAL; 5529 ret = rtw_acl_add_sta(padapter, param->sta_addr); 5530 return ret; 5531} 5532 5533static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len) 5534{ 5535 int ret = 0; 5536 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5537 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5538 5539 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5540 return -EINVAL; 5541 5542 rtw_set_macaddr_acl(padapter, param->u.mlme.command); 5543 5544 return ret; 5545} 5546 5547static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) 5548{ 5549 struct ieee_param *param; 5550 int ret = 0; 5551 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5552 5553 /* 5554 * this function is expect to call in master mode, which allows no power saving 5555 * so, we just check hw_init_completed 5556 */ 5557 5558 if (!padapter->hw_init_completed) { 5559 ret = -EPERM; 5560 goto out; 5561 } 5562 5563 if (!p->pointer) { 5564 ret = -EINVAL; 5565 goto out; 5566 } 5567 5568 param = (struct ieee_param *)rtw_malloc(p->length); 5569 if (param == NULL) { 5570 ret = -ENOMEM; 5571 goto out; 5572 } 5573 5574 if (copy_from_user(param, p->pointer, p->length)) { 5575 kfree(param); 5576 ret = -EFAULT; 5577 goto out; 5578 } 5579 5580 switch (param->cmd) { 5581 case RTL871X_HOSTAPD_FLUSH: 5582 ret = rtw_hostapd_sta_flush(dev); 5583 break; 5584 case RTL871X_HOSTAPD_ADD_STA: 5585 ret = rtw_add_sta(dev, param); 5586 break; 5587 case RTL871X_HOSTAPD_REMOVE_STA: 5588 ret = rtw_del_sta(dev, param); 5589 break; 5590 case RTL871X_HOSTAPD_SET_BEACON: 5591 ret = rtw_set_beacon(dev, param, p->length); 5592 break; 5593 case RTL871X_SET_ENCRYPTION: 5594 ret = rtw_set_encryption(dev, param, p->length); 5595 break; 5596 case RTL871X_HOSTAPD_GET_WPAIE_STA: 5597 ret = rtw_get_sta_wpaie(dev, param); 5598 break; 5599 case RTL871X_HOSTAPD_SET_WPS_BEACON: 5600 ret = rtw_set_wps_beacon(dev, param, p->length); 5601 break; 5602 case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP: 5603 ret = rtw_set_wps_probe_resp(dev, param, p->length); 5604 break; 5605 case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP: 5606 ret = rtw_set_wps_assoc_resp(dev, param, p->length); 5607 break; 5608 case RTL871X_HOSTAPD_SET_HIDDEN_SSID: 5609 ret = rtw_set_hidden_ssid(dev, param, p->length); 5610 break; 5611 case RTL871X_HOSTAPD_GET_INFO_STA: 5612 ret = rtw_ioctl_get_sta_data(dev, param, p->length); 5613 break; 5614 case RTL871X_HOSTAPD_SET_MACADDR_ACL: 5615 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length); 5616 break; 5617 case RTL871X_HOSTAPD_ACL_ADD_STA: 5618 ret = rtw_ioctl_acl_add_sta(dev, param, p->length); 5619 break; 5620 case RTL871X_HOSTAPD_ACL_REMOVE_STA: 5621 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length); 5622 break; 5623 default: 5624 DBG_88E("Unknown hostapd request: %d\n", param->cmd); 5625 ret = -EOPNOTSUPP; 5626 break; 5627 } 5628 5629 if (ret == 0 && copy_to_user(p->pointer, param, p->length)) 5630 ret = -EFAULT; 5631 kfree(param); 5632out: 5633 return ret; 5634} 5635#endif 5636 5637#include <rtw_android.h> 5638static int rtw_wx_set_priv(struct net_device *dev, 5639 struct iw_request_info *info, 5640 union iwreq_data *awrq, 5641 char *extra) 5642{ 5643 int ret = 0; 5644 int len = 0; 5645 char *ext; 5646 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5647 struct iw_point *dwrq = (struct iw_point *)awrq; 5648 5649 if (dwrq->length == 0) 5650 return -EFAULT; 5651 5652 len = dwrq->length; 5653 ext = vmalloc(len); 5654 if (!ext) 5655 return -ENOMEM; 5656 5657 if (copy_from_user(ext, dwrq->pointer, len)) { 5658 rtw_vmfree(ext, len); 5659 return -EFAULT; 5660 } 5661 5662 /* added for wps2.0 @20110524 */ 5663 if (dwrq->flags == 0x8766 && len > 8) { 5664 u32 cp_sz; 5665 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5666 u8 *probereq_wpsie = ext; 5667 int probereq_wpsie_len = len; 5668 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 5669 5670 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) && 5671 (!memcmp(&probereq_wpsie[2], wps_oui, 4))) { 5672 cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len; 5673 5674 pmlmepriv->wps_probe_req_ie_len = 0; 5675 kfree(pmlmepriv->wps_probe_req_ie); 5676 pmlmepriv->wps_probe_req_ie = NULL; 5677 5678 pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz); 5679 if (pmlmepriv->wps_probe_req_ie == NULL) { 5680 pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); 5681 ret = -EINVAL; 5682 goto FREE_EXT; 5683 } 5684 memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz); 5685 pmlmepriv->wps_probe_req_ie_len = cp_sz; 5686 } 5687 goto FREE_EXT; 5688 } 5689 5690 if (len >= WEXT_CSCAN_HEADER_SIZE && 5691 !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) { 5692 ret = rtw_wx_set_scan(dev, info, awrq, ext); 5693 goto FREE_EXT; 5694 } 5695 5696FREE_EXT: 5697 5698 rtw_vmfree(ext, len); 5699 5700 return ret; 5701} 5702 5703static int rtw_pm_set(struct net_device *dev, 5704 struct iw_request_info *info, 5705 union iwreq_data *wrqu, char *extra) 5706{ 5707 int ret = 0; 5708 unsigned mode = 0; 5709 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 5710 5711 DBG_88E("[%s] extra = %s\n", __func__, extra); 5712 5713 if (!memcmp(extra, "lps =", 4)) { 5714 sscanf(extra+4, "%u", &mode); 5715 ret = rtw_pm_set_lps(padapter, mode); 5716 } else if (!memcmp(extra, "ips =", 4)) { 5717 sscanf(extra+4, "%u", &mode); 5718 ret = rtw_pm_set_ips(padapter, mode); 5719 } else { 5720 ret = -EINVAL; 5721 } 5722 5723 return ret; 5724} 5725 5726static int rtw_mp_efuse_get(struct net_device *dev, 5727 struct iw_request_info *info, 5728 union iwreq_data *wdata, char *extra) 5729{ 5730 struct adapter *padapter = rtw_netdev_priv(dev); 5731 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); 5732 struct hal_data_8188e *haldata = GET_HAL_DATA(padapter); 5733 struct efuse_hal *pEfuseHal; 5734 struct iw_point *wrqu; 5735 5736 u8 *PROMContent = pEEPROM->efuse_eeprom_data; 5737 u8 ips_mode = 0, lps_mode = 0; 5738 struct pwrctrl_priv *pwrctrlpriv; 5739 u8 *data = NULL; 5740 u8 *rawdata = NULL; 5741 char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL}; 5742 u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0; 5743 u16 max_available_size = 0, raw_cursize = 0, raw_maxsize = 0; 5744 int err; 5745 u8 org_fw_iol = padapter->registrypriv.fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */ 5746 5747 wrqu = (struct iw_point *)wdata; 5748 pwrctrlpriv = &padapter->pwrctrlpriv; 5749 pEfuseHal = &haldata->EfuseHal; 5750 5751 err = 0; 5752 data = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN); 5753 if (data == NULL) { 5754 err = -ENOMEM; 5755 goto exit; 5756 } 5757 rawdata = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN); 5758 if (rawdata == NULL) { 5759 err = -ENOMEM; 5760 goto exit; 5761 } 5762 5763 if (copy_from_user(extra, wrqu->pointer, wrqu->length)) { 5764 err = -EFAULT; 5765 goto exit; 5766 } 5767 lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */ 5768 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE); 5769 5770 ips_mode = pwrctrlpriv->ips_mode;/* keep org value */ 5771 rtw_pm_set_ips(padapter, IPS_NONE); 5772 5773 pch = extra; 5774 DBG_88E("%s: in =%s\n", __func__, extra); 5775 5776 i = 0; 5777 /* mac 16 "00e04c871200" rmap, 00, 2 */ 5778 while ((token = strsep(&pch, ",")) != NULL) { 5779 if (i > 2) 5780 break; 5781 tmp[i] = token; 5782 i++; 5783 } 5784 padapter->registrypriv.fw_iol = 0;/* 0:Disable, 1:enable, 2:by usb speed */ 5785 5786 if (strcmp(tmp[0], "status") == 0) { 5787 sprintf(extra, "Load File efuse =%s, Load File MAC =%s", (pEEPROM->bloadfile_fail_flag ? "FAIL" : "OK"), (pEEPROM->bloadmac_fail_flag ? "FAIL" : "OK")); 5788 5789 goto exit; 5790 } else if (strcmp(tmp[0], "filemap") == 0) { 5791 mapLen = EFUSE_MAP_SIZE; 5792 5793 sprintf(extra, "\n"); 5794 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) { 5795 sprintf(extra, "%s0x%02x\t", extra, i); 5796 for (j = 0; j < 8; j++) 5797 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]); 5798 sprintf(extra, "%s\t", extra); 5799 for (; j < 16; j++) 5800 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]); 5801 sprintf(extra, "%s\n", extra); 5802 } 5803 } else if (strcmp(tmp[0], "realmap") == 0) { 5804 mapLen = EFUSE_MAP_SIZE; 5805 if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) { 5806 DBG_88E("%s: read realmap Fail!!\n", __func__); 5807 err = -EFAULT; 5808 goto exit; 5809 } 5810 5811 sprintf(extra, "\n"); 5812 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) { 5813 sprintf(extra, "%s0x%02x\t", extra, i); 5814 for (j = 0; j < 8; j++) 5815 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]); 5816 sprintf(extra, "%s\t", extra); 5817 for (; j < 16; j++) 5818 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]); 5819 sprintf(extra, "%s\n", extra); 5820 } 5821 } else if (strcmp(tmp[0], "rmap") == 0) { 5822 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 5823 DBG_88E("%s: rmap Fail!! Parameters error!\n", __func__); 5824 err = -EINVAL; 5825 goto exit; 5826 } 5827 5828 /* rmap addr cnts */ 5829 addr = simple_strtoul(tmp[1], &ptmp, 16); 5830 DBG_88E("%s: addr =%x\n", __func__, addr); 5831 5832 cnts = simple_strtoul(tmp[2], &ptmp, 10); 5833 if (cnts == 0) { 5834 DBG_88E("%s: rmap Fail!! cnts error!\n", __func__); 5835 err = -EINVAL; 5836 goto exit; 5837 } 5838 DBG_88E("%s: cnts =%d\n", __func__, cnts); 5839 5840 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 5841 if ((addr + cnts) > max_available_size) { 5842 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts); 5843 err = -EINVAL; 5844 goto exit; 5845 } 5846 5847 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) { 5848 DBG_88E("%s: rtw_efuse_map_read error!\n", __func__); 5849 err = -EFAULT; 5850 goto exit; 5851 } 5852 5853 *extra = 0; 5854 for (i = 0; i < cnts; i++) 5855 sprintf(extra, "%s0x%02X ", extra, data[i]); 5856 } else if (strcmp(tmp[0], "realraw") == 0) { 5857 addr = 0; 5858 mapLen = EFUSE_MAX_SIZE; 5859 if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) { 5860 DBG_88E("%s: rtw_efuse_access Fail!!\n", __func__); 5861 err = -EFAULT; 5862 goto exit; 5863 } 5864 5865 sprintf(extra, "\n"); 5866 for (i = 0; i < mapLen; i++) { 5867 sprintf(extra, "%s%02X", extra, rawdata[i]); 5868 5869 if ((i & 0xF) == 0xF) 5870 sprintf(extra, "%s\n", extra); 5871 else if ((i & 0x7) == 0x7) 5872 sprintf(extra, "%s\t", extra); 5873 else 5874 sprintf(extra, "%s ", extra); 5875 } 5876 } else if (strcmp(tmp[0], "mac") == 0) { 5877 cnts = 6; 5878 5879 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 5880 if ((addr + cnts) > max_available_size) { 5881 DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts); 5882 err = -EFAULT; 5883 goto exit; 5884 } 5885 5886 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) { 5887 DBG_88E("%s: rtw_efuse_map_read error!\n", __func__); 5888 err = -EFAULT; 5889 goto exit; 5890 } 5891 5892 *extra = 0; 5893 for (i = 0; i < cnts; i++) { 5894 sprintf(extra, "%s%02X", extra, data[i]); 5895 if (i != (cnts-1)) 5896 sprintf(extra, "%s:", extra); 5897 } 5898 } else if (strcmp(tmp[0], "vidpid") == 0) { 5899 cnts = 4; 5900 5901 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 5902 if ((addr + cnts) > max_available_size) { 5903 DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts); 5904 err = -EFAULT; 5905 goto exit; 5906 } 5907 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) { 5908 DBG_88E("%s: rtw_efuse_access error!!\n", __func__); 5909 err = -EFAULT; 5910 goto exit; 5911 } 5912 5913 *extra = 0; 5914 for (i = 0; i < cnts; i++) { 5915 sprintf(extra, "%s0x%02X", extra, data[i]); 5916 if (i != (cnts-1)) 5917 sprintf(extra, "%s,", extra); 5918 } 5919 } else if (strcmp(tmp[0], "ableraw") == 0) { 5920 efuse_GetCurrentSize(padapter, &raw_cursize); 5921 raw_maxsize = efuse_GetMaxSize(padapter); 5922 sprintf(extra, "[available raw size] = %d bytes", raw_maxsize-raw_cursize); 5923 } else if (strcmp(tmp[0], "btfmap") == 0) { 5924 mapLen = EFUSE_BT_MAX_MAP_LEN; 5925 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) { 5926 DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__); 5927 err = -EFAULT; 5928 goto exit; 5929 } 5930 5931 sprintf(extra, "\n"); 5932 for (i = 0; i < 512; i += 16) { 5933 /* set 512 because the iwpriv's extra size have limit 0x7FF */ 5934 sprintf(extra, "%s0x%03x\t", extra, i); 5935 for (j = 0; j < 8; j++) 5936 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]); 5937 sprintf(extra, "%s\t", extra); 5938 for (; j < 16; j++) 5939 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]); 5940 sprintf(extra, "%s\n", extra); 5941 } 5942 } else if (strcmp(tmp[0], "btbmap") == 0) { 5943 mapLen = EFUSE_BT_MAX_MAP_LEN; 5944 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) { 5945 DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__); 5946 err = -EFAULT; 5947 goto exit; 5948 } 5949 5950 sprintf(extra, "\n"); 5951 for (i = 512; i < 1024; i += 16) { 5952 sprintf(extra, "%s0x%03x\t", extra, i); 5953 for (j = 0; j < 8; j++) 5954 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]); 5955 sprintf(extra, "%s\t", extra); 5956 for (; j < 16; j++) 5957 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]); 5958 sprintf(extra, "%s\n", extra); 5959 } 5960 } else if (strcmp(tmp[0], "btrmap") == 0) { 5961 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 5962 err = -EINVAL; 5963 goto exit; 5964 } 5965 5966 /* rmap addr cnts */ 5967 addr = simple_strtoul(tmp[1], &ptmp, 16); 5968 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 5969 5970 cnts = simple_strtoul(tmp[2], &ptmp, 10); 5971 if (cnts == 0) { 5972 DBG_88E("%s: btrmap Fail!! cnts error!\n", __func__); 5973 err = -EINVAL; 5974 goto exit; 5975 } 5976 DBG_88E("%s: cnts =%d\n", __func__, cnts); 5977 5978 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 5979 if ((addr + cnts) > max_available_size) { 5980 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts); 5981 err = -EFAULT; 5982 goto exit; 5983 } 5984 5985 if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) { 5986 DBG_88E("%s: rtw_BT_efuse_map_read error!!\n", __func__); 5987 err = -EFAULT; 5988 goto exit; 5989 } 5990 5991 *extra = 0; 5992 for (i = 0; i < cnts; i++) 5993 sprintf(extra, "%s 0x%02X ", extra, data[i]); 5994 } else if (strcmp(tmp[0], "btffake") == 0) { 5995 sprintf(extra, "\n"); 5996 for (i = 0; i < 512; i += 16) { 5997 sprintf(extra, "%s0x%03x\t", extra, i); 5998 for (j = 0; j < 8; j++) 5999 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]); 6000 sprintf(extra, "%s\t", extra); 6001 for (; j < 16; j++) 6002 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]); 6003 sprintf(extra, "%s\n", extra); 6004 } 6005 } else if (strcmp(tmp[0], "btbfake") == 0) { 6006 sprintf(extra, "\n"); 6007 for (i = 512; i < 1024; i += 16) { 6008 sprintf(extra, "%s0x%03x\t", extra, i); 6009 for (j = 0; j < 8; j++) 6010 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]); 6011 sprintf(extra, "%s\t", extra); 6012 for (; j < 16; j++) 6013 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]); 6014 sprintf(extra, "%s\n", extra); 6015 } 6016 } else if (strcmp(tmp[0], "wlrfkmap") == 0) { 6017 sprintf(extra, "\n"); 6018 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) { 6019 sprintf(extra, "%s0x%02x\t", extra, i); 6020 for (j = 0; j < 8; j++) 6021 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]); 6022 sprintf(extra, "%s\t", extra); 6023 for (; j < 16; j++) 6024 sprintf(extra, "%s %02X", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]); 6025 sprintf(extra, "%s\n", extra); 6026 } 6027 } else { 6028 sprintf(extra, "Command not found!"); 6029 } 6030 6031exit: 6032 kfree(data); 6033 kfree(rawdata); 6034 if (!err) 6035 wrqu->length = strlen(extra); 6036 6037 rtw_pm_set_ips(padapter, ips_mode); 6038 rtw_pm_set_lps(padapter, lps_mode); 6039 padapter->registrypriv.fw_iol = org_fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */ 6040 return err; 6041} 6042 6043static int rtw_mp_efuse_set(struct net_device *dev, 6044 struct iw_request_info *info, 6045 union iwreq_data *wdata, char *extra) 6046{ 6047 struct adapter *padapter; 6048 struct pwrctrl_priv *pwrctrlpriv; 6049 struct hal_data_8188e *haldata; 6050 struct efuse_hal *pEfuseHal; 6051 6052 u8 ips_mode = 0, lps_mode = 0; 6053 u32 i, jj, kk; 6054 u8 *setdata = NULL; 6055 u8 *ShadowMapBT = NULL; 6056 u8 *ShadowMapWiFi = NULL; 6057 u8 *setrawdata = NULL; 6058 char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL}; 6059 u16 addr = 0, cnts = 0, max_available_size = 0; 6060 int err; 6061 6062 padapter = rtw_netdev_priv(dev); 6063 pwrctrlpriv = &padapter->pwrctrlpriv; 6064 haldata = GET_HAL_DATA(padapter); 6065 pEfuseHal = &haldata->EfuseHal; 6066 err = 0; 6067 setdata = _rtw_zmalloc(1024); 6068 if (setdata == NULL) { 6069 err = -ENOMEM; 6070 goto exit; 6071 } 6072 ShadowMapBT = _rtw_malloc(EFUSE_BT_MAX_MAP_LEN); 6073 if (ShadowMapBT == NULL) { 6074 err = -ENOMEM; 6075 goto exit; 6076 } 6077 ShadowMapWiFi = _rtw_malloc(EFUSE_MAP_SIZE); 6078 if (ShadowMapWiFi == NULL) { 6079 err = -ENOMEM; 6080 goto exit; 6081 } 6082 setrawdata = _rtw_malloc(EFUSE_MAX_SIZE); 6083 if (setrawdata == NULL) { 6084 err = -ENOMEM; 6085 goto exit; 6086 } 6087 6088 lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */ 6089 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE); 6090 6091 ips_mode = pwrctrlpriv->ips_mode;/* keep org value */ 6092 rtw_pm_set_ips(padapter, IPS_NONE); 6093 6094 pch = extra; 6095 DBG_88E("%s: in =%s\n", __func__, extra); 6096 6097 i = 0; 6098 while ((token = strsep(&pch, ",")) != NULL) { 6099 if (i > 2) 6100 break; 6101 tmp[i] = token; 6102 i++; 6103 } 6104 6105 /* tmp[0],[1],[2] */ 6106 /* wmap, addr, 00e04c871200 */ 6107 if (strcmp(tmp[0], "wmap") == 0) { 6108 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 6109 err = -EINVAL; 6110 goto exit; 6111 } 6112 6113 addr = simple_strtoul(tmp[1], &ptmp, 16); 6114 addr &= 0xFFF; 6115 6116 cnts = strlen(tmp[2]); 6117 if (cnts%2) { 6118 err = -EINVAL; 6119 goto exit; 6120 } 6121 cnts /= 2; 6122 if (cnts == 0) { 6123 err = -EINVAL; 6124 goto exit; 6125 } 6126 6127 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6128 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6129 DBG_88E("%s: map data =%s\n", __func__, tmp[2]); 6130 6131 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6132 setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]); 6133 /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */ 6134 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false); 6135 if ((addr+cnts) > max_available_size) { 6136 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts); 6137 err = -EFAULT; 6138 goto exit; 6139 } 6140 6141 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) { 6142 DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__); 6143 err = -EFAULT; 6144 goto exit; 6145 } 6146 } else if (strcmp(tmp[0], "wraw") == 0) { 6147 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 6148 err = -EINVAL; 6149 goto exit; 6150 } 6151 6152 addr = simple_strtoul(tmp[1], &ptmp, 16); 6153 addr &= 0xFFF; 6154 6155 cnts = strlen(tmp[2]); 6156 if (cnts%2) { 6157 err = -EINVAL; 6158 goto exit; 6159 } 6160 cnts /= 2; 6161 if (cnts == 0) { 6162 err = -EINVAL; 6163 goto exit; 6164 } 6165 6166 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6167 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6168 DBG_88E("%s: raw data =%s\n", __func__, tmp[2]); 6169 6170 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6171 setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]); 6172 6173 if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) { 6174 DBG_88E("%s: rtw_efuse_access error!!\n", __func__); 6175 err = -EFAULT; 6176 goto exit; 6177 } 6178 } else if (strcmp(tmp[0], "mac") == 0) { 6179 if (tmp[1] == NULL) { 6180 err = -EINVAL; 6181 goto exit; 6182 } 6183 6184 /* mac, 00e04c871200 */ 6185 addr = EEPROM_MAC_ADDR_88EU; 6186 cnts = strlen(tmp[1]); 6187 if (cnts%2) { 6188 err = -EINVAL; 6189 goto exit; 6190 } 6191 cnts /= 2; 6192 if (cnts == 0) { 6193 err = -EINVAL; 6194 goto exit; 6195 } 6196 if (cnts > 6) { 6197 DBG_88E("%s: error data for mac addr =\"%s\"\n", __func__, tmp[1]); 6198 err = -EFAULT; 6199 goto exit; 6200 } 6201 6202 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6203 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6204 DBG_88E("%s: MAC address =%s\n", __func__, tmp[1]); 6205 6206 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6207 setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]); 6208 /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */ 6209 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false); 6210 if ((addr+cnts) > max_available_size) { 6211 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts); 6212 err = -EFAULT; 6213 goto exit; 6214 } 6215 6216 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) { 6217 DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__); 6218 err = -EFAULT; 6219 goto exit; 6220 } 6221 } else if (strcmp(tmp[0], "vidpid") == 0) { 6222 if (tmp[1] == NULL) { 6223 err = -EINVAL; 6224 goto exit; 6225 } 6226 6227 /* pidvid, da0b7881 */ 6228 addr = EEPROM_VID_88EE; 6229 cnts = strlen(tmp[1]); 6230 if (cnts%2) { 6231 err = -EINVAL; 6232 goto exit; 6233 } 6234 cnts /= 2; 6235 if (cnts == 0) { 6236 err = -EINVAL; 6237 goto exit; 6238 } 6239 6240 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6241 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6242 DBG_88E("%s: VID/PID =%s\n", __func__, tmp[1]); 6243 6244 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6245 setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]); 6246 6247 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 6248 if ((addr+cnts) > max_available_size) { 6249 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts); 6250 err = -EFAULT; 6251 goto exit; 6252 } 6253 6254 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) { 6255 DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__); 6256 err = -EFAULT; 6257 goto exit; 6258 } 6259 } else if (strcmp(tmp[0], "btwmap") == 0) { 6260 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 6261 err = -EINVAL; 6262 goto exit; 6263 } 6264 6265 addr = simple_strtoul(tmp[1], &ptmp, 16); 6266 addr &= 0xFFF; 6267 6268 cnts = strlen(tmp[2]); 6269 if (cnts%2) { 6270 err = -EINVAL; 6271 goto exit; 6272 } 6273 cnts /= 2; 6274 if (cnts == 0) { 6275 err = -EINVAL; 6276 goto exit; 6277 } 6278 6279 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6280 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6281 DBG_88E("%s: BT data =%s\n", __func__, tmp[2]); 6282 6283 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6284 setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]); 6285 6286 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 6287 if ((addr+cnts) > max_available_size) { 6288 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts); 6289 err = -EFAULT; 6290 goto exit; 6291 } 6292 6293 if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) { 6294 DBG_88E("%s: rtw_BT_efuse_map_write error!!\n", __func__); 6295 err = -EFAULT; 6296 goto exit; 6297 } 6298 } else if (strcmp(tmp[0], "btwfake") == 0) { 6299 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 6300 err = -EINVAL; 6301 goto exit; 6302 } 6303 6304 addr = simple_strtoul(tmp[1], &ptmp, 16); 6305 addr &= 0xFFF; 6306 6307 cnts = strlen(tmp[2]); 6308 if (cnts%2) { 6309 err = -EINVAL; 6310 goto exit; 6311 } 6312 cnts /= 2; 6313 if (cnts == 0) { 6314 err = -EINVAL; 6315 goto exit; 6316 } 6317 6318 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6319 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6320 DBG_88E("%s: BT tmp data =%s\n", __func__, tmp[2]); 6321 6322 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6323 pEfuseHal->fakeBTEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]); 6324 } else if (strcmp(tmp[0], "btdumpfake") == 0) { 6325 if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS) { 6326 DBG_88E("%s: BT read all map success\n", __func__); 6327 } else { 6328 DBG_88E("%s: BT read all map Fail!\n", __func__); 6329 err = -EFAULT; 6330 } 6331 } else if (strcmp(tmp[0], "wldumpfake") == 0) { 6332 if (rtw_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) { 6333 DBG_88E("%s: BT read all map success\n", __func__); 6334 } else { 6335 DBG_88E("%s: BT read all map Fail\n", __func__); 6336 err = -EFAULT; 6337 } 6338 } else if (strcmp(tmp[0], "btfk2map") == 0) { 6339 memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN); 6340 6341 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 6342 if (max_available_size < 1) { 6343 err = -EFAULT; 6344 goto exit; 6345 } 6346 6347 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) { 6348 DBG_88E("%s: rtw_BT_efuse_map_write error!\n", __func__); 6349 err = -EFAULT; 6350 goto exit; 6351 } 6352 } else if (strcmp(tmp[0], "wlfk2map") == 0) { 6353 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 6354 if (max_available_size < 1) { 6355 err = -EFAULT; 6356 goto exit; 6357 } 6358 6359 if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) { 6360 DBG_88E("%s: rtw_efuse_map_write error!\n", __func__); 6361 err = -EFAULT; 6362 goto exit; 6363 } 6364 } else if (strcmp(tmp[0], "wlwfake") == 0) { 6365 if ((tmp[1] == NULL) || (tmp[2] == NULL)) { 6366 err = -EINVAL; 6367 goto exit; 6368 } 6369 6370 addr = simple_strtoul(tmp[1], &ptmp, 16); 6371 addr &= 0xFFF; 6372 6373 cnts = strlen(tmp[2]); 6374 if (cnts%2) { 6375 err = -EINVAL; 6376 goto exit; 6377 } 6378 cnts /= 2; 6379 if (cnts == 0) { 6380 err = -EINVAL; 6381 goto exit; 6382 } 6383 6384 DBG_88E("%s: addr = 0x%X\n", __func__, addr); 6385 DBG_88E("%s: cnts =%d\n", __func__, cnts); 6386 DBG_88E("%s: map tmp data =%s\n", __func__, tmp[2]); 6387 6388 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2) 6389 pEfuseHal->fakeEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]); 6390 } 6391 6392exit: 6393 kfree(setdata); 6394 kfree(ShadowMapBT); 6395 kfree(ShadowMapWiFi); 6396 kfree(setrawdata); 6397 6398 rtw_pm_set_ips(padapter, ips_mode); 6399 rtw_pm_set_lps(padapter, lps_mode); 6400 6401 return err; 6402} 6403 6404/* 6405 * Input Format: %s,%d,%d 6406 * %s is width, could be 6407 * "b" for 1 byte 6408 * "w" for WORD (2 bytes) 6409 * "dw" for DWORD (4 bytes) 6410 * 1st %d is address(offset) 6411 * 2st %d is data to write 6412 */ 6413static int rtw_mp_write_reg(struct net_device *dev, 6414 struct iw_request_info *info, 6415 struct iw_point *wrqu, char *extra) 6416{ 6417 char *pch, *pnext, *ptmp; 6418 char *width_str; 6419 char width; 6420 u32 addr, data; 6421 int ret; 6422 struct adapter *padapter = rtw_netdev_priv(dev); 6423 6424 pch = extra; 6425 pnext = strpbrk(pch, ",.-"); 6426 if (pnext == NULL) 6427 return -EINVAL; 6428 *pnext = 0; 6429 width_str = pch; 6430 6431 pch = pnext + 1; 6432 pnext = strpbrk(pch, ",.-"); 6433 if (pnext == NULL) 6434 return -EINVAL; 6435 *pnext = 0; 6436 addr = simple_strtoul(pch, &ptmp, 16); 6437 if (addr > 0x3FFF) 6438 return -EINVAL; 6439 6440 pch = pnext + 1; 6441 if ((pch - extra) >= wrqu->length) 6442 return -EINVAL; 6443 data = simple_strtoul(pch, &ptmp, 16); 6444 6445 ret = 0; 6446 width = width_str[0]; 6447 switch (width) { 6448 case 'b': 6449 /* 1 byte */ 6450 if (data > 0xFF) { 6451 ret = -EINVAL; 6452 break; 6453 } 6454 rtw_write8(padapter, addr, data); 6455 break; 6456 case 'w': 6457 /* 2 bytes */ 6458 if (data > 0xFFFF) { 6459 ret = -EINVAL; 6460 break; 6461 } 6462 rtw_write16(padapter, addr, data); 6463 break; 6464 case 'd': 6465 /* 4 bytes */ 6466 rtw_write32(padapter, addr, data); 6467 break; 6468 default: 6469 ret = -EINVAL; 6470 break; 6471 } 6472 6473 return ret; 6474} 6475 6476/* 6477 * Input Format: %s,%d 6478 * %s is width, could be 6479 * "b" for 1 byte 6480 * "w" for WORD (2 bytes) 6481 * "dw" for DWORD (4 bytes) 6482 * %d is address(offset) 6483 * 6484 * Return: 6485 * %d for data readed 6486 */ 6487static int rtw_mp_read_reg(struct net_device *dev, 6488 struct iw_request_info *info, 6489 struct iw_point *wrqu, char *extra) 6490{ 6491 struct adapter *padapter = rtw_netdev_priv(dev); 6492 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6493 char *pch, *pnext, *ptmp; 6494 char *width_str; 6495 char width; 6496 char data[20], tmp[20]; 6497 u32 addr; 6498 u32 ret, i = 0, j = 0, strtout = 0; 6499 6500 if (!input) 6501 return -ENOMEM; 6502 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6503 kfree(input); 6504 return -EFAULT; 6505 } 6506 _rtw_memset(data, 0, 20); 6507 _rtw_memset(tmp, 0, 20); 6508 _rtw_memset(extra, 0, wrqu->length); 6509 6510 pch = input; 6511 pnext = strpbrk(pch, ",.-"); 6512 if (pnext == NULL) { 6513 kfree(input); 6514 return -EINVAL; 6515 } 6516 *pnext = 0; 6517 width_str = pch; 6518 6519 pch = pnext + 1; 6520 if ((pch - input) >= wrqu->length) { 6521 kfree(input); 6522 return -EINVAL; 6523 } 6524 kfree(input); 6525 addr = simple_strtoul(pch, &ptmp, 16); 6526 if (addr > 0x3FFF) 6527 return -EINVAL; 6528 6529 ret = 0; 6530 width = width_str[0]; 6531 switch (width) { 6532 case 'b': 6533 /* 1 byte */ 6534 sprintf(extra, "%d\n", rtw_read8(padapter, addr)); 6535 wrqu->length = strlen(extra); 6536 break; 6537 case 'w': 6538 /* 2 bytes */ 6539 sprintf(data, "%04x\n", rtw_read16(padapter, addr)); 6540 for (i = 0; i <= strlen(data); i++) { 6541 if (i%2 == 0) { 6542 tmp[j] = ' '; 6543 j++; 6544 } 6545 if (data[i] != '\0') 6546 tmp[j] = data[i]; 6547 j++; 6548 } 6549 pch = tmp; 6550 DBG_88E("pch =%s", pch); 6551 6552 while (*pch != '\0') { 6553 pnext = strpbrk(pch, " "); 6554 if (!pnext) 6555 break; 6556 6557 pnext++; 6558 if (*pnext != '\0') { 6559 strtout = simple_strtoul(pnext, &ptmp, 16); 6560 sprintf(extra, "%s %d", extra, strtout); 6561 } else { 6562 break; 6563 } 6564 pch = pnext; 6565 } 6566 wrqu->length = 6; 6567 break; 6568 case 'd': 6569 /* 4 bytes */ 6570 sprintf(data, "%08x", rtw_read32(padapter, addr)); 6571 /* add read data format blank */ 6572 for (i = 0; i <= strlen(data); i++) { 6573 if (i%2 == 0) { 6574 tmp[j] = ' '; 6575 j++; 6576 } 6577 if (data[i] != '\0') 6578 tmp[j] = data[i]; 6579 6580 j++; 6581 } 6582 pch = tmp; 6583 DBG_88E("pch =%s", pch); 6584 6585 while (*pch != '\0') { 6586 pnext = strpbrk(pch, " "); 6587 if (!pnext) 6588 break; 6589 pnext++; 6590 if (*pnext != '\0') { 6591 strtout = simple_strtoul(pnext, &ptmp, 16); 6592 sprintf(extra, "%s %d", extra, strtout); 6593 } else { 6594 break; 6595 } 6596 pch = pnext; 6597 } 6598 wrqu->length = strlen(extra); 6599 break; 6600 default: 6601 wrqu->length = 0; 6602 ret = -EINVAL; 6603 break; 6604 } 6605 6606 return ret; 6607} 6608 6609/* 6610 * Input Format: %d,%x,%x 6611 * %d is RF path, should be smaller than MAX_RF_PATH_NUMS 6612 * 1st %x is address(offset) 6613 * 2st %x is data to write 6614 */ 6615 static int rtw_mp_write_rf(struct net_device *dev, 6616 struct iw_request_info *info, 6617 struct iw_point *wrqu, char *extra) 6618{ 6619 u32 path, addr, data; 6620 int ret; 6621 struct adapter *padapter = rtw_netdev_priv(dev); 6622 6623 ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data); 6624 if (ret < 3) 6625 return -EINVAL; 6626 6627 if (path >= MAX_RF_PATH_NUMS) 6628 return -EINVAL; 6629 if (addr > 0xFF) 6630 return -EINVAL; 6631 if (data > 0xFFFFF) 6632 return -EINVAL; 6633 6634 _rtw_memset(extra, 0, wrqu->length); 6635 6636 write_rfreg(padapter, path, addr, data); 6637 6638 sprintf(extra, "write_rf completed\n"); 6639 wrqu->length = strlen(extra); 6640 6641 return 0; 6642} 6643 6644/* 6645 * Input Format: %d,%x 6646 * %d is RF path, should be smaller than MAX_RF_PATH_NUMS 6647 * %x is address(offset) 6648 * 6649 * Return: 6650 * %d for data readed 6651 */ 6652static int rtw_mp_read_rf(struct net_device *dev, 6653 struct iw_request_info *info, 6654 struct iw_point *wrqu, char *extra) 6655{ 6656 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6657 char *pch, *pnext, *ptmp; 6658 char data[20], tmp[20]; 6659 u32 path, addr; 6660 u32 ret, i = 0, j = 0, strtou = 0; 6661 struct adapter *padapter = rtw_netdev_priv(dev); 6662 6663 if (!input) 6664 return -ENOMEM; 6665 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6666 kfree(input); 6667 return -EFAULT; 6668 } 6669 ret = sscanf(input, "%d,%x", &path, &addr); 6670 kfree(input); 6671 if (ret < 2) 6672 return -EINVAL; 6673 6674 if (path >= MAX_RF_PATH_NUMS) 6675 return -EINVAL; 6676 if (addr > 0xFF) 6677 return -EINVAL; 6678 6679 _rtw_memset(extra, 0, wrqu->length); 6680 6681 sprintf(data, "%08x", read_rfreg(padapter, path, addr)); 6682 /* add read data format blank */ 6683 for (i = 0; i <= strlen(data); i++) { 6684 if (i%2 == 0) { 6685 tmp[j] = ' '; 6686 j++; 6687 } 6688 tmp[j] = data[i]; 6689 j++; 6690 } 6691 pch = tmp; 6692 DBG_88E("pch =%s", pch); 6693 6694 while (*pch != '\0') { 6695 pnext = strpbrk(pch, " "); 6696 pnext++; 6697 if (*pnext != '\0') { 6698 strtou = simple_strtoul(pnext, &ptmp, 16); 6699 sprintf(extra, "%s %d", extra, strtou); 6700 } else { 6701 break; 6702 } 6703 pch = pnext; 6704 } 6705 wrqu->length = strlen(extra); 6706 return 0; 6707} 6708 6709static int rtw_mp_start(struct net_device *dev, 6710 struct iw_request_info *info, 6711 struct iw_point *wrqu, char *extra) 6712{ 6713 struct adapter *padapter = rtw_netdev_priv(dev); 6714 6715 if (padapter->registrypriv.mp_mode == 0) { 6716 padapter->registrypriv.mp_mode = 1; 6717 6718 rtw_pm_set_ips(padapter, IPS_NONE); 6719 LeaveAllPowerSaveMode(padapter); 6720 6721 MPT_InitializeAdapter(padapter, 1); 6722 } 6723 if (padapter->registrypriv.mp_mode == 0) 6724 return -EPERM; 6725 if (padapter->mppriv.mode == MP_OFF) { 6726 if (mp_start_test(padapter) == _FAIL) 6727 return -EPERM; 6728 padapter->mppriv.mode = MP_ON; 6729 } 6730 return 0; 6731} 6732 6733static int rtw_mp_stop(struct net_device *dev, 6734 struct iw_request_info *info, 6735 struct iw_point *wrqu, char *extra) 6736{ 6737 struct adapter *padapter = rtw_netdev_priv(dev); 6738 6739 if (padapter->registrypriv.mp_mode == 1) { 6740 MPT_DeInitAdapter(padapter); 6741 padapter->registrypriv.mp_mode = 0; 6742 } 6743 6744 if (padapter->mppriv.mode != MP_OFF) { 6745 mp_stop_test(padapter); 6746 padapter->mppriv.mode = MP_OFF; 6747 } 6748 6749 return 0; 6750} 6751 6752extern int wifirate2_ratetbl_inx(unsigned char rate); 6753 6754static int rtw_mp_rate(struct net_device *dev, 6755 struct iw_request_info *info, 6756 struct iw_point *wrqu, char *extra) 6757{ 6758 u32 rate = MPT_RATE_1M; 6759 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6760 struct adapter *padapter = rtw_netdev_priv(dev); 6761 6762 if (!input) 6763 return -ENOMEM; 6764 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6765 kfree(input); 6766 return -EFAULT; 6767 } 6768 rate = rtw_atoi(input); 6769 sprintf(extra, "Set data rate to %d", rate); 6770 kfree(input); 6771 if (rate <= 0x7f) 6772 rate = wifirate2_ratetbl_inx((u8)rate); 6773 else 6774 rate = (rate-0x80+MPT_RATE_MCS0); 6775 6776 if (rate >= MPT_RATE_LAST) 6777 return -EINVAL; 6778 6779 padapter->mppriv.rateidx = rate; 6780 Hal_SetDataRate(padapter); 6781 6782 wrqu->length = strlen(extra) + 1; 6783 return 0; 6784} 6785 6786static int rtw_mp_channel(struct net_device *dev, 6787 struct iw_request_info *info, 6788 struct iw_point *wrqu, char *extra) 6789{ 6790 struct adapter *padapter = rtw_netdev_priv(dev); 6791 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6792 u32 channel = 1; 6793 6794 if (!input) 6795 return -ENOMEM; 6796 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6797 kfree(input); 6798 return -EFAULT; 6799 } 6800 channel = rtw_atoi(input); 6801 sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel, channel); 6802 6803 padapter->mppriv.channel = channel; 6804 Hal_SetChannel(padapter); 6805 6806 wrqu->length = strlen(extra) + 1; 6807 kfree(input); 6808 return 0; 6809} 6810 6811static int rtw_mp_bandwidth(struct net_device *dev, 6812 struct iw_request_info *info, 6813 struct iw_point *wrqu, char *extra) 6814{ 6815 u32 bandwidth = 0, sg = 0; 6816 struct adapter *padapter = rtw_netdev_priv(dev); 6817 6818 sscanf(extra, "40M =%d, shortGI =%d", &bandwidth, &sg); 6819 6820 if (bandwidth != HT_CHANNEL_WIDTH_40) 6821 bandwidth = HT_CHANNEL_WIDTH_20; 6822 6823 padapter->mppriv.bandwidth = (u8)bandwidth; 6824 padapter->mppriv.preamble = sg; 6825 6826 SetBandwidth(padapter); 6827 6828 return 0; 6829} 6830 6831static int rtw_mp_txpower(struct net_device *dev, 6832 struct iw_request_info *info, 6833 struct iw_point *wrqu, char *extra) 6834{ 6835 u32 idx_a = 0, idx_b = 0; 6836 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6837 struct adapter *padapter = rtw_netdev_priv(dev); 6838 6839 if (!input) 6840 return -ENOMEM; 6841 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6842 kfree(input); 6843 return -EFAULT; 6844 } 6845 sscanf(input, "patha =%d, pathb =%d", &idx_a, &idx_b); 6846 6847 sprintf(extra, "Set power level path_A:%d path_B:%d", idx_a, idx_b); 6848 padapter->mppriv.txpoweridx = (u8)idx_a; 6849 padapter->mppriv.txpoweridx_b = (u8)idx_b; 6850 padapter->mppriv.bSetTxPower = 1; 6851 Hal_SetAntennaPathPower(padapter); 6852 6853 wrqu->length = strlen(extra) + 1; 6854 kfree(input); 6855 return 0; 6856} 6857 6858static int rtw_mp_ant_tx(struct net_device *dev, 6859 struct iw_request_info *info, 6860 struct iw_point *wrqu, char *extra) 6861{ 6862 u8 i; 6863 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6864 u16 antenna = 0; 6865 struct adapter *padapter = rtw_netdev_priv(dev); 6866 6867 if (!input) 6868 return -ENOMEM; 6869 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6870 kfree(input); 6871 return -EFAULT; 6872 } 6873 6874 sprintf(extra, "switch Tx antenna to %s", input); 6875 6876 for (i = 0; i < strlen(input); i++) { 6877 switch (input[i]) { 6878 case 'a': 6879 antenna |= ANTENNA_A; 6880 break; 6881 case 'b': 6882 antenna |= ANTENNA_B; 6883 break; 6884 } 6885 } 6886 padapter->mppriv.antenna_tx = antenna; 6887 6888 Hal_SetAntenna(padapter); 6889 6890 wrqu->length = strlen(extra) + 1; 6891 kfree(input); 6892 return 0; 6893} 6894 6895static int rtw_mp_ant_rx(struct net_device *dev, 6896 struct iw_request_info *info, 6897 struct iw_point *wrqu, char *extra) 6898{ 6899 u8 i; 6900 u16 antenna = 0; 6901 char *input = kmalloc(wrqu->length, GFP_KERNEL); 6902 struct adapter *padapter = rtw_netdev_priv(dev); 6903 6904 if (!input) 6905 return -ENOMEM; 6906 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 6907 kfree(input); 6908 return -EFAULT; 6909 } 6910 _rtw_memset(extra, 0, wrqu->length); 6911 6912 sprintf(extra, "switch Rx antenna to %s", input); 6913 6914 for (i = 0; i < strlen(input); i++) { 6915 switch (input[i]) { 6916 case 'a': 6917 antenna |= ANTENNA_A; 6918 break; 6919 case 'b': 6920 antenna |= ANTENNA_B; 6921 break; 6922 } 6923 } 6924 6925 padapter->mppriv.antenna_rx = antenna; 6926 Hal_SetAntenna(padapter); 6927 wrqu->length = strlen(extra); 6928 kfree(input); 6929 return 0; 6930} 6931 6932static int rtw_mp_ctx(struct net_device *dev, 6933 struct iw_request_info *info, 6934 struct iw_point *wrqu, char *extra) 6935{ 6936 u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1; 6937 u32 bStartTest = 1; 6938 u32 count = 0; 6939 struct mp_priv *pmp_priv; 6940 struct pkt_attrib *pattrib; 6941 6942 struct adapter *padapter = rtw_netdev_priv(dev); 6943 6944 pmp_priv = &padapter->mppriv; 6945 6946 if (copy_from_user(extra, wrqu->pointer, wrqu->length)) 6947 return -EFAULT; 6948 6949 DBG_88E("%s: in =%s\n", __func__, extra); 6950 6951 countPkTx = strncmp(extra, "count =", 5); /* strncmp true is 0 */ 6952 cotuTx = strncmp(extra, "background", 20); 6953 CarrSprTx = strncmp(extra, "background, cs", 20); 6954 scTx = strncmp(extra, "background, sc", 20); 6955 sgleTx = strncmp(extra, "background, stone", 20); 6956 pkTx = strncmp(extra, "background, pkt", 20); 6957 stop = strncmp(extra, "stop", 4); 6958 sscanf(extra, "count =%d, pkt", &count); 6959 6960 _rtw_memset(extra, '\0', sizeof(*extra)); 6961 6962 if (stop == 0) { 6963 bStartTest = 0; /* To set Stop */ 6964 pmp_priv->tx.stop = 1; 6965 sprintf(extra, "Stop continuous Tx"); 6966 } else { 6967 bStartTest = 1; 6968 if (pmp_priv->mode != MP_ON) { 6969 if (pmp_priv->tx.stop != 1) { 6970 DBG_88E("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode); 6971 return -EFAULT; 6972 } 6973 } 6974 } 6975 6976 if (pkTx == 0 || countPkTx == 0) 6977 pmp_priv->mode = MP_PACKET_TX; 6978 if (sgleTx == 0) 6979 pmp_priv->mode = MP_SINGLE_TONE_TX; 6980 if (cotuTx == 0) 6981 pmp_priv->mode = MP_CONTINUOUS_TX; 6982 if (CarrSprTx == 0) 6983 pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX; 6984 if (scTx == 0) 6985 pmp_priv->mode = MP_SINGLE_CARRIER_TX; 6986 6987 switch (pmp_priv->mode) { 6988 case MP_PACKET_TX: 6989 if (bStartTest == 0) { 6990 pmp_priv->tx.stop = 1; 6991 pmp_priv->mode = MP_ON; 6992 sprintf(extra, "Stop continuous Tx"); 6993 } else if (pmp_priv->tx.stop == 1) { 6994 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500 count =%u,\n", count); 6995 pmp_priv->tx.stop = 0; 6996 pmp_priv->tx.count = count; 6997 pmp_priv->tx.payload = 2; 6998 pattrib = &pmp_priv->tx.attrib; 6999 pattrib->pktlen = 1500; 7000 _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN); 7001 SetPacketTx(padapter); 7002 } else { 7003 return -EFAULT; 7004 } 7005 wrqu->length = strlen(extra); 7006 return 0; 7007 case MP_SINGLE_TONE_TX: 7008 if (bStartTest != 0) 7009 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes."); 7010 Hal_SetSingleToneTx(padapter, (u8)bStartTest); 7011 break; 7012 case MP_CONTINUOUS_TX: 7013 if (bStartTest != 0) 7014 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes."); 7015 Hal_SetContinuousTx(padapter, (u8)bStartTest); 7016 break; 7017 case MP_CARRIER_SUPPRISSION_TX: 7018 if (bStartTest != 0) { 7019 if (pmp_priv->rateidx <= MPT_RATE_11M) { 7020 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes."); 7021 Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest); 7022 } else { 7023 sprintf(extra, "Specify carrier suppression but not CCK rate"); 7024 } 7025 } 7026 break; 7027 case MP_SINGLE_CARRIER_TX: 7028 if (bStartTest != 0) 7029 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes."); 7030 Hal_SetSingleCarrierTx(padapter, (u8)bStartTest); 7031 break; 7032 default: 7033 sprintf(extra, "Error! Continuous-Tx is not on-going."); 7034 return -EFAULT; 7035 } 7036 7037 if (bStartTest == 1 && pmp_priv->mode != MP_ON) { 7038 struct mp_priv *pmp_priv = &padapter->mppriv; 7039 if (pmp_priv->tx.stop == 0) { 7040 pmp_priv->tx.stop = 1; 7041 msleep(5); 7042 } 7043 pmp_priv->tx.stop = 0; 7044 pmp_priv->tx.count = 1; 7045 SetPacketTx(padapter); 7046 } else { 7047 pmp_priv->mode = MP_ON; 7048 } 7049 7050 wrqu->length = strlen(extra); 7051 return 0; 7052} 7053 7054static int rtw_mp_arx(struct net_device *dev, 7055 struct iw_request_info *info, 7056 struct iw_point *wrqu, char *extra) 7057{ 7058 u8 bStartRx = 0, bStopRx = 0, bQueryPhy; 7059 u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0; 7060 char *input = kmalloc(wrqu->length, GFP_KERNEL); 7061 struct adapter *padapter = rtw_netdev_priv(dev); 7062 7063 if (!input) 7064 return -ENOMEM; 7065 7066 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 7067 kfree(input); 7068 return -EFAULT; 7069 } 7070 DBG_88E("%s: %s\n", __func__, input); 7071 7072 bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */ 7073 bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0 */ 7074 bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */ 7075 7076 if (bStartRx) { 7077 sprintf(extra, "start"); 7078 SetPacketRx(padapter, bStartRx); 7079 } else if (bStopRx) { 7080 SetPacketRx(padapter, 0); 7081 sprintf(extra, "Received packet OK:%d CRC error:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount); 7082 } else if (bQueryPhy) { 7083 /* 7084 OFDM FA 7085 RegCF0[15:0] 7086 RegCF2[31:16] 7087 RegDA0[31:16] 7088 RegDA4[15:0] 7089 RegDA4[31:16] 7090 RegDA8[15:0] 7091 CCK FA 7092 (RegA5B<<8) | RegA5C 7093 */ 7094 cckok = read_bbreg(padapter, 0xf88, 0xffffffff); 7095 cckcrc = read_bbreg(padapter, 0xf84, 0xffffffff); 7096 ofdmok = read_bbreg(padapter, 0xf94, 0x0000FFFF); 7097 ofdmcrc = read_bbreg(padapter, 0xf94, 0xFFFF0000); 7098 htok = read_bbreg(padapter, 0xf90, 0x0000FFFF); 7099 htcrc = read_bbreg(padapter, 0xf90, 0xFFFF0000); 7100 7101 OFDM_FA = read_bbreg(padapter, 0xcf0, 0x0000FFFF); 7102 OFDM_FA = read_bbreg(padapter, 0xcf2, 0xFFFF0000); 7103 OFDM_FA = read_bbreg(padapter, 0xda0, 0xFFFF0000); 7104 OFDM_FA = read_bbreg(padapter, 0xda4, 0x0000FFFF); 7105 OFDM_FA = read_bbreg(padapter, 0xda4, 0xFFFF0000); 7106 OFDM_FA = read_bbreg(padapter, 0xda8, 0x0000FFFF); 7107 CCK_FA = (rtw_read8(padapter, 0xa5b)<<8) | (rtw_read8(padapter, 0xa5c)); 7108 7109 sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", cckok+ofdmok+htok, cckcrc+ofdmcrc+htcrc, OFDM_FA+CCK_FA); 7110 } 7111 wrqu->length = strlen(extra) + 1; 7112 kfree(input); 7113 return 0; 7114} 7115 7116static int rtw_mp_trx_query(struct net_device *dev, 7117 struct iw_request_info *info, 7118 struct iw_point *wrqu, char *extra) 7119{ 7120 u32 txok, txfail, rxok, rxfail; 7121 struct adapter *padapter = rtw_netdev_priv(dev); 7122 7123 txok = padapter->mppriv.tx.sended; 7124 txfail = 0; 7125 rxok = padapter->mppriv.rx_pktcount; 7126 rxfail = padapter->mppriv.rx_crcerrpktcount; 7127 7128 _rtw_memset(extra, '\0', 128); 7129 7130 sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail, rxok, rxfail); 7131 7132 wrqu->length = strlen(extra)+1; 7133 7134 return 0; 7135} 7136 7137static int rtw_mp_pwrtrk(struct net_device *dev, 7138 struct iw_request_info *info, 7139 struct iw_point *wrqu, char *extra) 7140{ 7141 u8 enable; 7142 u32 thermal; 7143 s32 ret; 7144 struct adapter *padapter = rtw_netdev_priv(dev); 7145 char *input = kmalloc(wrqu->length, GFP_KERNEL); 7146 7147 if (!input) 7148 return -ENOMEM; 7149 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 7150 kfree(input); 7151 return -EFAULT; 7152 } 7153 _rtw_memset(extra, 0, wrqu->length); 7154 7155 enable = 1; 7156 if (wrqu->length > 1) {/* not empty string */ 7157 if (strncmp(input, "stop", 4) == 0) { 7158 enable = 0; 7159 sprintf(extra, "mp tx power tracking stop"); 7160 } else if (sscanf(input, "ther =%d", &thermal)) { 7161 ret = Hal_SetThermalMeter(padapter, (u8)thermal); 7162 if (ret == _FAIL) 7163 return -EPERM; 7164 sprintf(extra, "mp tx power tracking start, target value =%d ok ", thermal); 7165 } else { 7166 kfree(input); 7167 return -EINVAL; 7168 } 7169 } 7170 7171 kfree(input); 7172 ret = Hal_SetPowerTracking(padapter, enable); 7173 if (ret == _FAIL) 7174 return -EPERM; 7175 7176 wrqu->length = strlen(extra); 7177 return 0; 7178} 7179 7180static int rtw_mp_psd(struct net_device *dev, 7181 struct iw_request_info *info, 7182 struct iw_point *wrqu, char *extra) 7183{ 7184 struct adapter *padapter = rtw_netdev_priv(dev); 7185 char *input = kmalloc(wrqu->length, GFP_KERNEL); 7186 7187 if (!input) 7188 return -ENOMEM; 7189 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 7190 kfree(input); 7191 return -EFAULT; 7192 } 7193 7194 strcpy(extra, input); 7195 7196 wrqu->length = mp_query_psd(padapter, extra); 7197 kfree(input); 7198 return 0; 7199} 7200 7201static int rtw_mp_thermal(struct net_device *dev, 7202 struct iw_request_info *info, 7203 struct iw_point *wrqu, char *extra) 7204{ 7205 u8 val; 7206 u16 bwrite = 1; 7207 u16 addr = EEPROM_THERMAL_METER_88E; 7208 7209 u16 cnt = 1; 7210 u16 max_available_size = 0; 7211 struct adapter *padapter = rtw_netdev_priv(dev); 7212 7213 if (copy_from_user(extra, wrqu->pointer, wrqu->length)) 7214 return -EFAULT; 7215 7216 bwrite = strncmp(extra, "write", 6); /* strncmp true is 0 */ 7217 7218 Hal_GetThermalMeter(padapter, &val); 7219 7220 if (bwrite == 0) { 7221 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); 7222 if (2 > max_available_size) { 7223 DBG_88E("no available efuse!\n"); 7224 return -EFAULT; 7225 } 7226 if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) { 7227 DBG_88E("rtw_efuse_map_write error\n"); 7228 return -EFAULT; 7229 } else { 7230 sprintf(extra, " efuse write ok :%d", val); 7231 } 7232 } else { 7233 sprintf(extra, "%d", val); 7234 } 7235 wrqu->length = strlen(extra); 7236 7237 return 0; 7238} 7239 7240static int rtw_mp_reset_stats(struct net_device *dev, 7241 struct iw_request_info *info, 7242 struct iw_point *wrqu, char *extra) 7243{ 7244 struct mp_priv *pmp_priv; 7245 struct adapter *padapter = rtw_netdev_priv(dev); 7246 7247 pmp_priv = &padapter->mppriv; 7248 7249 pmp_priv->tx.sended = 0; 7250 pmp_priv->tx_pktcount = 0; 7251 pmp_priv->rx_pktcount = 0; 7252 pmp_priv->rx_crcerrpktcount = 0; 7253 7254 /* reset phy counter */ 7255 write_bbreg(padapter, 0xf14, BIT16, 0x1); 7256 msleep(10); 7257 write_bbreg(padapter, 0xf14, BIT16, 0x0); 7258 7259 return 0; 7260} 7261 7262static int rtw_mp_dump(struct net_device *dev, 7263 struct iw_request_info *info, 7264 struct iw_point *wrqu, char *extra) 7265{ 7266 u32 value; 7267 u8 rf_type, path_nums = 0; 7268 u32 i, j = 1, path; 7269 struct adapter *padapter = rtw_netdev_priv(dev); 7270 7271 if (strncmp(extra, "all", 4) == 0) { 7272 DBG_88E("\n ======= MAC REG =======\n"); 7273 for (i = 0x0; i < 0x300; i += 4) { 7274 if (j%4 == 1) 7275 DBG_88E("0x%02x", i); 7276 DBG_88E(" 0x%08x ", rtw_read32(padapter, i)); 7277 if ((j++)%4 == 0) 7278 DBG_88E("\n"); 7279 } 7280 for (i = 0x400; i < 0x1000; i += 4) { 7281 if (j%4 == 1) 7282 DBG_88E("0x%02x", i); 7283 DBG_88E(" 0x%08x ", rtw_read32(padapter, i)); 7284 if ((j++)%4 == 0) 7285 DBG_88E("\n"); 7286 } 7287 7288 j = 1; 7289 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); 7290 7291 DBG_88E("\n ======= RF REG =======\n"); 7292 if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) 7293 path_nums = 1; 7294 else 7295 path_nums = 2; 7296 7297 for (path = 0; path < path_nums; path++) { 7298 for (i = 0; i < 0x34; i++) { 7299 value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); 7300 if (j%4 == 1) 7301 DBG_88E("0x%02x ", i); 7302 DBG_88E(" 0x%08x ", value); 7303 if ((j++)%4 == 0) 7304 DBG_88E("\n"); 7305 } 7306 } 7307 } 7308 return 0; 7309} 7310 7311static int rtw_mp_phypara(struct net_device *dev, 7312 struct iw_request_info *info, 7313 struct iw_point *wrqu, char *extra) 7314{ 7315 char *input = kmalloc(wrqu->length, GFP_KERNEL); 7316 u32 valxcap; 7317 7318 if (!input) 7319 return -ENOMEM; 7320 if (copy_from_user(input, wrqu->pointer, wrqu->length)) { 7321 kfree(input); 7322 return -EFAULT; 7323 } 7324 7325 DBG_88E("%s:iwpriv in =%s\n", __func__, input); 7326 7327 sscanf(input, "xcap =%d", &valxcap); 7328 7329 kfree(input); 7330 return 0; 7331} 7332 7333static int rtw_mp_SetRFPath(struct net_device *dev, 7334 struct iw_request_info *info, 7335 union iwreq_data *wrqu, char *extra) 7336{ 7337 struct adapter *padapter = rtw_netdev_priv(dev); 7338 char *input = kmalloc(wrqu->data.length, GFP_KERNEL); 7339 u8 bMain = 1, bTurnoff = 1; 7340 7341 if (!input) 7342 return -ENOMEM; 7343 if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) 7344 return -EFAULT; 7345 DBG_88E("%s:iwpriv in =%s\n", __func__, input); 7346 7347 bMain = strncmp(input, "1", 2); /* strncmp true is 0 */ 7348 bTurnoff = strncmp(input, "0", 3); /* strncmp true is 0 */ 7349 7350 if (bMain == 0) { 7351 MP_PHY_SetRFPathSwitch(padapter, true); 7352 DBG_88E("%s:PHY_SetRFPathSwitch = true\n", __func__); 7353 } else if (bTurnoff == 0) { 7354 MP_PHY_SetRFPathSwitch(padapter, false); 7355 DBG_88E("%s:PHY_SetRFPathSwitch = false\n", __func__); 7356 } 7357 kfree(input); 7358 return 0; 7359} 7360 7361static int rtw_mp_QueryDrv(struct net_device *dev, 7362 struct iw_request_info *info, 7363 union iwreq_data *wrqu, char *extra) 7364{ 7365 struct adapter *padapter = rtw_netdev_priv(dev); 7366 char *input = kmalloc(wrqu->data.length, GFP_KERNEL); 7367 u8 qAutoLoad = 1; 7368 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); 7369 7370 if (!input) 7371 return -ENOMEM; 7372 7373 if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) 7374 return -EFAULT; 7375 DBG_88E("%s:iwpriv in =%s\n", __func__, input); 7376 7377 qAutoLoad = strncmp(input, "autoload", 8); /* strncmp true is 0 */ 7378 7379 if (qAutoLoad == 0) { 7380 DBG_88E("%s:qAutoLoad\n", __func__); 7381 7382 if (pEEPROM->bautoload_fail_flag) 7383 sprintf(extra, "fail"); 7384 else 7385 sprintf(extra, "ok"); 7386 } 7387 wrqu->data.length = strlen(extra) + 1; 7388 kfree(input); 7389 return 0; 7390} 7391 7392static int rtw_mp_set(struct net_device *dev, 7393 struct iw_request_info *info, 7394 union iwreq_data *wdata, char *extra) 7395{ 7396 struct iw_point *wrqu = (struct iw_point *)wdata; 7397 u32 subcmd = wrqu->flags; 7398 struct adapter *padapter = rtw_netdev_priv(dev); 7399 7400 if (padapter == NULL) 7401 return -ENETDOWN; 7402 7403 if (extra == NULL) { 7404 wrqu->length = 0; 7405 return -EIO; 7406 } 7407 7408 switch (subcmd) { 7409 case MP_START: 7410 DBG_88E("set case mp_start\n"); 7411 rtw_mp_start(dev, info, wrqu, extra); 7412 break; 7413 case MP_STOP: 7414 DBG_88E("set case mp_stop\n"); 7415 rtw_mp_stop(dev, info, wrqu, extra); 7416 break; 7417 case MP_BANDWIDTH: 7418 DBG_88E("set case mp_bandwidth\n"); 7419 rtw_mp_bandwidth(dev, info, wrqu, extra); 7420 break; 7421 case MP_RESET_STATS: 7422 DBG_88E("set case MP_RESET_STATS\n"); 7423 rtw_mp_reset_stats(dev, info, wrqu, extra); 7424 break; 7425 case MP_SetRFPathSwh: 7426 DBG_88E("set MP_SetRFPathSwitch\n"); 7427 rtw_mp_SetRFPath(dev, info, wdata, extra); 7428 break; 7429 case CTA_TEST: 7430 DBG_88E("set CTA_TEST\n"); 7431 rtw_cta_test_start(dev, info, wdata, extra); 7432 break; 7433 } 7434 7435 return 0; 7436} 7437 7438static int rtw_mp_get(struct net_device *dev, 7439 struct iw_request_info *info, 7440 union iwreq_data *wdata, char *extra) 7441{ 7442 struct iw_point *wrqu = (struct iw_point *)wdata; 7443 u32 subcmd = wrqu->flags; 7444 struct adapter *padapter = rtw_netdev_priv(dev); 7445 7446 if (padapter == NULL) 7447 return -ENETDOWN; 7448 if (extra == NULL) { 7449 wrqu->length = 0; 7450 return -EIO; 7451 } 7452 7453 switch (subcmd) { 7454 case WRITE_REG: 7455 rtw_mp_write_reg(dev, info, wrqu, extra); 7456 break; 7457 case WRITE_RF: 7458 rtw_mp_write_rf(dev, info, wrqu, extra); 7459 break; 7460 case MP_PHYPARA: 7461 DBG_88E("mp_get MP_PHYPARA\n"); 7462 rtw_mp_phypara(dev, info, wrqu, extra); 7463 break; 7464 case MP_CHANNEL: 7465 DBG_88E("set case mp_channel\n"); 7466 rtw_mp_channel(dev, info, wrqu, extra); 7467 break; 7468 case READ_REG: 7469 DBG_88E("mp_get READ_REG\n"); 7470 rtw_mp_read_reg(dev, info, wrqu, extra); 7471 break; 7472 case READ_RF: 7473 DBG_88E("mp_get READ_RF\n"); 7474 rtw_mp_read_rf(dev, info, wrqu, extra); 7475 break; 7476 case MP_RATE: 7477 DBG_88E("set case mp_rate\n"); 7478 rtw_mp_rate(dev, info, wrqu, extra); 7479 break; 7480 case MP_TXPOWER: 7481 DBG_88E("set case MP_TXPOWER\n"); 7482 rtw_mp_txpower(dev, info, wrqu, extra); 7483 break; 7484 case MP_ANT_TX: 7485 DBG_88E("set case MP_ANT_TX\n"); 7486 rtw_mp_ant_tx(dev, info, wrqu, extra); 7487 break; 7488 case MP_ANT_RX: 7489 DBG_88E("set case MP_ANT_RX\n"); 7490 rtw_mp_ant_rx(dev, info, wrqu, extra); 7491 break; 7492 case MP_QUERY: 7493 rtw_mp_trx_query(dev, info, wrqu, extra); 7494 break; 7495 case MP_CTX: 7496 DBG_88E("set case MP_CTX\n"); 7497 rtw_mp_ctx(dev, info, wrqu, extra); 7498 break; 7499 case MP_ARX: 7500 DBG_88E("set case MP_ARX\n"); 7501 rtw_mp_arx(dev, info, wrqu, extra); 7502 break; 7503 case EFUSE_GET: 7504 DBG_88E("efuse get EFUSE_GET\n"); 7505 rtw_mp_efuse_get(dev, info, wdata, extra); 7506 break; 7507 case MP_DUMP: 7508 DBG_88E("set case MP_DUMP\n"); 7509 rtw_mp_dump(dev, info, wrqu, extra); 7510 break; 7511 case MP_PSD: 7512 DBG_88E("set case MP_PSD\n"); 7513 rtw_mp_psd(dev, info, wrqu, extra); 7514 break; 7515 case MP_THER: 7516 DBG_88E("set case MP_THER\n"); 7517 rtw_mp_thermal(dev, info, wrqu, extra); 7518 break; 7519 case MP_QueryDrvStats: 7520 DBG_88E("mp_get MP_QueryDrvStats\n"); 7521 rtw_mp_QueryDrv (dev, info, wdata, extra); 7522 break; 7523 case MP_PWRTRK: 7524 DBG_88E("set case MP_PWRTRK\n"); 7525 rtw_mp_pwrtrk(dev, info, wrqu, extra); 7526 break; 7527 case EFUSE_SET: 7528 DBG_88E("set case efuse set\n"); 7529 rtw_mp_efuse_set(dev, info, wdata, extra); 7530 break; 7531 } 7532 7533 msleep(10); /* delay 5ms for sending pkt before exit adb shell operation */ 7534 return 0; 7535} 7536 7537static int rtw_tdls(struct net_device *dev, 7538 struct iw_request_info *info, 7539 union iwreq_data *wrqu, char *extra) 7540{ 7541 return 0; 7542} 7543 7544static int rtw_tdls_get(struct net_device *dev, 7545 struct iw_request_info *info, 7546 union iwreq_data *wrqu, char *extra) 7547{ 7548 return 0; 7549} 7550 7551static int rtw_test( 7552 struct net_device *dev, 7553 struct iw_request_info *info, 7554 union iwreq_data *wrqu, char *extra) 7555{ 7556 u32 len; 7557 u8 *pbuf, *pch; 7558 char *ptmp; 7559 u8 *delim = ","; 7560 7561 DBG_88E("+%s\n", __func__); 7562 len = wrqu->data.length; 7563 7564 pbuf = (u8 *)rtw_zmalloc(len); 7565 if (pbuf == NULL) { 7566 DBG_88E("%s: no memory!\n", __func__); 7567 return -ENOMEM; 7568 } 7569 7570 if (copy_from_user(pbuf, wrqu->data.pointer, len)) { 7571 kfree(pbuf); 7572 DBG_88E("%s: copy from user fail!\n", __func__); 7573 return -EFAULT; 7574 } 7575 DBG_88E("%s: string =\"%s\"\n", __func__, pbuf); 7576 7577 ptmp = (char *)pbuf; 7578 pch = strsep(&ptmp, delim); 7579 if ((pch == NULL) || (strlen(pch) == 0)) { 7580 kfree(pbuf); 7581 DBG_88E("%s: parameter error(level 1)!\n", __func__); 7582 return -EFAULT; 7583 } 7584 kfree(pbuf); 7585 return 0; 7586} 7587 7588static iw_handler rtw_handlers[] = { 7589 NULL, /* SIOCSIWCOMMIT */ 7590 rtw_wx_get_name, /* SIOCGIWNAME */ 7591 dummy, /* SIOCSIWNWID */ 7592 dummy, /* SIOCGIWNWID */ 7593 rtw_wx_set_freq, /* SIOCSIWFREQ */ 7594 rtw_wx_get_freq, /* SIOCGIWFREQ */ 7595 rtw_wx_set_mode, /* SIOCSIWMODE */ 7596 rtw_wx_get_mode, /* SIOCGIWMODE */ 7597 dummy, /* SIOCSIWSENS */ 7598 rtw_wx_get_sens, /* SIOCGIWSENS */ 7599 NULL, /* SIOCSIWRANGE */ 7600 rtw_wx_get_range, /* SIOCGIWRANGE */ 7601 rtw_wx_set_priv, /* SIOCSIWPRIV */ 7602 NULL, /* SIOCGIWPRIV */ 7603 NULL, /* SIOCSIWSTATS */ 7604 NULL, /* SIOCGIWSTATS */ 7605 dummy, /* SIOCSIWSPY */ 7606 dummy, /* SIOCGIWSPY */ 7607 NULL, /* SIOCGIWTHRSPY */ 7608 NULL, /* SIOCWIWTHRSPY */ 7609 rtw_wx_set_wap, /* SIOCSIWAP */ 7610 rtw_wx_get_wap, /* SIOCGIWAP */ 7611 rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */ 7612 dummy, /* SIOCGIWAPLIST -- depricated */ 7613 rtw_wx_set_scan, /* SIOCSIWSCAN */ 7614 rtw_wx_get_scan, /* SIOCGIWSCAN */ 7615 rtw_wx_set_essid, /* SIOCSIWESSID */ 7616 rtw_wx_get_essid, /* SIOCGIWESSID */ 7617 dummy, /* SIOCSIWNICKN */ 7618 rtw_wx_get_nick, /* SIOCGIWNICKN */ 7619 NULL, /* -- hole -- */ 7620 NULL, /* -- hole -- */ 7621 rtw_wx_set_rate, /* SIOCSIWRATE */ 7622 rtw_wx_get_rate, /* SIOCGIWRATE */ 7623 rtw_wx_set_rts, /* SIOCSIWRTS */ 7624 rtw_wx_get_rts, /* SIOCGIWRTS */ 7625 rtw_wx_set_frag, /* SIOCSIWFRAG */ 7626 rtw_wx_get_frag, /* SIOCGIWFRAG */ 7627 dummy, /* SIOCSIWTXPOW */ 7628 dummy, /* SIOCGIWTXPOW */ 7629 dummy, /* SIOCSIWRETRY */ 7630 rtw_wx_get_retry, /* SIOCGIWRETRY */ 7631 rtw_wx_set_enc, /* SIOCSIWENCODE */ 7632 rtw_wx_get_enc, /* SIOCGIWENCODE */ 7633 dummy, /* SIOCSIWPOWER */ 7634 rtw_wx_get_power, /* SIOCGIWPOWER */ 7635 NULL, /*---hole---*/ 7636 NULL, /*---hole---*/ 7637 rtw_wx_set_gen_ie, /* SIOCSIWGENIE */ 7638 NULL, /* SIOCGWGENIE */ 7639 rtw_wx_set_auth, /* SIOCSIWAUTH */ 7640 NULL, /* SIOCGIWAUTH */ 7641 rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 7642 NULL, /* SIOCGIWENCODEEXT */ 7643 rtw_wx_set_pmkid, /* SIOCSIWPMKSA */ 7644 NULL, /*---hole---*/ 7645}; 7646 7647static const struct iw_priv_args rtw_private_args[] = { 7648 { 7649 SIOCIWFIRSTPRIV + 0x0, 7650 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write" 7651 }, 7652 { 7653 SIOCIWFIRSTPRIV + 0x1, 7654 IW_PRIV_TYPE_CHAR | 0x7FF, 7655 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read" 7656 }, 7657 { 7658 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext" 7659 }, 7660 { 7661 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl" 7662 }, 7663 { 7664 SIOCIWFIRSTPRIV + 0x4, 7665 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" 7666 }, 7667 { 7668 SIOCIWFIRSTPRIV + 0x5, 7669 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid" 7670 }, 7671 { 7672 SIOCIWFIRSTPRIV + 0x6, 7673 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start" 7674 }, 7675 { 7676 SIOCIWFIRSTPRIV + 0x7, 7677 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity" 7678 }, 7679 { 7680 SIOCIWFIRSTPRIV + 0x8, 7681 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie" 7682 }, 7683 { 7684 SIOCIWFIRSTPRIV + 0x9, 7685 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie" 7686 }, 7687 7688 { 7689 SIOCIWFIRSTPRIV + 0xA, 7690 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan" 7691 }, 7692 7693 { 7694 SIOCIWFIRSTPRIV + 0xB, 7695 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg" 7696 }, 7697 { 7698 SIOCIWFIRSTPRIV + 0xC, 7699 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw" 7700 }, 7701 { 7702 SIOCIWFIRSTPRIV + 0xD, 7703 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr" 7704 }, 7705 { 7706 SIOCIWFIRSTPRIV + 0x10, 7707 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set" 7708 }, 7709 { 7710 SIOCIWFIRSTPRIV + 0x11, 7711 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get" 7712 }, 7713 { 7714 SIOCIWFIRSTPRIV + 0x12, 7715 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2" 7716 }, 7717 {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0, "NULL"}, 7718 { 7719 SIOCIWFIRSTPRIV + 0x14, 7720 IW_PRIV_TYPE_CHAR | 64, 0, "tdls" 7721 }, 7722 { 7723 SIOCIWFIRSTPRIV + 0x15, 7724 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "tdls_get" 7725 }, 7726 { 7727 SIOCIWFIRSTPRIV + 0x16, 7728 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set" 7729 }, 7730 7731 {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"}, 7732 7733 {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"}, 7734 {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"}, 7735 {SIOCIWFIRSTPRIV + 0x1D, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test" 7736 }, 7737 7738 {SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0, ""}, /* set */ 7739 {SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, ""},/* get */ 7740/* --- sub-ioctls definitions --- */ 7741 7742 {MP_START, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start"}, /* set */ 7743 {MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara"},/* get */ 7744 {MP_STOP, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop"}, /* set */ 7745 {MP_CHANNEL, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel"},/* get */ 7746 {MP_BANDWIDTH, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, /* set */ 7747 {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},/* get */ 7748 {MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"}, 7749 {MP_QUERY, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_query"}, /* get */ 7750 {READ_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg"}, 7751 {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"}, 7752 {READ_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf"}, 7753 {MP_PSD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"}, 7754 {MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump"}, 7755 {MP_TXPOWER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"}, 7756 {MP_ANT_TX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"}, 7757 {MP_ANT_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"}, 7758 {WRITE_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg"}, 7759 {WRITE_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf"}, 7760 {MP_CTX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"}, 7761 {MP_ARX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"}, 7762 {MP_THER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"}, 7763 {EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set"}, 7764 {EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"}, 7765 {MP_PWRTRK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"}, 7766 {MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery"}, 7767 {MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, /* mp_ioctl */ 7768 {MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath"}, 7769 {CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"}, 7770}; 7771 7772static iw_handler rtw_private_handler[] = { 7773rtw_wx_write32, /* 0x00 */ 7774rtw_wx_read32, /* 0x01 */ 7775rtw_drvext_hdl, /* 0x02 */ 7776rtw_mp_ioctl_hdl, /* 0x03 */ 7777 7778/* for MM DTV platform */ 7779 rtw_get_ap_info, /* 0x04 */ 7780 7781 rtw_set_pid, /* 0x05 */ 7782 rtw_wps_start, /* 0x06 */ 7783 7784 rtw_wx_get_sensitivity, /* 0x07 */ 7785 rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */ 7786 rtw_wx_set_mtk_wps_ie, /* 0x09 */ 7787 7788/* Set Channel depend on the country code */ 7789 rtw_wx_set_channel_plan, /* 0x0A */ 7790 7791 rtw_dbg_port, /* 0x0B */ 7792 rtw_wx_write_rf, /* 0x0C */ 7793 rtw_wx_read_rf, /* 0x0D */ 7794 7795 rtw_mp_set, /* 0x0E */ 7796 rtw_mp_get, /* 0x0F */ 7797 rtw_p2p_set, /* 0x10 */ 7798 rtw_p2p_get, /* 0x11 */ 7799 rtw_p2p_get2, /* 0x12 */ 7800 7801 NULL, /* 0x13 */ 7802 rtw_tdls, /* 0x14 */ 7803 rtw_tdls_get, /* 0x15 */ 7804 7805 rtw_pm_set, /* 0x16 */ 7806 rtw_wx_priv_null, /* 0x17 */ 7807 rtw_rereg_nd_name, /* 0x18 */ 7808 rtw_wx_priv_null, /* 0x19 */ 7809 7810 rtw_mp_efuse_set, /* 0x1A */ 7811 rtw_mp_efuse_get, /* 0x1B */ 7812 NULL, /* 0x1C is reserved for hostapd */ 7813 rtw_test, /* 0x1D */ 7814}; 7815 7816static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev) 7817{ 7818 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); 7819 struct iw_statistics *piwstats = &padapter->iwstats; 7820 int tmp_level = 0; 7821 int tmp_qual = 0; 7822 int tmp_noise = 0; 7823 7824 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { 7825 piwstats->qual.qual = 0; 7826 piwstats->qual.level = 0; 7827 piwstats->qual.noise = 0; 7828 } else { 7829 tmp_level = padapter->recvpriv.signal_strength; 7830 tmp_qual = padapter->recvpriv.signal_qual; 7831 tmp_noise = padapter->recvpriv.noise; 7832 7833 piwstats->qual.level = tmp_level; 7834 piwstats->qual.qual = tmp_qual; 7835 piwstats->qual.noise = tmp_noise; 7836 } 7837 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */ 7838 return &padapter->iwstats; 7839} 7840 7841struct iw_handler_def rtw_handlers_def = { 7842 .standard = rtw_handlers, 7843 .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler), 7844 .private = rtw_private_handler, 7845 .private_args = (struct iw_priv_args *)rtw_private_args, 7846 .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler), 7847 .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args), 7848 .get_wireless_stats = rtw_get_wireless_stats, 7849}; 7850 7851/* copy from net/wireless/wext.c start */ 7852/* ---------------------------------------------------------------- */ 7853/* 7854 * Calculate size of private arguments 7855 */ 7856static const char iw_priv_type_size[] = { 7857 0, /* IW_PRIV_TYPE_NONE */ 7858 1, /* IW_PRIV_TYPE_BYTE */ 7859 1, /* IW_PRIV_TYPE_CHAR */ 7860 0, /* Not defined */ 7861 sizeof(__u32), /* IW_PRIV_TYPE_INT */ 7862 sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ 7863 sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 7864 0, /* Not defined */ 7865}; 7866 7867static int get_priv_size(__u16 args) 7868{ 7869 int num = args & IW_PRIV_SIZE_MASK; 7870 int type = (args & IW_PRIV_TYPE_MASK) >> 12; 7871 7872 return num * iw_priv_type_size[type]; 7873} 7874/* copy from net/wireless/wext.c end */ 7875 7876static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data) 7877{ 7878 int err = 0; 7879 u8 *input = NULL; 7880 u32 input_len = 0; 7881 const char delim[] = " "; 7882 u8 *output = NULL; 7883 u32 output_len = 0; 7884 u32 count = 0; 7885 u8 *buffer = NULL; 7886 u32 buffer_len = 0; 7887 char *ptr = NULL; 7888 u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */ 7889 u32 cmdlen; 7890 s32 len; 7891 u8 *extra = NULL; 7892 u32 extra_size = 0; 7893 7894 s32 k; 7895 const iw_handler *priv; /* Private ioctl */ 7896 const struct iw_priv_args *priv_args; /* Private ioctl description */ 7897 u32 num_priv_args; /* Number of descriptions */ 7898 iw_handler handler; 7899 int temp; 7900 int subcmd = 0; /* sub-ioctl index */ 7901 int offset = 0; /* Space for sub-ioctl index */ 7902 7903 union iwreq_data wdata; 7904 7905 memcpy(&wdata, wrq_data, sizeof(wdata)); 7906 7907 input_len = wdata.data.length; 7908 input = rtw_zmalloc(input_len); 7909 if (NULL == input) 7910 return -ENOMEM; 7911 if (copy_from_user(input, wdata.data.pointer, input_len)) { 7912 err = -EFAULT; 7913 goto exit; 7914 } 7915 ptr = input; 7916 len = input_len; 7917 7918 sscanf(ptr, "%16s", cmdname); 7919 cmdlen = strlen(cmdname); 7920 DBG_88E("%s: cmd =%s\n", __func__, cmdname); 7921 7922 /* skip command string */ 7923 if (cmdlen > 0) 7924 cmdlen += 1; /* skip one space */ 7925 ptr += cmdlen; 7926 len -= cmdlen; 7927 DBG_88E("%s: parameters =%s\n", __func__, ptr); 7928 7929 priv = rtw_private_handler; 7930 priv_args = rtw_private_args; 7931 num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args); 7932 7933 if (num_priv_args == 0) { 7934 err = -EOPNOTSUPP; 7935 goto exit; 7936 } 7937 7938 /* Search the correct ioctl */ 7939 k = -1; 7940 while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname)); 7941 7942 /* If not found... */ 7943 if (k == num_priv_args) { 7944 err = -EOPNOTSUPP; 7945 goto exit; 7946 } 7947 7948 /* Watch out for sub-ioctls ! */ 7949 if (priv_args[k].cmd < SIOCDEVPRIVATE) { 7950 int j = -1; 7951 7952 /* Find the matching *real* ioctl */ 7953 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') || 7954 (priv_args[j].set_args != priv_args[k].set_args) || 7955 (priv_args[j].get_args != priv_args[k].get_args))); 7956 7957 /* If not found... */ 7958 if (j == num_priv_args) { 7959 err = -EINVAL; 7960 goto exit; 7961 } 7962 7963 /* Save sub-ioctl number */ 7964 subcmd = priv_args[k].cmd; 7965 /* Reserve one int (simplify alignment issues) */ 7966 offset = sizeof(__u32); 7967 /* Use real ioctl definition from now on */ 7968 k = j; 7969 } 7970 7971 buffer = rtw_zmalloc(4096); 7972 if (NULL == buffer) { 7973 err = -ENOMEM; 7974 goto exit; 7975 } 7976 7977 /* If we have to set some data */ 7978 if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) && 7979 (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) { 7980 u8 *str; 7981 7982 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) { 7983 case IW_PRIV_TYPE_BYTE: 7984 /* Fetch args */ 7985 count = 0; 7986 do { 7987 str = strsep(&ptr, delim); 7988 if (NULL == str) 7989 break; 7990 sscanf(str, "%i", &temp); 7991 buffer[count++] = (u8)temp; 7992 } while (1); 7993 buffer_len = count; 7994 /* Number of args to fetch */ 7995 wdata.data.length = count; 7996 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 7997 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK; 7998 break; 7999 case IW_PRIV_TYPE_INT: 8000 /* Fetch args */ 8001 count = 0; 8002 do { 8003 str = strsep(&ptr, delim); 8004 if (NULL == str) 8005 break; 8006 sscanf(str, "%i", &temp); 8007 ((s32 *)buffer)[count++] = (s32)temp; 8008 } while (1); 8009 buffer_len = count * sizeof(s32); 8010 /* Number of args to fetch */ 8011 wdata.data.length = count; 8012 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 8013 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK; 8014 break; 8015 case IW_PRIV_TYPE_CHAR: 8016 if (len > 0) { 8017 /* Size of the string to fetch */ 8018 wdata.data.length = len; 8019 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) 8020 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK; 8021 8022 /* Fetch string */ 8023 memcpy(buffer, ptr, wdata.data.length); 8024 } else { 8025 wdata.data.length = 1; 8026 buffer[0] = '\0'; 8027 } 8028 buffer_len = wdata.data.length; 8029 break; 8030 default: 8031 DBG_88E("%s: Not yet implemented...\n", __func__); 8032 err = -1; 8033 goto exit; 8034 } 8035 8036 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) && 8037 (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) { 8038 DBG_88E("%s: The command %s needs exactly %d argument(s)...\n", 8039 __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK); 8040 err = -EINVAL; 8041 goto exit; 8042 } 8043 } else { 8044 /* if args to set */ 8045 wdata.data.length = 0L; 8046 } 8047 8048 /* Those two tests are important. They define how the driver 8049 * will have to handle the data */ 8050 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) && 8051 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) { 8052 /* First case : all SET args fit within wrq */ 8053 if (offset) 8054 wdata.mode = subcmd; 8055 memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset); 8056 } else { 8057 if ((priv_args[k].set_args == 0) && 8058 (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) && 8059 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) { 8060 /* Second case : no SET args, GET args fit within wrq */ 8061 if (offset) 8062 wdata.mode = subcmd; 8063 } else { 8064 /* Third case : args won't fit in wrq, or variable number of args */ 8065 if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) { 8066 err = -EFAULT; 8067 goto exit; 8068 } 8069 wdata.data.flags = subcmd; 8070 } 8071 } 8072 8073 kfree(input); 8074 input = NULL; 8075 8076 extra_size = 0; 8077 if (IW_IS_SET(priv_args[k].cmd)) { 8078 /* Size of set arguments */ 8079 extra_size = get_priv_size(priv_args[k].set_args); 8080 8081 /* Does it fits in iwr ? */ 8082 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) && 8083 ((extra_size + offset) <= IFNAMSIZ)) 8084 extra_size = 0; 8085 } else { 8086 /* Size of get arguments */ 8087 extra_size = get_priv_size(priv_args[k].get_args); 8088 8089 /* Does it fits in iwr ? */ 8090 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) && 8091 (extra_size <= IFNAMSIZ)) 8092 extra_size = 0; 8093 } 8094 8095 if (extra_size == 0) { 8096 extra = (u8 *)&wdata; 8097 kfree(buffer); 8098 buffer = NULL; 8099 } else { 8100 extra = buffer; 8101 } 8102 8103 handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV]; 8104 err = handler(dev, NULL, &wdata, extra); 8105 8106 /* If we have to get some data */ 8107 if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) && 8108 (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) { 8109 int j; 8110 int n = 0; /* number of args */ 8111 u8 str[20] = {0}; 8112 8113 /* Check where is the returned data */ 8114 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) && 8115 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) 8116 n = priv_args[k].get_args & IW_PRIV_SIZE_MASK; 8117 else 8118 n = wdata.data.length; 8119 8120 output = rtw_zmalloc(4096); 8121 if (NULL == output) { 8122 err = -ENOMEM; 8123 goto exit; 8124 } 8125 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) { 8126 case IW_PRIV_TYPE_BYTE: 8127 /* Display args */ 8128 for (j = 0; j < n; j++) { 8129 sprintf(str, "%d ", extra[j]); 8130 len = strlen(str); 8131 output_len = strlen(output); 8132 if ((output_len + len + 1) > 4096) { 8133 err = -E2BIG; 8134 goto exit; 8135 } 8136 memcpy(output+output_len, str, len); 8137 } 8138 break; 8139 case IW_PRIV_TYPE_INT: 8140 /* Display args */ 8141 for (j = 0; j < n; j++) { 8142 sprintf(str, "%d ", ((__s32 *)extra)[j]); 8143 len = strlen(str); 8144 output_len = strlen(output); 8145 if ((output_len + len + 1) > 4096) { 8146 err = -E2BIG; 8147 goto exit; 8148 } 8149 memcpy(output+output_len, str, len); 8150 } 8151 break; 8152 case IW_PRIV_TYPE_CHAR: 8153 /* Display args */ 8154 memcpy(output, extra, n); 8155 break; 8156 default: 8157 DBG_88E("%s: Not yet implemented...\n", __func__); 8158 err = -1; 8159 goto exit; 8160 } 8161 8162 output_len = strlen(output) + 1; 8163 wrq_data->data.length = output_len; 8164 if (copy_to_user(wrq_data->data.pointer, output, output_len)) { 8165 err = -EFAULT; 8166 goto exit; 8167 } 8168 } else { 8169 /* if args to set */ 8170 wrq_data->data.length = 0; 8171 } 8172 8173exit: 8174 kfree(input); 8175 kfree(buffer); 8176 kfree(output); 8177 return err; 8178} 8179 8180#include <rtw_android.h> 8181int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 8182{ 8183 struct iwreq *wrq = (struct iwreq *)rq; 8184 int ret = 0; 8185 8186 switch (cmd) { 8187 case RTL_IOCTL_WPA_SUPPLICANT: 8188 ret = wpa_supplicant_ioctl(dev, &wrq->u.data); 8189 break; 8190#ifdef CONFIG_88EU_AP_MODE 8191 case RTL_IOCTL_HOSTAPD: 8192 ret = rtw_hostapd_ioctl(dev, &wrq->u.data); 8193 break; 8194#endif /* CONFIG_88EU_AP_MODE */ 8195 case SIOCDEVPRIVATE: 8196 ret = rtw_ioctl_wext_private(dev, &wrq->u); 8197 break; 8198 case (SIOCDEVPRIVATE+1): 8199 ret = rtw_android_priv_cmd(dev, rq, cmd); 8200 break; 8201 default: 8202 ret = -EOPNOTSUPP; 8203 break; 8204 } 8205 return ret; 8206} 8207