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