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