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