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