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