Merge branch 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / staging / rtl8723bs / os_dep / ioctl_linux.c
CommitLineData
58391efd 1// SPDX-License-Identifier: GPL-2.0
554c0a3a
HG
2/******************************************************************************
3 *
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 *
554c0a3a
HG
6 ******************************************************************************/
7#define _IOCTL_LINUX_C_
8
2dcce8ed 9#include <linux/etherdevice.h>
554c0a3a
HG
10#include <drv_types.h>
11#include <rtw_debug.h>
12#include <rtw_mp.h>
7d6a6e7b 13#include <hal_btcoex.h>
554c0a3a 14#include <linux/jiffies.h>
60db8d10 15#include <linux/kernel.h>
554c0a3a 16
f85ac230 17#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV+30)
554c0a3a
HG
18
19#define SCAN_ITEM_SIZE 768
20#define MAX_CUSTOM_LEN 64
21#define RATE_COUNT 4
22
23/* combo scan */
554c0a3a
HG
24#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
25#define WEXT_CSCAN_HEADER_SIZE 12
26#define WEXT_CSCAN_SSID_SECTION 'S'
27#define WEXT_CSCAN_CHANNEL_SECTION 'C'
554c0a3a
HG
28#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
29#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
30#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
31#define WEXT_CSCAN_TYPE_SECTION 'T'
32
554c0a3a
HG
33static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
34 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
35
f85ac230 36static const char * const iw_operation_mode[] = {
554c0a3a
HG
37 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor"
38};
39
554c0a3a
HG
40void indicate_wx_scan_complete_event(struct adapter *padapter)
41{
42 union iwreq_data wrqu;
43
44 memset(&wrqu, 0, sizeof(union iwreq_data));
45
46 /* DBG_871X("+rtw_indicate_wx_scan_complete_event\n"); */
47}
48
49
50void rtw_indicate_wx_assoc_event(struct adapter *padapter)
51{
52 union iwreq_data wrqu;
53 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
54 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
55 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
a7dd567e 56 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
554c0a3a
HG
57
58 memset(&wrqu, 0, sizeof(union iwreq_data));
59
60 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
61
c77761d6 62 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
554c0a3a
HG
63 memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
64 else
65 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
66
67 DBG_871X_LEVEL(_drv_always_, "assoc success\n");
68}
69
70void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
71{
72 union iwreq_data wrqu;
73
74 memset(&wrqu, 0, sizeof(union iwreq_data));
75
76 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2dcce8ed 77 eth_zero_addr(wrqu.ap_addr.sa_data);
554c0a3a
HG
78}
79
554c0a3a
HG
80static char *translate_scan(struct adapter *padapter,
81 struct iw_request_info* info, struct wlan_network *pnetwork,
82 char *start, char *stop)
83{
84 struct iw_event iwe;
85 u16 cap;
86 u32 ht_ielen = 0;
87 char *custom = NULL;
88 char *p;
c77761d6 89 u16 max_rate = 0, rate, ht_cap = false, vht_cap = false;
554c0a3a
HG
90 u32 i = 0;
91 u8 bw_40MHz = 0, short_GI = 0;
92 u16 mcs_rate = 0, vht_data_rate = 0;
c77761d6 93 u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12);
554c0a3a
HG
94 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
95 u8 ss, sq;
96
97 /* AP MAC address */
98 iwe.cmd = SIOCGIWAP;
99 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
100
101 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
102 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
103
104 /* Add the ESSID */
105 iwe.cmd = SIOCGIWESSID;
106 iwe.u.data.flags = 1;
107 iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
108 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
109
110 /* parsing HT_CAP_IE */
f85ac230 111 if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
554c0a3a 112 p = rtw_get_ie(&pnetwork->network.IEs[0], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength);
f85ac230 113 } else {
554c0a3a
HG
114 p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
115 }
c77761d6 116 if (p && ht_ielen > 0) {
554c0a3a
HG
117 struct rtw_ieee80211_ht_cap *pht_capie;
118 ht_cap = true;
119 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
c77761d6 120 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
554c0a3a
HG
121 bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
122 short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
123 }
124
125 /* Add the protocol name */
126 iwe.cmd = SIOCGIWNAME;
153c6b11
MS
127 if (rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) {
128 if (ht_cap)
554c0a3a
HG
129 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
130 else
131 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
153c6b11
MS
132 } else if (rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) {
133 if (ht_cap)
554c0a3a
HG
134 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
135 else
136 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
f85ac230
TD
137 } else {
138 if (pnetwork->network.Configuration.DSConfig > 14) {
153c6b11 139 if (vht_cap)
554c0a3a 140 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC");
153c6b11 141 else if (ht_cap)
554c0a3a
HG
142 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
143 else
144 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
f85ac230 145 } else {
153c6b11 146 if (ht_cap)
554c0a3a
HG
147 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
148 else
149 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
150 }
151 }
152
153 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
154
155 /* Add mode */
f85ac230 156 if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
554c0a3a 157 cap = 0;
f85ac230 158 } else {
554c0a3a
HG
159 __le16 le_tmp;
160
161 iwe.cmd = SIOCGIWMODE;
162 memcpy((u8 *)&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
163 cap = le16_to_cpu(le_tmp);
164 }
165
c77761d6 166 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
554c0a3a
HG
167 if (cap & WLAN_CAPABILITY_BSS)
168 iwe.u.mode = IW_MODE_MASTER;
169 else
170 iwe.u.mode = IW_MODE_ADHOC;
171
172 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
173 }
174
c77761d6 175 if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig > 14*/)
554c0a3a
HG
176 pnetwork->network.Configuration.DSConfig = 1;
177
178 /* Add frequency/channel */
179 iwe.cmd = SIOCGIWFREQ;
180 iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
181 iwe.u.freq.e = 1;
182 iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
183 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
184
185 /* Add encryption capability */
186 iwe.cmd = SIOCGIWENCODE;
187 if (cap & WLAN_CAPABILITY_PRIVACY)
188 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
189 else
190 iwe.u.data.flags = IW_ENCODE_DISABLED;
191 iwe.u.data.length = 0;
192 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
193
194 /*Add basic and extended rates */
195 max_rate = 0;
196 custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC);
197 if (!custom)
198 return start;
199 p = custom;
038341dc 200 p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
c77761d6 201 while (pnetwork->network.SupportedRates[i] != 0) {
554c0a3a
HG
202 rate = pnetwork->network.SupportedRates[i]&0x7F;
203 if (rate > max_rate)
204 max_rate = rate;
038341dc 205 p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
554c0a3a
HG
206 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
207 i++;
208 }
209
e2b13595 210 if (vht_cap) {
554c0a3a 211 max_rate = vht_data_rate;
e2b13595 212 } else if (ht_cap) {
f85ac230 213 if (mcs_rate&0x8000) { /* MCS15 */
554c0a3a 214 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
f85ac230 215 } else { /* default MCS7 */
554c0a3a
HG
216 /* DBG_871X("wx_get_scan, mcs_rate_bitmap = 0x%x\n", mcs_rate); */
217 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
218 }
219
220 max_rate = max_rate*2;/* Mbps/2; */
221 }
222
223 iwe.cmd = SIOCGIWRATE;
224 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
225 iwe.u.bitrate.value = max_rate * 500000;
226 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
227
228 /* parsing WPA/WPA2 IE */
f85ac230 229 if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
554c0a3a
HG
230 u8 *buf;
231 u8 wpa_ie[255], rsn_ie[255];
232 u16 wpa_len = 0, rsn_len = 0;
233 u8 *p;
a21a773f 234 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
554c0a3a
HG
235 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
236 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
237
05e540b2 238 buf = kzalloc(MAX_WPA_IE_LEN*2, GFP_ATOMIC);
554c0a3a
HG
239 if (!buf)
240 return start;
241 if (wpa_len > 0) {
c77761d6 242 p = buf;
554c0a3a 243 p += sprintf(p, "wpa_ie =");
f85ac230 244 for (i = 0; i < wpa_len; i++)
554c0a3a 245 p += sprintf(p, "%02x", wpa_ie[i]);
554c0a3a
HG
246
247 if (wpa_len > 100) {
248 printk("-----------------Len %d----------------\n", wpa_len);
f85ac230 249 for (i = 0; i < wpa_len; i++)
554c0a3a 250 printk("%02x ", wpa_ie[i]);
554c0a3a
HG
251 printk("\n");
252 printk("-----------------Len %d----------------\n", wpa_len);
253 }
254
255 memset(&iwe, 0, sizeof(iwe));
256 iwe.cmd = IWEVCUSTOM;
257 iwe.u.data.length = strlen(buf);
258 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
259
260 memset(&iwe, 0, sizeof(iwe));
c77761d6 261 iwe.cmd = IWEVGENIE;
554c0a3a
HG
262 iwe.u.data.length = wpa_len;
263 start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
264 }
265 if (rsn_len > 0) {
266 p = buf;
267 memset(buf, 0, MAX_WPA_IE_LEN*2);
268 p += sprintf(p, "rsn_ie =");
269 for (i = 0; i < rsn_len; i++)
270 p += sprintf(p, "%02x", rsn_ie[i]);
271 memset(&iwe, 0, sizeof(iwe));
272 iwe.cmd = IWEVCUSTOM;
273 iwe.u.data.length = strlen(buf);
274 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
275
276 memset(&iwe, 0, sizeof(iwe));
c77761d6 277 iwe.cmd = IWEVGENIE;
554c0a3a
HG
278 iwe.u.data.length = rsn_len;
279 start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
280 }
281 kfree(buf);
282 }
283
284 { /* parsing WPS IE */
285 uint cnt = 0, total_ielen;
286 u8 *wpsie_ptr = NULL;
287 uint wps_ielen = 0;
288
c5f69117 289 u8 *ie_ptr;
554c0a3a
HG
290 total_ielen = pnetwork->network.IELength - ie_offset;
291
f85ac230 292 if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
554c0a3a
HG
293 ie_ptr = pnetwork->network.IEs;
294 total_ielen = pnetwork->network.IELength;
f85ac230 295 } else { /* Beacon or Probe Respones */
554c0a3a
HG
296 ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
297 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
298 }
299
f85ac230 300 while (cnt < total_ielen) {
c77761d6 301 if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
554c0a3a 302 wpsie_ptr = &ie_ptr[cnt];
c77761d6 303 iwe.cmd = IWEVGENIE;
554c0a3a
HG
304 iwe.u.data.length = (u16)wps_ielen;
305 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
306 }
c77761d6 307 cnt += ie_ptr[cnt + 1] + 2; /* goto next */
554c0a3a
HG
308 }
309 }
310
311 /* Add quality statistics */
312 iwe.cmd = IWEVQUAL;
313 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
314 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
315 | IW_QUAL_NOISE_UPDATED
316 #else
317 | IW_QUAL_NOISE_INVALID
318 #endif
319 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
320 | IW_QUAL_DBM
321 #endif
322 ;
323
324 if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
325 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
326 ss = padapter->recvpriv.signal_strength;
327 sq = padapter->recvpriv.signal_qual;
328 } else {
329 ss = pnetwork->network.PhyInfo.SignalStrength;
330 sq = pnetwork->network.PhyInfo.SignalQuality;
331 }
332
333
334 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
54da60be 335 iwe.u.qual.level = (u8)translate_percentage_to_dbm(ss);/* dbm */
554c0a3a
HG
336 #else
337 #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
338 {
339 /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
340
341 struct hal_com_data *pHal = GET_HAL_DATA(padapter);
342
343 iwe.u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss);
344 }
345 #else
346 iwe.u.qual.level = (u8)ss;/* */
347 #endif
348 #endif
349
350 iwe.u.qual.qual = (u8)sq; /* signal quality */
351
352 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
353 {
354 s16 tmp_noise = 0;
c77761d6
LS
355 rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
356 iwe.u.qual.noise = tmp_noise;
554c0a3a
HG
357 }
358 #else
359 iwe.u.qual.noise = 0; /* noise level */
360 #endif
361
362 /* DBG_871X("iqual =%d, ilevel =%d, inoise =%d, iupdated =%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated); */
363
364 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
365
366 {
367 u8 *buf;
368 u8 *p, *pos;
369
05e540b2 370 buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
554c0a3a
HG
371 if (!buf)
372 goto exit;
373 p = buf;
374 pos = pnetwork->network.Reserved;
375 p += sprintf(p, "fm =%02X%02X", pos[1], pos[0]);
376 memset(&iwe, 0, sizeof(iwe));
377 iwe.cmd = IWEVCUSTOM;
378 iwe.u.data.length = strlen(buf);
379 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
380 kfree(buf);
381 }
382exit:
383 kfree(custom);
384
385 return start;
386}
387
388static int wpa_set_auth_algs(struct net_device *dev, u32 value)
389{
54da60be 390 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
554c0a3a
HG
391 int ret = 0;
392
5befa937
QK
393 if ((value & WLAN_AUTH_SHARED_KEY) && (value & WLAN_AUTH_OPEN)) {
394 DBG_871X("wpa_set_auth_algs, WLAN_AUTH_SHARED_KEY and WLAN_AUTH_OPEN [value:0x%x]\n", value);
554c0a3a
HG
395 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
396 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
397 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
5befa937
QK
398 } else if (value & WLAN_AUTH_SHARED_KEY) {
399 DBG_871X("wpa_set_auth_algs, WLAN_AUTH_SHARED_KEY [value:0x%x]\n", value);
554c0a3a
HG
400 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
401
402 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
403 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
5befa937
QK
404 } else if (value & WLAN_AUTH_OPEN) {
405 DBG_871X("wpa_set_auth_algs, WLAN_AUTH_OPEN\n");
554c0a3a 406 /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
f85ac230 407 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
554c0a3a
HG
408 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
409 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
410 }
5befa937
QK
411 } else if (value & WLAN_AUTH_LEAP) {
412 DBG_871X("wpa_set_auth_algs, WLAN_AUTH_LEAP\n");
f85ac230 413 } else {
554c0a3a
HG
414 DBG_871X("wpa_set_auth_algs, error!\n");
415 ret = -EINVAL;
416 }
417
418 return ret;
419
420}
421
422static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
423{
424 int ret = 0;
425 u32 wep_key_idx, wep_key_len, wep_total_len;
426 struct ndis_802_11_wep *pwep = NULL;
427 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
428 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
429 struct security_priv *psecuritypriv = &padapter->securitypriv;
430
431 param->u.crypt.err = 0;
432 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
433
54da60be 434 if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
554c0a3a
HG
435 ret = -EINVAL;
436 goto exit;
437 }
438
439 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
440 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230 441 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
6557ddfe 442 if (param->u.crypt.idx >= WEP_KEYS ||
554c0a3a
HG
443 param->u.crypt.idx >= BIP_MAX_KEYID) {
444 ret = -EINVAL;
445 goto exit;
446 }
f85ac230 447 } else {
554c0a3a
HG
448 {
449 ret = -EINVAL;
450 goto exit;
451 }
452 }
453
f85ac230 454 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
554c0a3a
HG
455 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
456 DBG_871X("wpa_set_encryption, crypt.alg = WEP\n");
457
458 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
459 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
460 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
461
462 wep_key_idx = param->u.crypt.idx;
463 wep_key_len = param->u.crypt.key_len;
464
465 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
466 DBG_871X("(1)wep_key_idx =%d\n", wep_key_idx);
467
468 if (wep_key_idx > WEP_KEYS)
469 return -EINVAL;
470
471 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
472
f85ac230 473 if (wep_key_len > 0) {
554c0a3a
HG
474 wep_key_len = wep_key_len <= 5 ? 5 : 13;
475 wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
6254acde 476 pwep = kzalloc(wep_total_len, GFP_KERNEL);
554c0a3a
HG
477 if (pwep == NULL) {
478 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
479 goto exit;
480 }
481
554c0a3a
HG
482 pwep->KeyLength = wep_key_len;
483 pwep->Length = wep_total_len;
484
f85ac230 485 if (wep_key_len == 13) {
554c0a3a
HG
486 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
487 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
488 }
f85ac230 489 } else {
554c0a3a
HG
490 ret = -EINVAL;
491 goto exit;
492 }
493
494 pwep->KeyIndex = wep_key_idx;
495 pwep->KeyIndex |= 0x80000000;
496
497 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
498
f85ac230 499 if (param->u.crypt.set_tx) {
554c0a3a
HG
500 DBG_871X("wep, set_tx = 1\n");
501
502 if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
c77761d6 503 ret = -EOPNOTSUPP;
f85ac230 504 } else {
554c0a3a
HG
505 DBG_871X("wep, set_tx = 0\n");
506
507 /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
508 /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */
509
510 if (wep_key_idx >= WEP_KEYS) {
c77761d6 511 ret = -EOPNOTSUPP;
554c0a3a
HG
512 goto exit;
513 }
514
515 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
c77761d6 516 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
554c0a3a
HG
517 rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
518 }
519
520 goto exit;
521 }
522
f85ac230 523 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
d840eb63
MS
524 struct sta_info *psta, *pbcmc_sta;
525 struct sta_priv *pstapriv = &padapter->stapriv;
554c0a3a 526
f85ac230 527 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
554c0a3a
HG
528 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
529 if (psta == NULL) {
530 /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
f85ac230 531 } else {
554c0a3a
HG
532 /* Jeff: don't disable ieee8021x_blocked while clearing key */
533 if (strcmp(param->u.crypt.alg, "none") != 0)
534 psta->ieee8021x_blocked = false;
535
c77761d6 536 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
f85ac230 537 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) {
554c0a3a
HG
538 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
539 }
540
f85ac230 541 if (param->u.crypt.set_tx == 1) { /* pairwise key */
c77761d6 542 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a 543
f85ac230 544 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
554c0a3a
HG
545 /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
546 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
547 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
548
c77761d6 549 padapter->securitypriv.busetkipkey = false;
554c0a3a
HG
550 /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
551 }
552
553 /* DEBUG_ERR((" param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
554 DBG_871X(" ~~~~set sta key:unicastkey\n");
555
556 rtw_setstakey_cmd(padapter, psta, true, true);
f85ac230
TD
557 } else { /* group key */
558 if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
c77761d6 559 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));
554c0a3a 560 /* only TKIP group key need to install this */
f85ac230 561 if (param->u.crypt.key_len > 16) {
c77761d6
LS
562 memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
563 memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
554c0a3a
HG
564 }
565 padapter->securitypriv.binstallGrpkey = true;
566 /* DEBUG_ERR((" param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
567 DBG_871X(" ~~~~set sta key:groupkey\n");
568
569 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
570
c77761d6 571 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
f85ac230 572 } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
554c0a3a
HG
573 /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
574 /* save the IGTK key, length 16 bytes */
c77761d6 575 memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a
HG
576 /*printk("IGTK key below:\n");
577 for (no = 0;no<16;no++)
578 printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
579 printk("\n");*/
580 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
581 padapter->securitypriv.binstallBIPkey = true;
582 DBG_871X(" ~~~~set sta key:IGKT\n");
583 }
584 }
585 }
586
c77761d6 587 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
f85ac230 588 if (pbcmc_sta == NULL) {
554c0a3a 589 /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
f85ac230 590 } else {
554c0a3a
HG
591 /* Jeff: don't disable ieee8021x_blocked while clearing key */
592 if (strcmp(param->u.crypt.alg, "none") != 0)
593 pbcmc_sta->ieee8021x_blocked = false;
594
c77761d6 595 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
f85ac230 596 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) {
554c0a3a
HG
597 pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
598 }
599 }
f85ac230
TD
600 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
601 /* adhoc mode */
554c0a3a
HG
602 }
603 }
604
605exit:
606
428715ba 607 kfree(pwep);
554c0a3a
HG
608 return ret;
609}
610
611static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
612{
288f9aca 613 u8 *buf = NULL;
554c0a3a
HG
614 int group_cipher = 0, pairwise_cipher = 0;
615 int ret = 0;
c77761d6 616 u8 null_addr[] = {0, 0, 0, 0, 0, 0};
554c0a3a
HG
617
618 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
619 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
620 if (pie == NULL)
621 return ret;
622 else
623 return -EINVAL;
624 }
625
f85ac230 626 if (ielen) {
554c0a3a
HG
627 buf = rtw_zmalloc(ielen);
628 if (buf == NULL) {
629 ret = -ENOMEM;
630 goto exit;
631 }
632
c77761d6 633 memcpy(buf, pie, ielen);
554c0a3a
HG
634
635 /* dump */
636 {
637 int i;
638 DBG_871X("\n wpa_ie(length:%d):\n", ielen);
c77761d6 639 for (i = 0; i < ielen; i = i + 8)
554c0a3a
HG
640 DBG_871X("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]);
641 }
642
554c0a3a
HG
643 if (ielen < RSN_HEADER_LEN) {
644 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
645 ret = -1;
646 goto exit;
647 }
648
f85ac230 649 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
554c0a3a 650 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
c77761d6 651 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
554c0a3a
HG
652 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
653 }
654
f85ac230 655 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
554c0a3a 656 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
c77761d6 657 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
554c0a3a
HG
658 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
659 }
660
661 if (group_cipher == 0)
554c0a3a 662 group_cipher = WPA_CIPHER_NONE;
554c0a3a 663 if (pairwise_cipher == 0)
554c0a3a 664 pairwise_cipher = WPA_CIPHER_NONE;
554c0a3a 665
f85ac230 666 switch (group_cipher) {
554c0a3a
HG
667 case WPA_CIPHER_NONE:
668 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
c77761d6 669 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
554c0a3a
HG
670 break;
671 case WPA_CIPHER_WEP40:
672 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
673 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
674 break;
675 case WPA_CIPHER_TKIP:
676 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
677 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
678 break;
679 case WPA_CIPHER_CCMP:
680 padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
681 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
682 break;
683 case WPA_CIPHER_WEP104:
684 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
685 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
686 break;
687 }
688
f85ac230 689 switch (pairwise_cipher) {
554c0a3a
HG
690 case WPA_CIPHER_NONE:
691 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
c77761d6 692 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
554c0a3a
HG
693 break;
694 case WPA_CIPHER_WEP40:
695 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
696 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
697 break;
698 case WPA_CIPHER_TKIP:
699 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
700 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
701 break;
702 case WPA_CIPHER_CCMP:
703 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
704 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
705 break;
706 case WPA_CIPHER_WEP104:
707 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
708 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
709 break;
710 }
711
712 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
713 {/* set wps_ie */
714 u16 cnt = 0;
c77761d6 715 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
554c0a3a 716
f85ac230 717 while (cnt < ielen) {
554c0a3a
HG
718 eid = buf[cnt];
719
f85ac230 720 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
554c0a3a
HG
721 DBG_871X("SET WPS_IE\n");
722
723 padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN;
724
725 memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
726
727 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
728
729 cnt += buf[cnt+1]+2;
730
731 break;
732 } else {
733 cnt += buf[cnt+1]+2; /* goto next */
734 }
735 }
736 }
737 }
738
739 /* TKIP and AES disallow multicast packets until installing group key */
740 if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
741 || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
742 || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
743 /* WPS open need to enable multicast */
744 /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
745 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
746
747 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
748 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
749 pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
750
751exit:
752
7ad61a38 753 kfree(buf);
554c0a3a
HG
754
755 return ret;
756}
757
758static int rtw_wx_get_name(struct net_device *dev,
759 struct iw_request_info *info,
760 union iwreq_data *wrqu, char *extra)
761{
762 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
763 u32 ht_ielen = 0;
764 char *p;
c77761d6 765 u8 ht_cap = false, vht_cap = false;
554c0a3a
HG
766 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
767 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
768 NDIS_802_11_RATES_EX* prates = NULL;
769
770 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
771
772 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
773 /* parsing HT_CAP_IE */
774 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
c77761d6 775 if (p && ht_ielen > 0)
554c0a3a 776 ht_cap = true;
554c0a3a
HG
777
778 prates = &pcur_bss->SupportedRates;
779
153c6b11
MS
780 if (rtw_is_cckratesonly_included((u8 *)prates)) {
781 if (ht_cap)
554c0a3a
HG
782 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
783 else
784 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
153c6b11
MS
785 } else if (rtw_is_cckrates_included((u8 *)prates)) {
786 if (ht_cap)
554c0a3a
HG
787 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
788 else
789 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
f85ac230
TD
790 } else {
791 if (pcur_bss->Configuration.DSConfig > 14) {
153c6b11 792 if (vht_cap)
554c0a3a 793 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC");
153c6b11 794 else if (ht_cap)
554c0a3a
HG
795 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
796 else
797 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
f85ac230 798 } else {
153c6b11 799 if (ht_cap)
554c0a3a
HG
800 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
801 else
802 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
803 }
804 }
f85ac230 805 } else {
554c0a3a
HG
806 /* prates = &padapter->registrypriv.dev_network.SupportedRates; */
807 /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
808 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
809 }
810 return 0;
811}
812
813static int rtw_wx_set_freq(struct net_device *dev,
814 struct iw_request_info *info,
815 union iwreq_data *wrqu, char *extra)
816{
817 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
818
819 return 0;
820}
821
822static int rtw_wx_get_freq(struct net_device *dev,
823 struct iw_request_info *info,
824 union iwreq_data *wrqu, char *extra)
825{
826 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
827 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
828 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
829
f85ac230 830 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
554c0a3a
HG
831 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
832 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
833 wrqu->freq.e = 1;
834 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
835
f85ac230 836 } else {
554c0a3a
HG
837 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
838 wrqu->freq.e = 1;
839 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
840 }
841
842 return 0;
843}
844
845static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
846 union iwreq_data *wrqu, char *b)
847{
848 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
c77761d6 849 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
554c0a3a
HG
850 int ret = 0;
851
852 if (_FAIL == rtw_pwr_wakeup(padapter)) {
853 ret = -EPERM;
854 goto exit;
855 }
856
e2b13595 857 if (!padapter->hw_init_completed) {
554c0a3a
HG
858 ret = -EPERM;
859 goto exit;
860 }
861
f85ac230 862 switch (wrqu->mode) {
554c0a3a
HG
863 case IW_MODE_AUTO:
864 networkType = Ndis802_11AutoUnknown;
865 DBG_871X("set_mode = IW_MODE_AUTO\n");
866 break;
867 case IW_MODE_ADHOC:
868 networkType = Ndis802_11IBSS;
869 DBG_871X("set_mode = IW_MODE_ADHOC\n");
870 break;
871 case IW_MODE_MASTER:
872 networkType = Ndis802_11APMode;
873 DBG_871X("set_mode = IW_MODE_MASTER\n");
874 /* rtw_setopmode_cmd(padapter, networkType, true); */
875 break;
876 case IW_MODE_INFRA:
877 networkType = Ndis802_11Infrastructure;
878 DBG_871X("set_mode = IW_MODE_INFRA\n");
879 break;
880
c77761d6 881 default:
1590fb3a 882 ret = -EINVAL;
554c0a3a
HG
883 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported \n", iw_operation_mode[wrqu->mode]));
884 goto exit;
885 }
886
887/*
888 if (Ndis802_11APMode == networkType)
889 {
890 rtw_setopmode_cmd(padapter, networkType, true);
891 }
892 else
893 {
894 rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown, true);
895 }
896*/
897
c77761d6 898 if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
554c0a3a
HG
899
900 ret = -EPERM;
901 goto exit;
902
903 }
904
905 rtw_setopmode_cmd(padapter, networkType, true);
906
907exit:
908 return ret;
909}
910
911static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
912 union iwreq_data *wrqu, char *b)
913{
914 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
915 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
916
917 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
918
f85ac230 919 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
554c0a3a 920 wrqu->mode = IW_MODE_INFRA;
f85ac230
TD
921 } else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
922 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
554c0a3a 923 wrqu->mode = IW_MODE_ADHOC;
f85ac230 924 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
554c0a3a 925 wrqu->mode = IW_MODE_MASTER;
f85ac230 926 } else {
554c0a3a
HG
927 wrqu->mode = IW_MODE_AUTO;
928 }
929 return 0;
930}
931
932
933static int rtw_wx_set_pmkid(struct net_device *dev,
934 struct iw_request_info *a,
935 union iwreq_data *wrqu, char *extra)
936{
937 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
938 u8 j, blInserted = false;
939 int intReturn = false;
940 struct security_priv *psecuritypriv = &padapter->securitypriv;
a7dd567e 941 struct iw_pmksa* pPMK = (struct iw_pmksa *)extra;
c77761d6
LS
942 u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };
943 u8 strIssueBssid[ETH_ALEN] = { 0x00 };
554c0a3a
HG
944
945 /*
946 There are the BSSID information in the bssid.sa_data array.
947 If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
948 If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
949 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
950 */
951
952 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
f85ac230 953 if (pPMK->cmd == IW_PMKSA_ADD) {
554c0a3a
HG
954 DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
955 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
5b07a390 956 return intReturn;
554c0a3a 957 else
554c0a3a 958 intReturn = true;
f85ac230 959
554c0a3a
HG
960 blInserted = false;
961
962 /* overwrite PMKID */
c77761d6 963 for (j = 0; j < NUM_PMKID_CACHE; j++) {
f85ac230
TD
964 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
965 /* BSSID is matched, the same AP => rewrite with new PMKID. */
554c0a3a
HG
966 DBG_871X("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
967
968 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
c77761d6 969 psecuritypriv->PMKIDList[j].bUsed = true;
554c0a3a
HG
970 psecuritypriv->PMKIDIndex = j+1;
971 blInserted = true;
972 break;
973 }
974 }
975
f85ac230 976 if (!blInserted) {
554c0a3a
HG
977 /* Find a new entry */
978 DBG_871X("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
979 psecuritypriv->PMKIDIndex);
980
981 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
982 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
983
c77761d6
LS
984 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
985 psecuritypriv->PMKIDIndex++;
554c0a3a 986 if (psecuritypriv->PMKIDIndex == 16)
554c0a3a 987 psecuritypriv->PMKIDIndex = 0;
554c0a3a 988 }
f85ac230 989 } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
554c0a3a
HG
990 DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
991 intReturn = true;
c77761d6 992 for (j = 0; j < NUM_PMKID_CACHE; j++) {
f85ac230
TD
993 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
994 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
2dcce8ed 995 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
c77761d6 996 psecuritypriv->PMKIDList[j].bUsed = false;
554c0a3a
HG
997 break;
998 }
999 }
f85ac230 1000 } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
554c0a3a 1001 DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
c77761d6 1002 memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
554c0a3a
HG
1003 psecuritypriv->PMKIDIndex = 0;
1004 intReturn = true;
1005 }
1006 return intReturn;
1007}
1008
1009static int rtw_wx_get_sens(struct net_device *dev,
1010 struct iw_request_info *info,
1011 union iwreq_data *wrqu, char *extra)
1012{
1013 {
1014 wrqu->sens.value = 0;
1015 wrqu->sens.fixed = 0; /* no auto select */
1016 wrqu->sens.disabled = 1;
1017 }
1018 return 0;
1019}
1020
1021static int rtw_wx_get_range(struct net_device *dev,
1022 struct iw_request_info *info,
1023 union iwreq_data *wrqu, char *extra)
1024{
1025 struct iw_range *range = (struct iw_range *)extra;
1026 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1027 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1028
1029 u16 val;
1030 int i;
1031
1032 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
1033
1034 wrqu->data.length = sizeof(*range);
1035 memset(range, 0, sizeof(*range));
1036
1037 /* Let's try to keep this struct in the same order as in
1038 * linux/include/wireless.h
1039 */
1040
1041 /* TODO: See what values we can set, and remove the ones we can't
1042 * set, or fill them with some default data.
1043 */
1044
1045 /* ~5 Mb/s real (802.11b) */
1046 range->throughput = 5 * 1000 * 1000;
1047
1048 /* signal level threshold range */
1049
1050 /* percent values between 0 and 100. */
1051 range->max_qual.qual = 100;
1052 range->max_qual.level = 100;
1053 range->max_qual.noise = 100;
1054 range->max_qual.updated = 7; /* Updated all three */
1055
1056
1057 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
1058 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
1059 range->avg_qual.level = 256 - 78;
1060 range->avg_qual.noise = 0;
1061 range->avg_qual.updated = 7; /* Updated all three */
1062
1063 range->num_bitrates = RATE_COUNT;
1064
f85ac230 1065 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
554c0a3a 1066 range->bitrate[i] = rtw_rates[i];
554c0a3a
HG
1067
1068 range->min_frag = MIN_FRAG_THRESHOLD;
1069 range->max_frag = MAX_FRAG_THRESHOLD;
1070
1071 range->pm_capa = 0;
1072
1073 range->we_version_compiled = WIRELESS_EXT;
1074 range->we_version_source = 16;
1075
1076 for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
1077
1078 /* Include only legal frequencies for some countries */
f85ac230 1079 if (pmlmeext->channel_set[i].ChannelNum != 0) {
554c0a3a
HG
1080 range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
1081 range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
1082 range->freq[val].e = 1;
1083 val++;
1084 }
1085
1086 if (val == IW_MAX_FREQUENCIES)
1087 break;
1088 }
1089
1090 range->num_channels = val;
1091 range->num_frequency = val;
1092
1093/* Commented by Albert 2009/10/13 */
1094/* The following code will proivde the security capability to network manager. */
1095/* If the driver doesn't provide this capability to network manager, */
8fd1e027 1096/* the WPA/WPA2 routers can't be chosen in the network manager. */
554c0a3a
HG
1097
1098/*
1099#define IW_SCAN_CAPA_NONE 0x00
1100#define IW_SCAN_CAPA_ESSID 0x01
1101#define IW_SCAN_CAPA_BSSID 0x02
1102#define IW_SCAN_CAPA_CHANNEL 0x04
1103#define IW_SCAN_CAPA_MODE 0x08
1104#define IW_SCAN_CAPA_RATE 0x10
1105#define IW_SCAN_CAPA_TYPE 0x20
1106#define IW_SCAN_CAPA_TIME 0x40
1107*/
1108
c77761d6
LS
1109 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1110 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
554c0a3a 1111
c77761d6
LS
1112 range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_BSSID |
1113 IW_SCAN_CAPA_CHANNEL | IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
554c0a3a
HG
1114
1115 return 0;
1116}
1117
1118/* set bssid flow */
1119/* s1. rtw_set_802_11_infrastructure_mode() */
1120/* s2. rtw_set_802_11_authentication_mode() */
1121/* s3. set_802_11_encryption_mode() */
1122/* s4. rtw_set_802_11_bssid() */
1123static int rtw_wx_set_wap(struct net_device *dev,
1124 struct iw_request_info *info,
1125 union iwreq_data *awrq,
1126 char *extra)
1127{
1128 uint ret = 0;
1129 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1130 struct sockaddr *temp = (struct sockaddr *)awrq;
1131 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1132 struct list_head *phead;
1133 u8 *dst_bssid, *src_bssid;
1134 struct __queue *queue = &(pmlmepriv->scanned_queue);
1135 struct wlan_network *pnetwork = NULL;
1136 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1137
1138 rtw_ps_deny(padapter, PS_DENY_JOIN);
f85ac230 1139 if (_FAIL == rtw_pwr_wakeup(padapter)) {
554c0a3a
HG
1140 ret = -1;
1141 goto exit;
1142 }
1143
1144 if (!padapter->bup) {
1145 ret = -1;
1146 goto exit;
1147 }
1148
1149
1150 if (temp->sa_family != ARPHRD_ETHER) {
1151 ret = -EINVAL;
1152 goto exit;
1153 }
1154
1155 authmode = padapter->securitypriv.ndisauthtype;
1156 spin_lock_bh(&queue->lock);
1157 phead = get_list_head(queue);
1158 pmlmepriv->pscanned = get_next(phead);
1159
1160 while (1) {
1161 if (phead == pmlmepriv->pscanned)
1162 break;
1163
1164 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
1165
1166 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1167
1168 dst_bssid = pnetwork->network.MacAddress;
1169
1170 src_bssid = temp->sa_data;
1171
f85ac230
TD
1172 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1173 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
554c0a3a
HG
1174 ret = -1;
1175 spin_unlock_bh(&queue->lock);
1176 goto exit;
1177 }
9cc579cc 1178 break;
554c0a3a
HG
1179 }
1180
1181 }
1182 spin_unlock_bh(&queue->lock);
1183
1184 rtw_set_802_11_authentication_mode(padapter, authmode);
1185 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1186 if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1187 ret = -1;
1188 goto exit;
1189 }
1190
1191exit:
1192
1193 rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1194
1195 return ret;
1196}
1197
1198static int rtw_wx_get_wap(struct net_device *dev,
1199 struct iw_request_info *info,
1200 union iwreq_data *wrqu, char *extra)
1201{
1202
1203 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1204 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1205 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1206
1207 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1208
2dcce8ed 1209 eth_zero_addr(wrqu->ap_addr.sa_data);
554c0a3a
HG
1210
1211 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
1212
1213 if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1214 ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
f85ac230 1215 ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true)) {
554c0a3a 1216 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
f85ac230 1217 } else {
2dcce8ed 1218 eth_zero_addr(wrqu->ap_addr.sa_data);
554c0a3a
HG
1219 }
1220
1221 return 0;
1222}
1223
1224static int rtw_wx_set_mlme(struct net_device *dev,
1225 struct iw_request_info *info,
1226 union iwreq_data *wrqu, char *extra)
1227{
1228 int ret = 0;
1229 u16 reason;
1230 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
54da60be 1231 struct iw_mlme *mlme = (struct iw_mlme *)extra;
554c0a3a
HG
1232
1233
1234 if (mlme == NULL)
1235 return -1;
1236
1237 DBG_871X("%s\n", __func__);
1238
1239 reason = mlme->reason_code;
1240
1241 DBG_871X("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1242
f85ac230 1243 switch (mlme->cmd) {
554c0a3a
HG
1244 case IW_MLME_DEAUTH:
1245 if (!rtw_set_802_11_disassociate(padapter))
1246 ret = -1;
1247 break;
1248 case IW_MLME_DISASSOC:
1249 if (!rtw_set_802_11_disassociate(padapter))
1250 ret = -1;
1251 break;
1252 default:
1253 return -EOPNOTSUPP;
1254 }
1255
1256 return ret;
1257}
1258
1259static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1260 union iwreq_data *wrqu, char *extra)
1261{
1262 u8 _status = false;
1263 int ret = 0;
1264 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1265 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1266 struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1267 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
1268
1269 #ifdef DBG_IOCTL
1270 DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__);
1271 #endif
1272
1273 rtw_ps_deny(padapter, PS_DENY_SCAN);
f85ac230 1274 if (_FAIL == rtw_pwr_wakeup(padapter)) {
554c0a3a
HG
1275 ret = -1;
1276 goto exit;
1277 }
1278
1279 if (padapter->bDriverStopped) {
1280 DBG_871X("bDriverStopped =%d\n", padapter->bDriverStopped);
1281 ret = -1;
1282 goto exit;
1283 }
1284
1285 if (!padapter->bup) {
1286 ret = -1;
1287 goto exit;
1288 }
1289
c77761d6 1290 if (!padapter->hw_init_completed) {
554c0a3a
HG
1291 ret = -1;
1292 goto exit;
1293 }
1294
1295 /* When Busy Traffic, driver do not site survey. So driver return success. */
1296 /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1297 /* modify by thomas 2011-02-22. */
e2b13595 1298 if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
554c0a3a
HG
1299 indicate_wx_scan_complete_event(padapter);
1300 goto exit;
1301 }
1302
f85ac230 1303 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
554c0a3a
HG
1304 indicate_wx_scan_complete_event(padapter);
1305 goto exit;
1306 }
1307
1308 memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1309
f85ac230 1310 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
554c0a3a
HG
1311 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1312
f85ac230 1313 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
554c0a3a
HG
1314 int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1315
1316 memcpy(ssid[0].Ssid, req->essid, len);
1317 ssid[0].SsidLength = len;
1318
1319 DBG_871X("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1320
1321 spin_lock_bh(&pmlmepriv->lock);
1322
1323 _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1324
1325 spin_unlock_bh(&pmlmepriv->lock);
1326
f85ac230 1327 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
554c0a3a
HG
1328 DBG_871X("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1329 }
1330
f85ac230
TD
1331 } else if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
1332 && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
c77761d6 1333 int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
554c0a3a
HG
1334 char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1335 char section;
1336 char sec_len;
1337 int ssid_index = 0;
1338
1339 /* DBG_871X("%s COMBO_SCAN header is recognized\n", __func__); */
1340
1341 while (len >= 1) {
c77761d6 1342 section = *(pos++); len -= 1;
554c0a3a
HG
1343
1344 switch (section) {
1345 case WEXT_CSCAN_SSID_SECTION:
1346 /* DBG_871X("WEXT_CSCAN_SSID_SECTION\n"); */
1347 if (len < 1) {
1348 len = 0;
1349 break;
1350 }
1351
c77761d6 1352 sec_len = *(pos++); len -= 1;
554c0a3a 1353
c77761d6 1354 if (sec_len > 0 && sec_len <= len) {
554c0a3a
HG
1355 ssid[ssid_index].SsidLength = sec_len;
1356 memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1357 /* DBG_871X("%s COMBO_SCAN with specific ssid:%s, %d\n", __func__ */
1358 /* , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength); */
1359 ssid_index++;
1360 }
1361
c77761d6 1362 pos += sec_len; len -= sec_len;
554c0a3a
HG
1363 break;
1364
1365
1366 case WEXT_CSCAN_CHANNEL_SECTION:
1367 /* DBG_871X("WEXT_CSCAN_CHANNEL_SECTION\n"); */
c77761d6 1368 pos += 1; len -= 1;
554c0a3a
HG
1369 break;
1370 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1371 /* DBG_871X("WEXT_CSCAN_ACTV_DWELL_SECTION\n"); */
c77761d6 1372 pos += 2; len -= 2;
554c0a3a
HG
1373 break;
1374 case WEXT_CSCAN_PASV_DWELL_SECTION:
1375 /* DBG_871X("WEXT_CSCAN_PASV_DWELL_SECTION\n"); */
c77761d6 1376 pos += 2; len -= 2;
554c0a3a
HG
1377 break;
1378 case WEXT_CSCAN_HOME_DWELL_SECTION:
1379 /* DBG_871X("WEXT_CSCAN_HOME_DWELL_SECTION\n"); */
c77761d6 1380 pos += 2; len -= 2;
554c0a3a
HG
1381 break;
1382 case WEXT_CSCAN_TYPE_SECTION:
1383 /* DBG_871X("WEXT_CSCAN_TYPE_SECTION\n"); */
c77761d6 1384 pos += 1; len -= 1;
554c0a3a
HG
1385 break;
1386 default:
1387 /* DBG_871X("Unknown CSCAN section %c\n", section); */
1388 len = 0; /* stop parsing */
1389 }
1390 /* DBG_871X("len:%d\n", len); */
1391
1392 }
1393
8fd1e027 1394 /* jeff: it has still some scan parameter to parse, we only do this now... */
554c0a3a
HG
1395 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1396
f85ac230 1397 } else {
554c0a3a
HG
1398 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1399 }
1400
1401 if (_status == false)
1402 ret = -1;
1403
1404exit:
1405
1406 rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
1407
1408 #ifdef DBG_IOCTL
1409 DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
1410 #endif
1411
1412 return ret;
1413}
1414
1415static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1416 union iwreq_data *wrqu, char *extra)
1417{
1418 struct list_head *plist, *phead;
1419 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1420 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1421 struct __queue *queue = &(pmlmepriv->scanned_queue);
1422 struct wlan_network *pnetwork = NULL;
1423 char *ev = extra;
1424 char *stop = ev + wrqu->data.length;
1425 u32 ret = 0;
1426 sint wait_status;
1427
1428 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1429 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1430
1431 #ifdef DBG_IOCTL
1432 DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__);
1433 #endif
1434
f85ac230 1435 if (adapter_to_pwrctl(padapter)->brfoffbyhw && padapter->bDriverStopped) {
554c0a3a
HG
1436 ret = -EINVAL;
1437 goto exit;
1438 }
1439
1440 wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1441
1442 if (check_fwstate(pmlmepriv, wait_status))
1443 return -EAGAIN;
1444
1445 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1446
1447 phead = get_list_head(queue);
1448 plist = get_next(phead);
1449
f85ac230 1450 while (1) {
554c0a3a
HG
1451 if (phead == plist)
1452 break;
1453
1454 if ((stop - ev) < SCAN_ITEM_SIZE) {
1455 ret = -E2BIG;
1456 break;
1457 }
1458
1459 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1460
1461 /* report network only if the current channel set contains the channel to which this network belongs */
1462 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
1463 && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true
f85ac230
TD
1464 && true == rtw_validate_ssid(&(pnetwork->network.Ssid))) {
1465
c77761d6 1466 ev = translate_scan(padapter, a, pnetwork, ev, stop);
554c0a3a
HG
1467 }
1468
1469 plist = get_next(plist);
1470
1471 }
1472
1473 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1474
1475 wrqu->data.length = ev-extra;
1476 wrqu->data.flags = 0;
1477
1478exit:
1479
1480 #ifdef DBG_IOCTL
1481 DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
1482 #endif
1483
c77761d6 1484 return ret;
554c0a3a
HG
1485
1486}
1487
1488/* set ssid flow */
1489/* s1. rtw_set_802_11_infrastructure_mode() */
1490/* s2. set_802_11_authenticaion_mode() */
1491/* s3. set_802_11_encryption_mode() */
1492/* s4. rtw_set_802_11_ssid() */
1493static int rtw_wx_set_essid(struct net_device *dev,
1494 struct iw_request_info *a,
1495 union iwreq_data *wrqu, char *extra)
1496{
1497 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1498 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1499 struct __queue *queue = &pmlmepriv->scanned_queue;
1500 struct list_head *phead;
1501 struct wlan_network *pnetwork = NULL;
1502 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1503 struct ndis_802_11_ssid ndis_ssid;
1504 u8 *dst_ssid, *src_ssid;
1505
1506 uint ret = 0, len;
1507
1508 #ifdef DBG_IOCTL
1509 DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__);
1510 #endif
1511
1512 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1513 ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1514
1515 rtw_ps_deny(padapter, PS_DENY_JOIN);
f85ac230 1516 if (_FAIL == rtw_pwr_wakeup(padapter)) {
554c0a3a
HG
1517 ret = -1;
1518 goto exit;
1519 }
1520
1521 if (!padapter->bup) {
1522 ret = -1;
1523 goto exit;
1524 }
1525
1526 if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1527 ret = -E2BIG;
1528 goto exit;
1529 }
1530
1531 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1532 ret = -1;
1533 goto exit;
1534 }
1535
1536 authmode = padapter->securitypriv.ndisauthtype;
1537 DBG_871X("=>%s\n", __func__);
f85ac230 1538 if (wrqu->essid.flags && wrqu->essid.length) {
554c0a3a
HG
1539 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1540
1541 if (wrqu->essid.length != 33)
1542 DBG_871X("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1543
1544 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1545 ndis_ssid.SsidLength = len;
1546 memcpy(ndis_ssid.Ssid, extra, len);
1547 src_ssid = ndis_ssid.Ssid;
1548
1549 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1550 spin_lock_bh(&queue->lock);
1551 phead = get_list_head(queue);
1552 pmlmepriv->pscanned = get_next(phead);
1553
1554 while (1) {
f85ac230 1555 if (phead == pmlmepriv->pscanned) {
554c0a3a
HG
1556 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
1557 ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
1558
1559 break;
1560 }
1561
1562 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
1563
1564 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1565
1566 dst_ssid = pnetwork->network.Ssid.Ssid;
1567
1568 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1569 ("rtw_wx_set_essid: dst_ssid =%s\n",
1570 pnetwork->network.Ssid.Ssid));
1571
1572 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
c77761d6 1573 (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
554c0a3a
HG
1574 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1575 ("rtw_wx_set_essid: find match, set infra mode\n"));
1576
f85ac230 1577 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
554c0a3a
HG
1578 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1579 continue;
1580 }
1581
f85ac230 1582 if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == false) {
554c0a3a
HG
1583 ret = -1;
1584 spin_unlock_bh(&queue->lock);
1585 goto exit;
1586 }
1587
1588 break;
1589 }
1590 }
1591 spin_unlock_bh(&queue->lock);
1592 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1593 ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1594 rtw_set_802_11_authentication_mode(padapter, authmode);
1595 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1596 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1597 ret = -1;
1598 goto exit;
1599 }
1600 }
1601
1602exit:
1603
1604 rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1605
1606 DBG_871X("<=%s, ret %d\n", __func__, ret);
1607
1608 #ifdef DBG_IOCTL
1609 DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
1610 #endif
1611
1612 return ret;
1613}
1614
1615static int rtw_wx_get_essid(struct net_device *dev,
1616 struct iw_request_info *a,
1617 union iwreq_data *wrqu, char *extra)
1618{
1619 u32 len, ret = 0;
1620 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1621 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1622 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1623
1624 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1625
1626 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
f85ac230 1627 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
554c0a3a
HG
1628 len = pcur_bss->Ssid.SsidLength;
1629
1630 wrqu->essid.length = len;
1631
1632 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1633
1634 wrqu->essid.flags = 1;
f85ac230 1635 } else {
554c0a3a
HG
1636 ret = -1;
1637 goto exit;
1638 }
1639
1640exit:
1641 return ret;
1642}
1643
1644static int rtw_wx_set_rate(struct net_device *dev,
1645 struct iw_request_info *a,
1646 union iwreq_data *wrqu, char *extra)
1647{
1648 int i, ret = 0;
1649 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1650 u8 datarates[NumRates];
1651 u32 target_rate = wrqu->bitrate.value;
1652 u32 fixed = wrqu->bitrate.fixed;
1653 u32 ratevalue = 0;
c77761d6 1654 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
554c0a3a
HG
1655
1656 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1657 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1658
1659 if (target_rate == -1) {
1660 ratevalue = 11;
1661 goto set_rate;
1662 }
1663 target_rate = target_rate/100000;
1664
1665 switch (target_rate) {
2dd67029
PM
1666 case 10:
1667 ratevalue = 0;
1668 break;
1669 case 20:
1670 ratevalue = 1;
1671 break;
1672 case 55:
1673 ratevalue = 2;
1674 break;
1675 case 60:
1676 ratevalue = 3;
1677 break;
1678 case 90:
1679 ratevalue = 4;
1680 break;
1681 case 110:
1682 ratevalue = 5;
1683 break;
1684 case 120:
1685 ratevalue = 6;
1686 break;
1687 case 180:
1688 ratevalue = 7;
1689 break;
1690 case 240:
1691 ratevalue = 8;
1692 break;
1693 case 360:
1694 ratevalue = 9;
1695 break;
1696 case 480:
1697 ratevalue = 10;
1698 break;
1699 case 540:
1700 ratevalue = 11;
1701 break;
1702 default:
1703 ratevalue = 11;
1704 break;
554c0a3a
HG
1705 }
1706
1707set_rate:
1708
c77761d6
LS
1709 for (i = 0; i < NumRates; i++) {
1710 if (ratevalue == mpdatarate[i]) {
554c0a3a
HG
1711 datarates[i] = mpdatarate[i];
1712 if (fixed == 0)
1713 break;
f85ac230 1714 } else {
554c0a3a
HG
1715 datarates[i] = 0xff;
1716 }
1717
1718 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1719 }
1720
1721 if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
1722 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n"));
1723 ret = -1;
1724 }
1725 return ret;
1726}
1727
1728static int rtw_wx_get_rate(struct net_device *dev,
1729 struct iw_request_info *info,
1730 union iwreq_data *wrqu, char *extra)
1731{
1732 u16 max_rate = 0;
1733
1734 max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1735
1736 if (max_rate == 0)
1737 return -EPERM;
1738
1739 wrqu->bitrate.fixed = 0; /* no auto select */
1740 wrqu->bitrate.value = max_rate * 100000;
1741
1742 return 0;
1743}
1744
1745static int rtw_wx_set_rts(struct net_device *dev,
1746 struct iw_request_info *info,
1747 union iwreq_data *wrqu, char *extra)
1748{
1749 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1750
1751 if (wrqu->rts.disabled)
1752 padapter->registrypriv.rts_thresh = 2347;
1753 else {
1754 if (wrqu->rts.value < 0 ||
1755 wrqu->rts.value > 2347)
1756 return -EINVAL;
1757
1758 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1759 }
1760
1761 DBG_871X("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1762
1763 return 0;
1764}
1765
1766static int rtw_wx_get_rts(struct net_device *dev,
1767 struct iw_request_info *info,
1768 union iwreq_data *wrqu, char *extra)
1769{
1770 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1771
1772 DBG_871X("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1773
1774 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1775 wrqu->rts.fixed = 0; /* no auto select */
1776 /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1777
1778 return 0;
1779}
1780
1781static int rtw_wx_set_frag(struct net_device *dev,
1782 struct iw_request_info *info,
1783 union iwreq_data *wrqu, char *extra)
1784{
1785 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1786
1787 if (wrqu->frag.disabled)
1788 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1789 else {
1790 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1791 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1792 return -EINVAL;
1793
1794 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1795 }
1796
1797 DBG_871X("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1798
1799 return 0;
1800
1801}
1802
1803static int rtw_wx_get_frag(struct net_device *dev,
1804 struct iw_request_info *info,
1805 union iwreq_data *wrqu, char *extra)
1806{
1807 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1808
1809 DBG_871X("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1810
1811 wrqu->frag.value = padapter->xmitpriv.frag_len;
1812 wrqu->frag.fixed = 0; /* no auto select */
1813 /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
1814
1815 return 0;
1816}
1817
1818static int rtw_wx_get_retry(struct net_device *dev,
1819 struct iw_request_info *info,
1820 union iwreq_data *wrqu, char *extra)
1821{
1822 /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
1823
1824
1825 wrqu->retry.value = 7;
1826 wrqu->retry.fixed = 0; /* no auto select */
1827 wrqu->retry.disabled = 1;
1828
1829 return 0;
1830
1831}
1832
1833static int rtw_wx_set_enc(struct net_device *dev,
1834 struct iw_request_info *info,
1835 union iwreq_data *wrqu, char *keybuf)
1836{
1837 u32 key, ret = 0;
1838 u32 keyindex_provided;
1839 struct ndis_802_11_wep wep;
1840 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1841
1842 struct iw_point *erq = &(wrqu->encoding);
1843 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1844 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1845 DBG_871X("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1846
1847 memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1848
1849 key = erq->flags & IW_ENCODE_INDEX;
1850
f85ac230 1851 if (erq->flags & IW_ENCODE_DISABLED) {
554c0a3a
HG
1852 DBG_871X("EncryptionDisabled\n");
1853 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1854 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1855 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1856 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1857 authmode = Ndis802_11AuthModeOpen;
c77761d6 1858 padapter->securitypriv.ndisauthtype = authmode;
554c0a3a
HG
1859
1860 goto exit;
1861 }
1862
1863 if (key) {
1864 if (key > WEP_KEYS)
1865 return -EINVAL;
1866 key--;
1867 keyindex_provided = 1;
f85ac230 1868 } else {
554c0a3a
HG
1869 keyindex_provided = 0;
1870 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1871 DBG_871X("rtw_wx_set_enc, key =%d\n", key);
1872 }
1873
1874 /* set authentication mode */
f85ac230 1875 if (erq->flags & IW_ENCODE_OPEN) {
554c0a3a
HG
1876 DBG_871X("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1877 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1878
1879 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1880
1881 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1882 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1883 authmode = Ndis802_11AuthModeOpen;
c77761d6 1884 padapter->securitypriv.ndisauthtype = authmode;
f85ac230 1885 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
554c0a3a
HG
1886 DBG_871X("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1887 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1888
1889 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1890
1891 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1892 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1893 authmode = Ndis802_11AuthModeShared;
c77761d6 1894 padapter->securitypriv.ndisauthtype = authmode;
f85ac230 1895 } else {
554c0a3a
HG
1896 DBG_871X("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1897
1898 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1899 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1900 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1901 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1902 authmode = Ndis802_11AuthModeOpen;
c77761d6 1903 padapter->securitypriv.ndisauthtype = authmode;
554c0a3a
HG
1904 }
1905
1906 wep.KeyIndex = key;
f85ac230 1907 if (erq->length > 0) {
554c0a3a
HG
1908 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1909
1910 wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
f85ac230 1911 } else {
c77761d6 1912 wep.KeyLength = 0;
554c0a3a 1913
f85ac230 1914 if (keyindex_provided == 1) { /* set key_id only, no given KeyMaterial(erq->length == 0). */
554c0a3a
HG
1915 padapter->securitypriv.dot11PrivacyKeyIndex = key;
1916
1917 DBG_871X("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1918
f85ac230 1919 switch (padapter->securitypriv.dot11DefKeylen[key]) {
554c0a3a
HG
1920 case 5:
1921 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1922 break;
1923 case 13:
1924 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1925 break;
1926 default:
1927 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1928 break;
1929 }
1930
1931 goto exit;
1932
1933 }
1934
1935 }
1936
1937 wep.KeyIndex |= 0x80000000;
1938
1939 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1940
1941 if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1942 if (rf_on == pwrpriv->rf_pwrstate)
1943 ret = -EOPNOTSUPP;
1944 goto exit;
1945 }
1946
1947exit:
1948 return ret;
1949}
1950
1951static int rtw_wx_get_enc(struct net_device *dev,
1952 struct iw_request_info *info,
1953 union iwreq_data *wrqu, char *keybuf)
1954{
1955 uint key, ret = 0;
1956 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1957 struct iw_point *erq = &(wrqu->encoding);
1958 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1959
f85ac230
TD
1960 if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1961 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true) {
1962 erq->length = 0;
1963 erq->flags |= IW_ENCODE_DISABLED;
1964 return 0;
1965 }
554c0a3a
HG
1966 }
1967
1968
1969 key = erq->flags & IW_ENCODE_INDEX;
1970
1971 if (key) {
1972 if (key > WEP_KEYS)
1973 return -EINVAL;
1974 key--;
f85ac230 1975 } else {
554c0a3a
HG
1976 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1977 }
1978
1979 erq->flags = key + 1;
1980
1981 /* if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
1982 /* */
1983 /* erq->flags |= IW_ENCODE_OPEN; */
1984 /* */
1985
f85ac230 1986 switch (padapter->securitypriv.ndisencryptstatus) {
554c0a3a
HG
1987 case Ndis802_11EncryptionNotSupported:
1988 case Ndis802_11EncryptionDisabled:
1989 erq->length = 0;
1990 erq->flags |= IW_ENCODE_DISABLED;
1991 break;
1992 case Ndis802_11Encryption1Enabled:
1993 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1994
f85ac230 1995 if (erq->length) {
554c0a3a
HG
1996 memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1997
1998 erq->flags |= IW_ENCODE_ENABLED;
1999
2000 if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
554c0a3a 2001 erq->flags |= IW_ENCODE_OPEN;
554c0a3a 2002 else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
f85ac230
TD
2003 erq->flags |= IW_ENCODE_RESTRICTED;
2004 } else {
554c0a3a
HG
2005 erq->length = 0;
2006 erq->flags |= IW_ENCODE_DISABLED;
2007 }
2008 break;
2009 case Ndis802_11Encryption2Enabled:
2010 case Ndis802_11Encryption3Enabled:
2011 erq->length = 16;
2012 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
2013 break;
2014 default:
2015 erq->length = 0;
2016 erq->flags |= IW_ENCODE_DISABLED;
2017 break;
2018 }
2019 return ret;
2020}
2021
2022static int rtw_wx_get_power(struct net_device *dev,
2023 struct iw_request_info *info,
2024 union iwreq_data *wrqu, char *extra)
2025{
2026 /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
2027
2028 wrqu->power.value = 0;
2029 wrqu->power.fixed = 0; /* no auto select */
2030 wrqu->power.disabled = 1;
2031
2032 return 0;
2033}
2034
2035static int rtw_wx_set_gen_ie(struct net_device *dev,
2036 struct iw_request_info *info,
2037 union iwreq_data *wrqu, char *extra)
2038{
554c0a3a
HG
2039 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2040
dedc1a73 2041 return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
554c0a3a
HG
2042}
2043
2044static int rtw_wx_set_auth(struct net_device *dev,
79652e2c
QK
2045 struct iw_request_info *info,
2046 union iwreq_data *wrqu, char *extra)
554c0a3a
HG
2047{
2048 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
a7dd567e 2049 struct iw_param *param = (struct iw_param *)&(wrqu->param);
554c0a3a
HG
2050 int ret = 0;
2051
2052 switch (param->flags & IW_AUTH_INDEX) {
554c0a3a
HG
2053 case IW_AUTH_WPA_VERSION:
2054 break;
2055 case IW_AUTH_CIPHER_PAIRWISE:
554c0a3a
HG
2056 break;
2057 case IW_AUTH_CIPHER_GROUP:
554c0a3a
HG
2058 break;
2059 case IW_AUTH_KEY_MGMT:
2060 /*
2061 * ??? does not use these parameters
2062 */
2063 break;
554c0a3a 2064 case IW_AUTH_TKIP_COUNTERMEASURES:
86c0205b
QK
2065 /* wpa_supplicant is setting the tkip countermeasure. */
2066 if (param->value) /* enabling */
f85ac230 2067 padapter->securitypriv.btkip_countermeasure = true;
86c0205b 2068 else /* disabling */
f85ac230 2069 padapter->securitypriv.btkip_countermeasure = false;
554c0a3a 2070 break;
554c0a3a 2071 case IW_AUTH_DROP_UNENCRYPTED:
41ed8df9
QK
2072 /* HACK:
2073 *
2074 * wpa_supplicant calls set_wpa_enabled when the driver
2075 * is loaded and unloaded, regardless of if WPA is being
2076 * used. No other calls are made which can be used to
2077 * determine if encryption will be used or not prior to
2078 * association being expected. If encryption is not being
2079 * used, drop_unencrypted is set to false, else true -- we
2080 * can use this to determine if the CAP_PRIVACY_ON bit should
2081 * be set.
2082 */
554c0a3a 2083
86c0205b
QK
2084 /*
2085 * This means init value, or using wep, ndisencryptstatus =
2086 * Ndis802_11Encryption1Enabled, then it needn't reset it;
2087 */
2088 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
2089 break;
554c0a3a 2090
41ed8df9
QK
2091 if (param->value) {
2092 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2093 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2094 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2095 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
c77761d6 2096 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
554c0a3a 2097 }
41ed8df9
QK
2098
2099 break;
554c0a3a 2100 case IW_AUTH_80211_AUTH_ALG:
554c0a3a
HG
2101 /*
2102 * It's the starting point of a link layer connection using wpa_supplicant
79652e2c 2103 */
554c0a3a
HG
2104 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2105 LeaveAllPowerSaveMode(padapter);
2106 rtw_disassoc_cmd(padapter, 500, false);
2107 DBG_871X("%s...call rtw_indicate_disconnect\n ", __func__);
2108 rtw_indicate_disconnect(padapter);
2109 rtw_free_assoc_resources(padapter, 1);
2110 }
2111
554c0a3a 2112 ret = wpa_set_auth_algs(dev, (u32)param->value);
554c0a3a 2113 break;
554c0a3a
HG
2114 case IW_AUTH_WPA_ENABLED:
2115 break;
2116 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2117 break;
2118 case IW_AUTH_PRIVACY_INVOKED:
2119 break;
2120 default:
2121 return -EOPNOTSUPP;
2122 }
5933a3c3 2123
554c0a3a
HG
2124 return ret;
2125}
2126
2127static int rtw_wx_set_enc_ext(struct net_device *dev,
2128 struct iw_request_info *info,
2129 union iwreq_data *wrqu, char *extra)
2130{
2131 char *alg_name;
2132 u32 param_len;
2133 struct ieee_param *param = NULL;
2134 struct iw_point *pencoding = &wrqu->encoding;
2135 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
2136 int ret = 0;
2137
2138 param_len = sizeof(struct ieee_param) + pext->key_len;
6254acde 2139 param = kzalloc(param_len, GFP_KERNEL);
554c0a3a
HG
2140 if (param == NULL)
2141 return -1;
2142
554c0a3a
HG
2143 param->cmd = IEEE_CMD_SET_ENCRYPTION;
2144 memset(param->sta_addr, 0xff, ETH_ALEN);
2145
2146
2147 switch (pext->alg) {
2148 case IW_ENCODE_ALG_NONE:
2149 /* todo: remove key */
2150 /* remove = 1; */
2151 alg_name = "none";
2152 break;
2153 case IW_ENCODE_ALG_WEP:
2154 alg_name = "WEP";
2155 break;
2156 case IW_ENCODE_ALG_TKIP:
2157 alg_name = "TKIP";
2158 break;
2159 case IW_ENCODE_ALG_CCMP:
2160 alg_name = "CCMP";
2161 break;
2162 case IW_ENCODE_ALG_AES_CMAC:
2163 alg_name = "BIP";
2164 break;
2165 default:
2166 ret = -1;
2167 goto exit;
2168 }
2169
2170 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2171
2172 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
554c0a3a 2173 param->u.crypt.set_tx = 1;
554c0a3a
HG
2174
2175 /* cliW: WEP does not have group key
2176 * just not checking GROUP key setting
2177 */
2178 if ((pext->alg != IW_ENCODE_ALG_WEP) &&
2179 ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
f85ac230 2180 || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC))) {
554c0a3a
HG
2181 param->u.crypt.set_tx = 0;
2182 }
2183
c77761d6 2184 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
554c0a3a
HG
2185
2186 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
554c0a3a 2187 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
554c0a3a 2188
f85ac230 2189 if (pext->key_len) {
554c0a3a
HG
2190 param->u.crypt.key_len = pext->key_len;
2191 /* memcpy(param + 1, pext + 1, pext->key_len); */
2192 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
2193 }
2194
f85ac230 2195 if (pencoding->flags & IW_ENCODE_DISABLED) {
554c0a3a
HG
2196 /* todo: remove key */
2197 /* remove = 1; */
2198 }
2199
2200 ret = wpa_set_encryption(dev, param, param_len);
2201
2202exit:
428715ba 2203 kfree(param);
554c0a3a
HG
2204
2205 return ret;
2206}
2207
2208
2209static int rtw_wx_get_nick(struct net_device *dev,
2210 struct iw_request_info *info,
2211 union iwreq_data *wrqu, char *extra)
2212{
2213 /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
2214 /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
2215 /* struct security_priv *psecuritypriv = &padapter->securitypriv; */
2216
f85ac230 2217 if (extra) {
554c0a3a
HG
2218 wrqu->data.length = 14;
2219 wrqu->data.flags = 1;
2220 memcpy(extra, "<WIFI@REALTEK>", 14);
2221 }
2222 return 0;
2223}
2224
2225static int rtw_wx_read32(struct net_device *dev,
2226 struct iw_request_info *info,
2227 union iwreq_data *wrqu, char *extra)
2228{
2229 struct adapter *padapter;
2230 struct iw_point *p;
2231 u16 len;
2232 u32 addr;
2233 u32 data32;
2234 u32 bytes;
2235 u8 *ptmp;
2236 int ret;
2237
2238
2239 ret = 0;
2240 padapter = (struct adapter *)rtw_netdev_priv(dev);
2241 p = &wrqu->data;
2242 len = p->length;
2243 if (0 == len)
2244 return -EINVAL;
2245
2ef2b7c2 2246 ptmp = rtw_malloc(len);
554c0a3a
HG
2247 if (NULL == ptmp)
2248 return -ENOMEM;
2249
2250 if (copy_from_user(ptmp, p->pointer, len)) {
2251 ret = -EFAULT;
2252 goto exit;
2253 }
2254
2255 bytes = 0;
2256 addr = 0;
2257 sscanf(ptmp, "%d,%x", &bytes, &addr);
2258
2259 switch (bytes) {
2dd67029
PM
2260 case 1:
2261 data32 = rtw_read8(padapter, addr);
2262 sprintf(extra, "0x%02X", data32);
2263 break;
2264 case 2:
2265 data32 = rtw_read16(padapter, addr);
2266 sprintf(extra, "0x%04X", data32);
2267 break;
2268 case 4:
2269 data32 = rtw_read32(padapter, addr);
2270 sprintf(extra, "0x%08X", data32);
2271 break;
2272 default:
2273 DBG_871X(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
2274 ret = -EINVAL;
2275 goto exit;
554c0a3a
HG
2276 }
2277 DBG_871X(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
2278
2279exit:
2280 kfree(ptmp);
2281
c3e43d8b 2282 return ret;
554c0a3a
HG
2283}
2284
2285static int rtw_wx_write32(struct net_device *dev,
2286 struct iw_request_info *info,
2287 union iwreq_data *wrqu, char *extra)
2288{
2289 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2290
2291 u32 addr;
2292 u32 data32;
2293 u32 bytes;
2294
2295
2296 bytes = 0;
2297 addr = 0;
2298 data32 = 0;
2299 sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
2300
2301 switch (bytes) {
2dd67029
PM
2302 case 1:
2303 rtw_write8(padapter, addr, (u8)data32);
2304 DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
2305 break;
2306 case 2:
2307 rtw_write16(padapter, addr, (u16)data32);
2308 DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
2309 break;
2310 case 4:
2311 rtw_write32(padapter, addr, data32);
2312 DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
2313 break;
2314 default:
2315 DBG_871X(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
2316 return -EINVAL;
554c0a3a
HG
2317 }
2318
2319 return 0;
2320}
2321
2322static int rtw_wx_read_rf(struct net_device *dev,
2323 struct iw_request_info *info,
2324 union iwreq_data *wrqu, char *extra)
2325{
2326 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2327 u32 path, addr, data32;
2328
2329
a7dd567e
SK
2330 path = *(u32 *)extra;
2331 addr = *((u32 *)extra + 1);
554c0a3a
HG
2332 data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
2333 /*
2334 * IMPORTANT!!
2335 * Only when wireless private ioctl is at odd order,
2336 * "extra" would be copied to user space.
2337 */
2338 sprintf(extra, "0x%05x", data32);
2339
2340 return 0;
2341}
2342
2343static int rtw_wx_write_rf(struct net_device *dev,
2344 struct iw_request_info *info,
2345 union iwreq_data *wrqu, char *extra)
2346{
2347 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2348 u32 path, addr, data32;
2349
2350
a7dd567e
SK
2351 path = *(u32 *)extra;
2352 addr = *((u32 *)extra + 1);
2353 data32 = *((u32 *)extra + 2);
554c0a3a
HG
2354/* DBG_871X("%s: path =%d addr = 0x%02x data = 0x%05x\n", __func__, path, addr, data32); */
2355 rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
2356
2357 return 0;
2358}
2359
2360static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
2361 union iwreq_data *wrqu, char *b)
2362{
2363 return -1;
2364}
2365
2366static int dummy(struct net_device *dev, struct iw_request_info *a,
2367 union iwreq_data *wrqu, char *b)
2368{
2369 /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
2370 /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
2371
2372 /* DBG_871X("cmd_code =%x, fwstate = 0x%x\n", a->cmd, get_fwstate(pmlmepriv)); */
2373
2374 return -1;
2375
2376}
2377
2378static int rtw_wx_set_channel_plan(struct net_device *dev,
2379 struct iw_request_info *info,
2380 union iwreq_data *wrqu, char *extra)
2381{
2382 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
54da60be 2383 u8 channel_plan_req = (u8)(*((int *)wrqu));
554c0a3a 2384
f85ac230 2385 if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1, 1))
554c0a3a 2386 DBG_871X("%s set channel_plan = 0x%02X\n", __func__, channel_plan_req);
f85ac230 2387 else
554c0a3a
HG
2388 return -EPERM;
2389
2390 return 0;
2391}
2392
2393static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
2394 struct iw_request_info *a,
2395 union iwreq_data *wrqu, char *b)
2396{
2397 return 0;
2398}
2399
2400static int rtw_wx_get_sensitivity(struct net_device *dev,
2401 struct iw_request_info *info,
2402 union iwreq_data *wrqu, char *buf)
2403{
2404 return 0;
2405}
2406
2407static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
2408 struct iw_request_info *info,
2409 union iwreq_data *wrqu, char *extra)
2410{
2411 return 0;
2412}
2413
2414/*
2415typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
2416 union iwreq_data *wrqu, char *extra);
2417*/
2418/*
2419 *For all data larger than 16 octets, we need to use a
2420 *pointer to memory allocated in user space.
2421 */
2422static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
2423 union iwreq_data *wrqu, char *extra)
2424{
2425 return 0;
2426}
2427
554c0a3a
HG
2428static int rtw_get_ap_info(struct net_device *dev,
2429 struct iw_request_info *info,
2430 union iwreq_data *wrqu, char *extra)
2431{
2432 int ret = 0;
c9ca79b3
JA
2433 int wpa_ielen;
2434 u32 cnt = 0;
554c0a3a
HG
2435 struct list_head *plist, *phead;
2436 unsigned char *pbuf;
2437 u8 bssid[ETH_ALEN];
2438 char data[32];
2439 struct wlan_network *pnetwork = NULL;
2440 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2441 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2442 struct __queue *queue = &(pmlmepriv->scanned_queue);
2443 struct iw_point *pdata = &wrqu->data;
2444
2445 DBG_871X("+rtw_get_aplist_info\n");
2446
f85ac230 2447 if ((padapter->bDriverStopped) || (pdata == NULL)) {
554c0a3a
HG
2448 ret = -EINVAL;
2449 goto exit;
2450 }
2451
f85ac230 2452 while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == true) {
554c0a3a
HG
2453 msleep(30);
2454 cnt++;
2455 if (cnt > 100)
2456 break;
2457 }
2458
2459
2460 /* pdata->length = 0;? */
2461 pdata->flags = 0;
c77761d6 2462 if (pdata->length >= 32) {
f85ac230 2463 if (copy_from_user(data, pdata->pointer, 32)) {
554c0a3a
HG
2464 ret = -EINVAL;
2465 goto exit;
2466 }
f85ac230 2467 } else {
554c0a3a
HG
2468 ret = -EINVAL;
2469 goto exit;
2470 }
2471
2472 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2473
2474 phead = get_list_head(queue);
2475 plist = get_next(phead);
2476
f85ac230 2477 while (1) {
554c0a3a
HG
2478 if (phead == plist)
2479 break;
2480
2481
2482 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2483
1cb5c559 2484 if (!mac_pton(data, bssid)) {
554c0a3a
HG
2485 DBG_871X("Invalid BSSID '%s'.\n", (u8 *)data);
2486 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2487 return -EINVAL;
2488 }
2489
2490
f85ac230 2491 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) { /* BSSID match, then check if supporting wpa/wpa2 */
554c0a3a
HG
2492 DBG_871X("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
2493
2494 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
c77761d6 2495 if (pbuf && (wpa_ielen > 0)) {
554c0a3a
HG
2496 pdata->flags = 1;
2497 break;
2498 }
2499
2500 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
c77761d6 2501 if (pbuf && (wpa_ielen > 0)) {
554c0a3a
HG
2502 pdata->flags = 2;
2503 break;
2504 }
554c0a3a
HG
2505 }
2506
2507 plist = get_next(plist);
2508
2509 }
2510
2511 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2512
c77761d6 2513 if (pdata->length >= 34) {
f85ac230 2514 if (copy_to_user((u8 __force __user *)pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
554c0a3a
HG
2515 ret = -EINVAL;
2516 goto exit;
2517 }
2518 }
2519
2520exit:
2521
2522 return ret;
2523
2524}
2525
2526static int rtw_set_pid(struct net_device *dev,
2527 struct iw_request_info *info,
2528 union iwreq_data *wrqu, char *extra)
2529{
2530
2531 int ret = 0;
2532 struct adapter *padapter = rtw_netdev_priv(dev);
2533 int *pdata = (int *)wrqu;
2534 int selector;
2535
f85ac230 2536 if ((padapter->bDriverStopped) || (pdata == NULL)) {
554c0a3a
HG
2537 ret = -EINVAL;
2538 goto exit;
2539 }
2540
2541 selector = *pdata;
2542 if (selector < 3 && selector >= 0) {
2543 padapter->pid[selector] = *(pdata+1);
c77761d6 2544 DBG_871X("%s set pid[%d]=%d\n", __func__, selector, padapter->pid[selector]);
554c0a3a
HG
2545 }
2546 else
2547 DBG_871X("%s selector %d error\n", __func__, selector);
2548
2549exit:
2550
2551 return ret;
2552
2553}
2554
2555static int rtw_wps_start(struct net_device *dev,
2556 struct iw_request_info *info,
2557 union iwreq_data *wrqu, char *extra)
2558{
2559
2560 int ret = 0;
2561 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2562 struct iw_point *pdata = &wrqu->data;
2563 u32 u32wps_start = 0;
2564 unsigned int uintRet = 0;
2565
c77761d6 2566 if ((true == padapter->bDriverStopped) || (true == padapter->bSurpriseRemoved) || (NULL == pdata)) {
554c0a3a
HG
2567 ret = -EINVAL;
2568 goto exit;
2569 }
2570
a7dd567e 2571 uintRet = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
554c0a3a 2572 if (u32wps_start == 0)
554c0a3a 2573 u32wps_start = *extra;
554c0a3a
HG
2574
2575 DBG_871X("[%s] wps_start = %d\n", __func__, u32wps_start);
2576
554c0a3a
HG
2577exit:
2578
2579 return ret;
2580
2581}
2582
2583static int rtw_p2p_set(struct net_device *dev,
2584 struct iw_request_info *info,
2585 union iwreq_data *wrqu, char *extra)
2586{
2587
8915d989 2588 return 0;
554c0a3a
HG
2589
2590}
2591
2592static int rtw_p2p_get(struct net_device *dev,
2593 struct iw_request_info *info,
2594 union iwreq_data *wrqu, char *extra)
2595{
2596
8915d989 2597 return 0;
554c0a3a
HG
2598
2599}
2600
2601static int rtw_p2p_get2(struct net_device *dev,
2602 struct iw_request_info *info,
2603 union iwreq_data *wrqu, char *extra)
2604{
2605
8915d989 2606 return 0;
554c0a3a
HG
2607
2608}
2609
2610static int rtw_rereg_nd_name(struct net_device *dev,
2611 struct iw_request_info *info,
2612 union iwreq_data *wrqu, char *extra)
2613{
2614 int ret = 0;
2615 struct adapter *padapter = rtw_netdev_priv(dev);
2616 struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
2617 char new_ifname[IFNAMSIZ];
2618
2619 if (rereg_priv->old_ifname[0] == 0) {
2620 char *reg_ifname;
2621 reg_ifname = padapter->registrypriv.ifname;
2622
2623 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
2624 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
2625 }
2626
2627 /* DBG_871X("%s wrqu->data.length:%d\n", __func__, wrqu->data.length); */
2628 if (wrqu->data.length > IFNAMSIZ)
2629 return -EFAULT;
2630
f85ac230 2631 if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
554c0a3a 2632 return -EFAULT;
554c0a3a 2633
f85ac230 2634 if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
554c0a3a 2635 return ret;
554c0a3a
HG
2636
2637 DBG_871X("%s new_ifname:%s\n", __func__, new_ifname);
f85ac230 2638 if (0 != (ret = rtw_change_ifname(padapter, new_ifname)))
554c0a3a 2639 goto exit;
554c0a3a
HG
2640
2641 strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
2642 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
2643
2644 if (!memcmp(new_ifname, "disable%d", 9)) {
2645
2646 DBG_871X("%s disable\n", __func__);
2647 /* free network queue for Android's timming issue */
2648 rtw_free_network_queue(padapter, true);
2649
2650 /* the interface is being "disabled", we can do deeper IPS */
2651 /* rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); */
2652 /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
2653 }
2654exit:
2655 return ret;
2656
2657}
2658
2659static int rtw_dbg_port(struct net_device *dev,
2660 struct iw_request_info *info,
2661 union iwreq_data *wrqu, char *extra)
2662{
554c0a3a
HG
2663 u8 major_cmd, minor_cmd;
2664 u16 arg;
2665 u32 extra_arg, *pdata, val32;
2666 struct sta_info *psta;
2667 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2668 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2669 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2670 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2671 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
2672 struct sta_priv *pstapriv = &padapter->stapriv;
2673
2674
a7dd567e 2675 pdata = (u32 *)&wrqu->data;
554c0a3a
HG
2676
2677 val32 = *pdata;
2678 arg = (u16)(val32&0x0000ffff);
2679 major_cmd = (u8)(val32>>24);
2680 minor_cmd = (u8)((val32>>16)&0x00ff);
2681
2682 extra_arg = *(pdata+1);
2683
f85ac230 2684 switch (major_cmd) {
554c0a3a 2685 case 0x70:/* read_reg */
f85ac230 2686 switch (minor_cmd) {
554c0a3a
HG
2687 case 1:
2688 DBG_871X("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
2689 break;
2690 case 2:
2691 DBG_871X("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
2692 break;
2693 case 4:
2694 DBG_871X("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
2695 break;
2696 }
2697 break;
2698 case 0x71:/* write_reg */
f85ac230 2699 switch (minor_cmd) {
554c0a3a
HG
2700 case 1:
2701 rtw_write8(padapter, arg, extra_arg);
2702 DBG_871X("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
2703 break;
2704 case 2:
2705 rtw_write16(padapter, arg, extra_arg);
2706 DBG_871X("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
2707 break;
2708 case 4:
2709 rtw_write32(padapter, arg, extra_arg);
2710 DBG_871X("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
2711 break;
2712 }
2713 break;
2714 case 0x72:/* read_bb */
2715 DBG_871X("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
2716 break;
2717 case 0x73:/* write_bb */
2718 rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
2719 DBG_871X("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
2720 break;
2721 case 0x74:/* read_rf */
2722 DBG_871X("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));
2723 break;
2724 case 0x75:/* write_rf */
2725 rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
2726 DBG_871X("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));
2727 break;
2728
2729 case 0x76:
f85ac230 2730 switch (minor_cmd) {
554c0a3a
HG
2731 case 0x00: /* normal mode, */
2732 padapter->recvpriv.is_signal_dbg = 0;
2733 break;
2734 case 0x01: /* dbg mode */
2735 padapter->recvpriv.is_signal_dbg = 1;
c77761d6
LS
2736 extra_arg = extra_arg > 100 ? 100 : extra_arg;
2737 padapter->recvpriv.signal_strength_dbg = extra_arg;
554c0a3a
HG
2738 break;
2739 }
2740 break;
2741 case 0x78: /* IOL test */
2742 break;
2743 case 0x79:
2744 {
2745 /*
2746 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
2747 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
2748 */
2749 u8 value = extra_arg & 0x0f;
2750 u8 sign = minor_cmd;
2751 u16 write_value = 0;
2752
2753 DBG_871X("%s set RESP_TXAGC to %s %u\n", __func__, sign?"minus":"plus", value);
2754
2755 if (sign)
2756 value = value | 0x10;
2757
2758 write_value = value | (value << 5);
2759 rtw_write16(padapter, 0x6d9, write_value);
2760 }
2761 break;
2762 case 0x7a:
2763 receive_disconnect(padapter, pmlmeinfo->network.MacAddress
2764 , WLAN_REASON_EXPIRATION_CHK);
2765 break;
2766 case 0x7F:
f85ac230 2767 switch (minor_cmd) {
554c0a3a
HG
2768 case 0x0:
2769 DBG_871X("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
2770 break;
2771 case 0x01:
2772 DBG_871X("minor_cmd 0x%x\n", minor_cmd);
2773 break;
2774 case 0x02:
2775 DBG_871X("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
2776 DBG_871X("DrvBcnEarly =%d\n", pmlmeext->DrvBcnEarly);
2777 DBG_871X("DrvBcnTimeOut =%d\n", pmlmeext->DrvBcnTimeOut);
2778 break;
2779 case 0x03:
2780 DBG_871X("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
2781 DBG_871X("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
2782 break;
2783 case 0x04:
2784 DBG_871X("cur_ch =%d\n", pmlmeext->cur_channel);
2785 DBG_871X("cur_bw =%d\n", pmlmeext->cur_bwmode);
2786 DBG_871X("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
2787
2788 DBG_871X("oper_ch =%d\n", rtw_get_oper_ch(padapter));
2789 DBG_871X("oper_bw =%d\n", rtw_get_oper_bw(padapter));
6f406c73 2790 DBG_871X("oper_ch_offset =%d\n", rtw_get_oper_choffset(padapter));
554c0a3a
HG
2791
2792 break;
2793 case 0x05:
2794 psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
f85ac230 2795 if (psta) {
554c0a3a
HG
2796 int i;
2797 struct recv_reorder_ctrl *preorder_ctrl;
2798
2799 DBG_871X("SSID =%s\n", cur_network->network.Ssid.Ssid);
2800 DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
2801 DBG_871X("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
2802 DBG_871X("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
2803 DBG_871X("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
2804 DBG_871X("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
2805 DBG_871X("bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
2806 DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
2807 DBG_871X("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
2808
c77761d6 2809 for (i = 0; i < 16; i++) {
554c0a3a
HG
2810 preorder_ctrl = &psta->recvreorder_ctrl[i];
2811 if (preorder_ctrl->enable)
554c0a3a 2812 DBG_871X("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
554c0a3a
HG
2813 }
2814
f85ac230 2815 } else {
554c0a3a
HG
2816 DBG_871X("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
2817 }
2818 break;
2819 case 0x06:
2820 {
2821 u32 ODMFlag;
2822 rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
2823 DBG_871X("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
2824 ODMFlag = (u32)(0x0f&arg);
2825 DBG_871X("(A)DMFlag = 0x%x\n", ODMFlag);
2826 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
2827 }
2828 break;
2829 case 0x07:
2830 DBG_871X("bSurpriseRemoved =%d, bDriverStopped =%d\n",
2831 padapter->bSurpriseRemoved, padapter->bDriverStopped);
2832 break;
2833 case 0x08:
2834 {
2835 DBG_871X("minor_cmd 0x%x\n", minor_cmd);
2836 }
2837 break;
2838 case 0x09:
2839 {
2840 int i, j;
2841 struct list_head *plist, *phead;
2842 struct recv_reorder_ctrl *preorder_ctrl;
2843
2844 DBG_871X("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
2845
2846 spin_lock_bh(&pstapriv->sta_hash_lock);
2847
c77761d6 2848 for (i = 0; i < NUM_STA; i++) {
554c0a3a
HG
2849 phead = &(pstapriv->sta_hash[i]);
2850 plist = get_next(phead);
2851
f85ac230 2852 while (phead != plist) {
554c0a3a
HG
2853 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
2854
2855 plist = get_next(plist);
2856
f85ac230 2857 if (extra_arg == psta->aid) {
554c0a3a
HG
2858 DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
2859 DBG_871X("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
2860 DBG_871X("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
2861 DBG_871X("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
2862 DBG_871X("bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
2863 DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
2864 DBG_871X("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
2865 DBG_871X("capability = 0x%x\n", psta->capability);
2866 DBG_871X("flags = 0x%x\n", psta->flags);
2867 DBG_871X("wpa_psk = 0x%x\n", psta->wpa_psk);
2868 DBG_871X("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
2869 DBG_871X("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
2870 DBG_871X("qos_info = 0x%x\n", psta->qos_info);
2871 DBG_871X("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
2872
2873
2874
c77761d6 2875 for (j = 0; j < 16; j++) {
554c0a3a
HG
2876 preorder_ctrl = &psta->recvreorder_ctrl[j];
2877 if (preorder_ctrl->enable)
554c0a3a 2878 DBG_871X("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
554c0a3a 2879 }
554c0a3a 2880 }
554c0a3a
HG
2881 }
2882 }
2883
2884 spin_unlock_bh(&pstapriv->sta_hash_lock);
2885
2886 }
2887 break;
2888 case 0x0a:
2889 {
2890 int max_mac_id = 0;
2891 max_mac_id = rtw_search_max_mac_id(padapter);
2892 printk("%s ==> max_mac_id = %d\n", __func__, max_mac_id);
2893 }
2894 break;
2895 case 0x0b: /* Enable = 1, Disable = 0 driver control vrtl_carrier_sense. */
2896 if (arg == 0) {
2897 DBG_871X("disable driver ctrl vcs\n");
2898 padapter->driver_vcs_en = 0;
f85ac230 2899 } else if (arg == 1) {
554c0a3a
HG
2900 DBG_871X("enable driver ctrl vcs = %d\n", extra_arg);
2901 padapter->driver_vcs_en = 1;
2902
c77761d6 2903 if (extra_arg > 2)
554c0a3a
HG
2904 padapter->driver_vcs_type = 1;
2905 else
2906 padapter->driver_vcs_type = extra_arg;
2907 }
2908 break;
2909 case 0x0c:/* dump rx/tx packet */
2910 {
2911 if (arg == 0) {
2912 DBG_871X("dump rx packet (%d)\n", extra_arg);
2913 /* pHalData->bDumpRxPkt =extra_arg; */
2914 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
f85ac230 2915 } else if (arg == 1) {
554c0a3a
HG
2916 DBG_871X("dump tx packet (%d)\n", extra_arg);
2917 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
2918 }
2919 }
2920 break;
2921 case 0x0e:
2922 {
2923 if (arg == 0) {
2924 DBG_871X("disable driver ctrl rx_ampdu_factor\n");
2925 padapter->driver_rx_ampdu_factor = 0xFF;
f85ac230 2926 } else if (arg == 1) {
554c0a3a
HG
2927
2928 DBG_871X("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg);
2929
2930 if ((extra_arg & 0x03) > 0x03)
2931 padapter->driver_rx_ampdu_factor = 0xFF;
2932 else
2933 padapter->driver_rx_ampdu_factor = extra_arg;
2934 }
2935 }
2936 break;
2937
2938 case 0x10:/* driver version display */
2939 dump_drv_version(RTW_DBGDUMP);
2940 break;
2941 case 0x11:/* dump linked status */
2942 {
2943 linked_info_dump(padapter, extra_arg);
2944 }
2945 break;
2946 case 0x12: /* set rx_stbc */
2947 {
2948 struct registry_priv *pregpriv = &padapter->registrypriv;
2949 /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
2950 /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
2a68ead3 2951 if (extra_arg == 0 || extra_arg == 1 || extra_arg == 2 || extra_arg == 3) {
554c0a3a
HG
2952 pregpriv->rx_stbc = extra_arg;
2953 DBG_871X("set rx_stbc =%d\n", pregpriv->rx_stbc);
f85ac230 2954 } else
554c0a3a
HG
2955 DBG_871X("get rx_stbc =%d\n", pregpriv->rx_stbc);
2956
2957 }
2958 break;
2959 case 0x13: /* set ampdu_enable */
2960 {
2961 struct registry_priv *pregpriv = &padapter->registrypriv;
2962 /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
2a68ead3 2963 if (extra_arg < 3) {
554c0a3a
HG
2964 pregpriv->ampdu_enable = extra_arg;
2965 DBG_871X("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
f85ac230 2966 } else
554c0a3a
HG
2967 DBG_871X("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
2968
2969 }
2970 break;
2971 case 0x14:
2972 {
2973 DBG_871X("minor_cmd 0x%x\n", minor_cmd);
2974 }
2975 break;
2976 case 0x16:
2977 {
2978 if (arg == 0xff) {
2979 rtw_odm_dbg_comp_msg(RTW_DBGDUMP, padapter);
f85ac230 2980 } else {
554c0a3a
HG
2981 u64 dbg_comp = (u64)extra_arg;
2982 rtw_odm_dbg_comp_set(padapter, dbg_comp);
2983 }
2984 }
2985 break;
2986#ifdef DBG_FIXED_CHAN
2987 case 0x17:
2988 {
2989 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2990 printk("===> Fixed channel to %d\n", extra_arg);
2991 pmlmeext->fixed_chan = extra_arg;
2992
2993 }
2994 break;
2995#endif
2996 case 0x18:
2997 {
2998 printk("===> Switch USB Mode %d\n", extra_arg);
2999 rtw_hal_set_hwreg(padapter, HW_VAR_USB_MODE, (u8 *)&extra_arg);
3000 }
3001 break;
3002 case 0x19:
3003 {
3004 struct registry_priv *pregistrypriv = &padapter->registrypriv;
3005 /* extra_arg : */
3006 /* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
3007 /* BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
3008 if (arg == 0) {
3009 DBG_871X("driver disable LDPC\n");
3010 pregistrypriv->ldpc_cap = 0x00;
f85ac230 3011 } else if (arg == 1) {
554c0a3a
HG
3012 DBG_871X("driver set LDPC cap = 0x%x\n", extra_arg);
3013 pregistrypriv->ldpc_cap = (u8)(extra_arg&0x33);
3014 }
3015 }
3016 break;
3017 case 0x1a:
3018 {
3019 struct registry_priv *pregistrypriv = &padapter->registrypriv;
3020 /* extra_arg : */
3021 /* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
3022 /* BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
3023 if (arg == 0) {
3024 DBG_871X("driver disable STBC\n");
3025 pregistrypriv->stbc_cap = 0x00;
f85ac230 3026 } else if (arg == 1) {
554c0a3a
HG
3027 DBG_871X("driver set STBC cap = 0x%x\n", extra_arg);
3028 pregistrypriv->stbc_cap = (u8)(extra_arg&0x33);
3029 }
3030 }
3031 break;
3032 case 0x1b:
3033 {
3034 struct registry_priv *pregistrypriv = &padapter->registrypriv;
3035
3036 if (arg == 0) {
3037 DBG_871X("disable driver ctrl max_rx_rate, reset to default_rate_set\n");
3038 init_mlme_default_rate_set(padapter);
3039 pregistrypriv->ht_enable = (u8)rtw_ht_enable;
f85ac230 3040 } else if (arg == 1) {
554c0a3a
HG
3041
3042 int i;
3043 u8 max_rx_rate;
3044
3045 DBG_871X("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg);
3046
3047 max_rx_rate = (u8)extra_arg;
3048
f85ac230 3049 if (max_rx_rate < 0xc) { /* max_rx_rate < MSC0 -> B or G -> disable HT */
554c0a3a 3050 pregistrypriv->ht_enable = 0;
c77761d6 3051 for (i = 0; i < NumRates; i++) {
554c0a3a
HG
3052 if (pmlmeext->datarate[i] > max_rx_rate)
3053 pmlmeext->datarate[i] = 0xff;
3054 }
3055
3056 }
f85ac230 3057 else if (max_rx_rate < 0x1c) { /* mcs0~mcs15 */
554c0a3a
HG
3058 u32 mcs_bitmap = 0x0;
3059
c77761d6 3060 for (i = 0; i < ((max_rx_rate + 1) - 0xc); i++)
554c0a3a
HG
3061 mcs_bitmap |= BIT(i);
3062
3063 set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
3064 }
3065 }
3066 }
3067 break;
3068 case 0x1c: /* enable/disable driver control AMPDU Density for peer sta's rx */
3069 {
3070 if (arg == 0) {
3071 DBG_871X("disable driver ctrl ampdu density\n");
3072 padapter->driver_ampdu_spacing = 0xFF;
f85ac230 3073 } else if (arg == 1) {
554c0a3a
HG
3074
3075 DBG_871X("enable driver ctrl ampdu density = %d\n", extra_arg);
3076
99803f17 3077 if (extra_arg > 0x07)
554c0a3a
HG
3078 padapter->driver_ampdu_spacing = 0xFF;
3079 else
3080 padapter->driver_ampdu_spacing = extra_arg;
3081 }
3082 }
3083 break;
3084#ifdef CONFIG_BACKGROUND_NOISE_MONITOR
3085 case 0x1e:
3086 {
3087 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
3088 PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
3089 u8 chan = rtw_get_oper_ch(padapter);
3090 DBG_871X("===========================================\n");
3091 ODM_InbandNoise_Monitor(pDM_Odm, true, 0x1e, 100);
3092 DBG_871X("channel(%d), noise_a = %d, noise_b = %d , noise_all:%d\n",
3093 chan, pDM_Odm->noise_level.noise[ODM_RF_PATH_A],
3094 pDM_Odm->noise_level.noise[ODM_RF_PATH_B],
3095 pDM_Odm->noise_level.noise_all);
3096 DBG_871X("===========================================\n");
3097
3098 }
3099 break;
3100#endif
3101 case 0x23:
3102 {
3103 DBG_871X("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1)?"on":"off");
3104 padapter->bNotifyChannelChange = extra_arg;
3105 break;
3106 }
3107 case 0x24:
3108 {
3109 break;
3110 }
3111#ifdef CONFIG_GPIO_API
3112 case 0x25: /* Get GPIO register */
3113 {
3114 /*
3115 * dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7
3116 */
3117
3118 int value;
3119 DBG_871X("Read GPIO Value extra_arg = %d\n", extra_arg);
3120 value = rtw_get_gpio(dev, extra_arg);
3121 DBG_871X("Read GPIO Value = %d\n", value);
3122 break;
3123 }
3124 case 0x26: /* Set GPIO direction */
3125 {
3126
3127 /* dbg 0x7f26000x [y], Set gpio direction,
3128 * x: gpio_num, 4~7 y: indicate direction, 0~1
3129 */
3130
3131 int value;
c77761d6 3132 DBG_871X("Set GPIO Direction! arg = %d , extra_arg =%d\n", arg, extra_arg);
554c0a3a 3133 value = rtw_config_gpio(dev, arg, extra_arg);
c77761d6 3134 DBG_871X("Set GPIO Direction %s\n", (value == -1) ? "Fail!!!" : "Success");
554c0a3a
HG
3135 break;
3136 }
3137 case 0x27: /* Set GPIO output direction value */
3138 {
3139 /*
3140 * dbg 0x7f27000x [y], Set gpio output direction value,
3141 * x: gpio_num, 4~7 y: indicate direction, 0~1
3142 */
3143
3144 int value;
c77761d6 3145 DBG_871X("Set GPIO Value! arg = %d , extra_arg =%d\n", arg, extra_arg);
554c0a3a 3146 value = rtw_set_gpio_output_value(dev, arg, extra_arg);
c77761d6 3147 DBG_871X("Set GPIO Value %s\n", (value == -1) ? "Fail!!!" : "Success");
554c0a3a
HG
3148 break;
3149 }
3150#endif
3151 case 0xaa:
3152 {
c77761d6 3153 if ((extra_arg & 0x7F) > 0x3F) extra_arg = 0xFF;
554c0a3a
HG
3154 DBG_871X("chang data rate to :0x%02x\n", extra_arg);
3155 padapter->fix_rate = extra_arg;
3156 }
3157 break;
3158 case 0xdd:/* registers dump , 0 for mac reg, 1 for bb reg, 2 for rf reg */
3159 {
f85ac230 3160 if (extra_arg == 0)
554c0a3a 3161 mac_reg_dump(RTW_DBGDUMP, padapter);
f85ac230 3162 else if (extra_arg == 1)
554c0a3a 3163 bb_reg_dump(RTW_DBGDUMP, padapter);
c77761d6 3164 else if (extra_arg == 2)
554c0a3a 3165 rf_reg_dump(RTW_DBGDUMP, padapter);
554c0a3a
HG
3166 }
3167 break;
3168
3169 case 0xee:/* turn on/off dynamic funcs */
3170 {
3171 u32 odm_flag;
3172
c77761d6
LS
3173 if (0xf == extra_arg) {
3174 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
554c0a3a
HG
3175 DBG_871X(" === DMFlag(0x%08x) ===\n", odm_flag);
3176 DBG_871X("extra_arg = 0 - disable all dynamic func\n");
3177 DBG_871X("extra_arg = 1 - disable DIG- BIT(0)\n");
3178 DBG_871X("extra_arg = 2 - disable High power - BIT(1)\n");
3179 DBG_871X("extra_arg = 3 - disable tx power tracking - BIT(2)\n");
3180 DBG_871X("extra_arg = 4 - disable BT coexistence - BIT(3)\n");
3181 DBG_871X("extra_arg = 5 - disable antenna diversity - BIT(4)\n");
3182 DBG_871X("extra_arg = 6 - enable all dynamic func\n");
f85ac230 3183 } else {
554c0a3a
HG
3184 /*extra_arg = 0 - disable all dynamic func
3185 extra_arg = 1 - disable DIG
3186 extra_arg = 2 - disable tx power tracking
3187 extra_arg = 3 - turn on all dynamic func
3188 */
3189 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
c77761d6 3190 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
554c0a3a
HG
3191 DBG_871X(" === DMFlag(0x%08x) ===\n", odm_flag);
3192 }
3193 }
3194 break;
3195
3196 case 0xfd:
3197 rtw_write8(padapter, 0xc50, arg);
3198 DBG_871X("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
3199 rtw_write8(padapter, 0xc58, arg);
3200 DBG_871X("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
3201 break;
3202 case 0xfe:
3203 DBG_871X("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
3204 DBG_871X("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
3205 break;
3206 case 0xff:
3207 {
3208 DBG_871X("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210));
3209 DBG_871X("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608));
3210 DBG_871X("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280));
3211 DBG_871X("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284));
3212 DBG_871X("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288));
3213
3214 DBG_871X("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664));
3215
3216
3217 DBG_871X("\n");
3218
3219 DBG_871X("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430));
3220 DBG_871X("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438));
3221
3222 DBG_871X("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440));
3223
3224 DBG_871X("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458));
3225
3226 DBG_871X("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484));
3227 DBG_871X("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488));
3228
3229 DBG_871X("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444));
3230 DBG_871X("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448));
3231 DBG_871X("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c));
3232 DBG_871X("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450));
3233 }
3234 break;
3235 }
3236 break;
3237 default:
3238 DBG_871X("error dbg cmd!\n");
3239 break;
3240 }
3241
3242
a8f7e0c9 3243 return 0;
554c0a3a
HG
3244
3245}
3246
3247static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
3248{
3249 uint ret = 0;
3250 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3251
3252 switch (name) {
3253 case IEEE_PARAM_WPA_ENABLED:
3254
3255 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
3256
3257 /* ret = ieee80211_wpa_enable(ieee, value); */
3258
f85ac230 3259 switch ((value)&0xff) {
c77761d6 3260 case 1: /* WPA */
554c0a3a
HG
3261 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
3262 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
3263 break;
3264 case 2: /* WPA2 */
3265 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
3266 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
3267 break;
3268 }
3269
3270 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
3271
3272 break;
3273
3274 case IEEE_PARAM_TKIP_COUNTERMEASURES:
3275 /* ieee->tkip_countermeasures =value; */
3276 break;
3277
3278 case IEEE_PARAM_DROP_UNENCRYPTED:
3279 {
3280 /* HACK:
3281 *
3282 * wpa_supplicant calls set_wpa_enabled when the driver
3283 * is loaded and unloaded, regardless of if WPA is being
3284 * used. No other calls are made which can be used to
3285 * determine if encryption will be used or not prior to
3286 * association being expected. If encryption is not being
3287 * used, drop_unencrypted is set to false, else true -- we
3288 * can use this to determine if the CAP_PRIVACY_ON bit should
3289 * be set.
3290 */
3291 break;
3292
3293 }
3294 case IEEE_PARAM_PRIVACY_INVOKED:
3295
3296 /* ieee->privacy_invoked =value; */
3297
3298 break;
3299
3300 case IEEE_PARAM_AUTH_ALGS:
3301
3302 ret = wpa_set_auth_algs(dev, value);
3303
3304 break;
3305
3306 case IEEE_PARAM_IEEE_802_1X:
3307
3308 /* ieee->ieee802_1x =value; */
3309
3310 break;
3311
3312 case IEEE_PARAM_WPAX_SELECT:
3313
3314 /* added for WPA2 mixed mode */
3315 /* DBG_871X(KERN_WARNING "------------------------>wpax value = %x\n", value); */
3316 /*
3317 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
3318 ieee->wpax_type_set = 1;
3319 ieee->wpax_type_notify = value;
3320 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
3321 */
3322
3323 break;
3324
3325 default:
3326
3327
3328
3329 ret = -EOPNOTSUPP;
3330
3331
3332 break;
3333
3334 }
3335
3336 return ret;
3337
3338}
3339
3340static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
3341{
3342 int ret = 0;
3343 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3344
f85ac230 3345 switch (command) {
2dd67029 3346 case IEEE_MLME_STA_DEAUTH:
554c0a3a 3347
2dd67029
PM
3348 if (!rtw_set_802_11_disassociate(padapter))
3349 ret = -1;
554c0a3a 3350
2dd67029 3351 break;
554c0a3a 3352
2dd67029 3353 case IEEE_MLME_STA_DISASSOC:
554c0a3a 3354
2dd67029
PM
3355 if (!rtw_set_802_11_disassociate(padapter))
3356 ret = -1;
554c0a3a 3357
2dd67029 3358 break;
554c0a3a 3359
2dd67029
PM
3360 default:
3361 ret = -EOPNOTSUPP;
3362 break;
554c0a3a
HG
3363 }
3364
3365 return ret;
3366
3367}
3368
3369static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
3370{
3371 struct ieee_param *param;
3372 uint ret = 0;
3373
3374 /* down(&ieee->wx_sem); */
3375
9a4556bd
LF
3376 if (!p->pointer || p->length != sizeof(struct ieee_param))
3377 return -EINVAL;
554c0a3a 3378
2ef2b7c2 3379 param = rtw_malloc(p->length);
9a4556bd
LF
3380 if (param == NULL)
3381 return -ENOMEM;
554c0a3a 3382
f85ac230 3383 if (copy_from_user(param, p->pointer, p->length)) {
428715ba 3384 kfree(param);
9a4556bd 3385 return -EFAULT;
554c0a3a
HG
3386 }
3387
3388 switch (param->cmd) {
3389
3390 case IEEE_CMD_SET_WPA_PARAM:
3391 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
3392 break;
3393
3394 case IEEE_CMD_SET_WPA_IE:
3395 /* ret = wpa_set_wpa_ie(dev, param, p->length); */
a7dd567e 3396 ret = rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
554c0a3a
HG
3397 break;
3398
3399 case IEEE_CMD_SET_ENCRYPTION:
3400 ret = wpa_set_encryption(dev, param, p->length);
3401 break;
3402
3403 case IEEE_CMD_MLME:
3404 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
3405 break;
3406
3407 default:
3408 DBG_871X("Unknown WPA supplicant request: %d\n", param->cmd);
3409 ret = -EOPNOTSUPP;
3410 break;
3411
3412 }
3413
3414 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3415 ret = -EFAULT;
3416
428715ba 3417 kfree(param);
554c0a3a 3418
554c0a3a 3419 /* up(&ieee->wx_sem); */
554c0a3a 3420 return ret;
554c0a3a
HG
3421}
3422
3423static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
3424{
3425 int ret = 0;
3426 u32 wep_key_idx, wep_key_len, wep_total_len;
3427 struct ndis_802_11_wep *pwep = NULL;
3428 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
3429 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3430 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
c77761d6 3431 struct security_priv* psecuritypriv = &(padapter->securitypriv);
554c0a3a
HG
3432 struct sta_priv *pstapriv = &padapter->stapriv;
3433
3434 DBG_871X("%s\n", __func__);
3435
3436 param->u.crypt.err = 0;
3437 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3438
3439 /* sizeof(struct ieee_param) = 64 bytes; */
3440 /* if (param_len != (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
f85ac230 3441 if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
554c0a3a
HG
3442 ret = -EINVAL;
3443 goto exit;
3444 }
3445
3446 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3447 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230
TD
3448 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3449 if (param->u.crypt.idx >= WEP_KEYS) {
554c0a3a
HG
3450 ret = -EINVAL;
3451 goto exit;
3452 }
f85ac230 3453 } else {
554c0a3a 3454 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
f85ac230 3455 if (!psta) {
554c0a3a
HG
3456 /* ret = -EINVAL; */
3457 DBG_871X("rtw_set_encryption(), sta has already been removed or never been added\n");
3458 goto exit;
3459 }
3460 }
3461
f85ac230 3462 if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
554c0a3a
HG
3463 /* todo:clear default encryption keys */
3464
3465 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
3466 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
3467 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
3468 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3469
3470 DBG_871X("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
3471
3472 goto exit;
3473 }
3474
3475
f85ac230 3476 if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
554c0a3a
HG
3477 DBG_871X("r871x_set_encryption, crypt.alg = WEP\n");
3478
3479 wep_key_idx = param->u.crypt.idx;
3480 wep_key_len = param->u.crypt.key_len;
3481
3482 DBG_871X("r871x_set_encryption, wep_key_idx =%d, len =%d\n", wep_key_idx, wep_key_len);
3483
c77761d6 3484 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
554c0a3a
HG
3485 ret = -EINVAL;
3486 goto exit;
3487 }
3488
3489
f85ac230 3490 if (wep_key_len > 0) {
554c0a3a
HG
3491 wep_key_len = wep_key_len <= 5 ? 5 : 13;
3492 wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
6254acde 3493 pwep = kzalloc(wep_total_len, GFP_KERNEL);
554c0a3a
HG
3494 if (pwep == NULL) {
3495 DBG_871X(" r871x_set_encryption: pwep allocate fail !!!\n");
3496 goto exit;
3497 }
3498
554c0a3a
HG
3499 pwep->KeyLength = wep_key_len;
3500 pwep->Length = wep_total_len;
3501
3502 }
3503
3504 pwep->KeyIndex = wep_key_idx;
3505
3506 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
3507
f85ac230 3508 if (param->u.crypt.set_tx) {
554c0a3a
HG
3509 DBG_871X("wep, set_tx = 1\n");
3510
3511 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3512 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
3513 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
3514 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3515
f85ac230 3516 if (pwep->KeyLength == 13) {
554c0a3a
HG
3517 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
3518 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
3519 }
3520
3521
3522 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
3523
3524 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
3525
c77761d6 3526 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
554c0a3a
HG
3527
3528 rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
f85ac230 3529 } else {
554c0a3a
HG
3530 DBG_871X("wep, set_tx = 0\n");
3531
3532 /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
3533 /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
3534
3535 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
3536
3537 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
3538
3539 rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
3540 }
3541
3542 goto exit;
3543
3544 }
3545
3546
f85ac230
TD
3547 if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
3548 if (param->u.crypt.set_tx == 1) {
3549 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
554c0a3a
HG
3550 DBG_871X("%s, set group_key, WEP\n", __func__);
3551
c77761d6 3552 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a
HG
3553
3554 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3555 if (param->u.crypt.key_len == 13)
554c0a3a 3556 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
554c0a3a 3557
f85ac230 3558 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
554c0a3a
HG
3559 DBG_871X("%s, set group_key, TKIP\n", __func__);
3560
3561 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
3562
c77761d6 3563 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a
HG
3564
3565 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3566 /* set mic key */
3567 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
3568 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
3569
3570 psecuritypriv->busetkipkey = true;
3571
3572 }
f85ac230 3573 else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
554c0a3a
HG
3574 DBG_871X("%s, set group_key, CCMP\n", __func__);
3575
3576 psecuritypriv->dot118021XGrpPrivacy = _AES_;
3577
c77761d6 3578 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
f85ac230 3579 } else {
554c0a3a
HG
3580 DBG_871X("%s, set group_key, none\n", __func__);
3581
3582 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3583 }
3584
3585 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
3586
3587 psecuritypriv->binstallGrpkey = true;
3588
3589 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
3590
3591 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
3592
c77761d6 3593 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
f85ac230 3594 if (pbcmc_sta) {
554c0a3a
HG
3595 pbcmc_sta->ieee8021x_blocked = false;
3596 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
3597 }
554c0a3a
HG
3598 }
3599
3600 goto exit;
3601
3602 }
3603
f85ac230
TD
3604 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
3605 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3606 if (param->u.crypt.set_tx == 1) {
c77761d6 3607 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a 3608
f85ac230 3609 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
554c0a3a
HG
3610 DBG_871X("%s, set pairwise key, WEP\n", __func__);
3611
3612 psta->dot118021XPrivacy = _WEP40_;
3613 if (param->u.crypt.key_len == 13)
554c0a3a 3614 psta->dot118021XPrivacy = _WEP104_;
f85ac230 3615 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
554c0a3a
HG
3616 DBG_871X("%s, set pairwise key, TKIP\n", __func__);
3617
3618 psta->dot118021XPrivacy = _TKIP_;
3619
3620 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3621 /* set mic key */
3622 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
3623 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
3624
3625 psecuritypriv->busetkipkey = true;
3626
f85ac230 3627 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
554c0a3a
HG
3628
3629 DBG_871X("%s, set pairwise key, CCMP\n", __func__);
3630
3631 psta->dot118021XPrivacy = _AES_;
f85ac230 3632 } else {
554c0a3a
HG
3633 DBG_871X("%s, set pairwise key, none\n", __func__);
3634
3635 psta->dot118021XPrivacy = _NO_PRIVACY_;
3636 }
3637
3638 rtw_ap_set_pairwise_key(padapter, psta);
3639
3640 psta->ieee8021x_blocked = false;
3641
f85ac230
TD
3642 } else { /* group key??? */
3643 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
c77761d6 3644 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a
HG
3645
3646 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3647 if (param->u.crypt.key_len == 13)
554c0a3a 3648 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
f85ac230 3649 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
554c0a3a
HG
3650 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
3651
c77761d6 3652 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
554c0a3a
HG
3653
3654 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3655 /* set mic key */
3656 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
3657 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
3658
3659 psecuritypriv->busetkipkey = true;
3660
f85ac230 3661 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
554c0a3a
HG
3662 psecuritypriv->dot118021XGrpPrivacy = _AES_;
3663
c77761d6 3664 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
f85ac230 3665 } else {
554c0a3a
HG
3666 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3667 }
3668
3669 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
3670
3671 psecuritypriv->binstallGrpkey = true;
3672
3673 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
3674
3675 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
3676
c77761d6 3677 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
f85ac230 3678 if (pbcmc_sta) {
554c0a3a
HG
3679 pbcmc_sta->ieee8021x_blocked = false;
3680 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
3681 }
554c0a3a 3682 }
554c0a3a 3683 }
554c0a3a
HG
3684 }
3685
3686exit:
428715ba 3687 kfree(pwep);
554c0a3a
HG
3688
3689 return ret;
3690
3691}
3692
3693static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
3694{
3695 int ret = 0;
3696 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3697 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3698 struct sta_priv *pstapriv = &padapter->stapriv;
3699 unsigned char *pbuf = param->u.bcn_ie.buf;
3700
3701
3702 DBG_871X("%s, len =%d\n", __func__, len);
3703
3704 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3705 return -EINVAL;
3706
3707 memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
3708
c77761d6 3709 if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
554c0a3a
HG
3710 pstapriv->max_num_sta = NUM_STA;
3711
3712
3713 if (rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)/* 12 = param header, 2:no packed */
3714 ret = 0;
3715 else
3716 ret = -EINVAL;
3717
3718
3719 return ret;
3720
3721}
3722
371ec021 3723static void rtw_hostapd_sta_flush(struct net_device *dev)
554c0a3a
HG
3724{
3725 /* _irqL irqL; */
3726 /* struct list_head *phead, *plist; */
554c0a3a
HG
3727 /* struct sta_info *psta = NULL; */
3728 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3729 /* struct sta_priv *pstapriv = &padapter->stapriv; */
3730
3731 DBG_871X("%s\n", __func__);
3732
3733 flush_all_cam_entry(padapter); /* clear CAM */
3734
371ec021 3735 rtw_sta_flush(padapter);
554c0a3a
HG
3736}
3737
3738static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
3739{
3740 int ret = 0;
3741 struct sta_info *psta = NULL;
3742 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3743 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3744 struct sta_priv *pstapriv = &padapter->stapriv;
3745
3746 DBG_871X("rtw_add_sta(aid =%d) =" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
3747
3748 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
554c0a3a 3749 return -EINVAL;
554c0a3a
HG
3750
3751 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3752 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230 3753 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
554c0a3a
HG
3754 return -EINVAL;
3755 }
3756
3757/*
3758 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3759 if (psta)
3760 {
3761 DBG_871X("rtw_add_sta(), free has been added psta =%p\n", psta);
3762 spin_lock_bh(&(pstapriv->sta_hash_lock));
3763 rtw_free_stainfo(padapter, psta);
3764 spin_unlock_bh(&(pstapriv->sta_hash_lock));
3765
3766 psta = NULL;
3767 }
3768*/
3769 /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
3770 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
f85ac230 3771 if (psta) {
554c0a3a
HG
3772 int flags = param->u.add_sta.flags;
3773
3774 /* DBG_871X("rtw_add_sta(), init sta's variables, psta =%p\n", psta); */
3775
3776 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
3777
3778 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
3779
3780
3781 /* check wmm cap. */
3782 if (WLAN_STA_WME&flags)
3783 psta->qos_option = 1;
3784 else
3785 psta->qos_option = 0;
3786
3787 if (pmlmepriv->qospriv.qos_option == 0)
3788 psta->qos_option = 0;
3789
3790 /* chec 802.11n ht cap. */
f85ac230 3791 if (WLAN_STA_HT&flags) {
554c0a3a
HG
3792 psta->htpriv.ht_option = true;
3793 psta->qos_option = 1;
a7dd567e 3794 memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
f85ac230 3795 } else {
554c0a3a
HG
3796 psta->htpriv.ht_option = false;
3797 }
3798
3799 if (pmlmepriv->htpriv.ht_option == false)
3800 psta->htpriv.ht_option = false;
3801
3802 update_sta_info_apmode(padapter, psta);
3803
3804
f85ac230 3805 } else {
554c0a3a
HG
3806 ret = -ENOMEM;
3807 }
3808
3809 return ret;
3810
3811}
3812
3813static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
3814{
3815 int ret = 0;
3816 struct sta_info *psta = NULL;
3817 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3818 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3819 struct sta_priv *pstapriv = &padapter->stapriv;
3820
3821 DBG_871X("rtw_del_sta =" MAC_FMT "\n", MAC_ARG(param->sta_addr));
3822
3823 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
554c0a3a 3824 return -EINVAL;
554c0a3a
HG
3825
3826 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3827 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230 3828 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
554c0a3a
HG
3829 return -EINVAL;
3830 }
3831
3832 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
f85ac230 3833 if (psta) {
c77761d6 3834 u8 updated = false;
554c0a3a
HG
3835
3836 /* DBG_871X("free psta =%p, aid =%d\n", psta, psta->aid); */
3837
3838 spin_lock_bh(&pstapriv->asoc_list_lock);
c77761d6 3839 if (list_empty(&psta->asoc_list) == false) {
554c0a3a
HG
3840 list_del_init(&psta->asoc_list);
3841 pstapriv->asoc_list_cnt--;
3842 updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
3843
3844 }
3845 spin_unlock_bh(&pstapriv->asoc_list_lock);
3846
3847 associated_clients_update(padapter, updated);
3848
3849 psta = NULL;
3850
f85ac230 3851 } else {
554c0a3a
HG
3852 DBG_871X("rtw_del_sta(), sta has already been removed or never been added\n");
3853
3854 /* ret = -1; */
3855 }
3856
3857
3858 return ret;
3859
3860}
3861
3862static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
3863{
3864 int ret = 0;
3865 struct sta_info *psta = NULL;
3866 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3867 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3868 struct sta_priv *pstapriv = &padapter->stapriv;
3869 struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
3870 struct sta_data *psta_data = (struct sta_data *)param_ex->data;
3871
3872 DBG_871X("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
3873
3874 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
554c0a3a 3875 return -EINVAL;
554c0a3a
HG
3876
3877 if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
3878 param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
f85ac230 3879 param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
554c0a3a
HG
3880 return -EINVAL;
3881 }
3882
3883 psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
f85ac230 3884 if (psta) {
554c0a3a
HG
3885 psta_data->aid = (u16)psta->aid;
3886 psta_data->capability = psta->capability;
3887 psta_data->flags = psta->flags;
3888
3889/*
3890 nonerp_set : BIT(0)
3891 no_short_slot_time_set : BIT(1)
3892 no_short_preamble_set : BIT(2)
3893 no_ht_gf_set : BIT(3)
3894 no_ht_set : BIT(4)
3895 ht_20mhz_set : BIT(5)
3896*/
3897
c77761d6
LS
3898 psta_data->sta_set = ((psta->nonerp_set) |
3899 (psta->no_short_slot_time_set << 1) |
3900 (psta->no_short_preamble_set << 2) |
3901 (psta->no_ht_gf_set << 3) |
3902 (psta->no_ht_set << 4) |
3903 (psta->ht_20mhz_set << 5));
554c0a3a
HG
3904
3905 psta_data->tx_supp_rates_len = psta->bssratelen;
3906 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
3907 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
3908 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
3909 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
3910 psta_data->rx_drops = psta->sta_stats.rx_drops;
3911
3912 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
3913 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
3914 psta_data->tx_drops = psta->sta_stats.tx_drops;
3915
3916
f85ac230 3917 } else {
554c0a3a
HG
3918 ret = -1;
3919 }
3920
3921 return ret;
3922
3923}
3924
3925static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
3926{
3927 int ret = 0;
3928 struct sta_info *psta = NULL;
3929 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3930 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3931 struct sta_priv *pstapriv = &padapter->stapriv;
3932
3933 DBG_871X("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
3934
3935 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
554c0a3a 3936 return -EINVAL;
554c0a3a
HG
3937
3938 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3939 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230 3940 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
554c0a3a
HG
3941 return -EINVAL;
3942 }
3943
3944 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
f85ac230
TD
3945 if (psta) {
3946 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
554c0a3a
HG
3947 int wpa_ie_len;
3948 int copy_len;
3949
3950 wpa_ie_len = psta->wpa_ie[1];
3951
3952 copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
3953
3954 param->u.wpa_ie.len = copy_len;
3955
3956 memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
f85ac230 3957 } else {
554c0a3a
HG
3958 /* ret = -1; */
3959 DBG_871X("sta's wpa_ie is NONE\n");
3960 }
f85ac230 3961 } else {
554c0a3a
HG
3962 ret = -1;
3963 }
3964
3965 return ret;
3966
3967}
3968
3969static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
3970{
3971 int ret = 0;
c77761d6 3972 unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
554c0a3a
HG
3973 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3974 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3975 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3976 int ie_len;
3977
3978 DBG_871X("%s, len =%d\n", __func__, len);
3979
3980 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3981 return -EINVAL;
3982
3983 ie_len = len-12-2;/* 12 = param header, 2:no packed */
3984
3985
4d506758
HJ
3986 kfree(pmlmepriv->wps_beacon_ie);
3987 pmlmepriv->wps_beacon_ie = NULL;
554c0a3a 3988
c77761d6 3989 if (ie_len > 0) {
554c0a3a
HG
3990 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
3991 pmlmepriv->wps_beacon_ie_len = ie_len;
3992 if (pmlmepriv->wps_beacon_ie == NULL) {
3993 DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
3994 return -EINVAL;
3995 }
3996
3997 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
3998
3999 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
4000
4001 pmlmeext->bstart_bss = true;
554c0a3a
HG
4002 }
4003
4004
4005 return ret;
4006
4007}
4008
4009static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
4010{
4011 int ret = 0;
4012 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4013 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4014 int ie_len;
4015
4016 DBG_871X("%s, len =%d\n", __func__, len);
4017
4018 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4019 return -EINVAL;
4020
4021 ie_len = len-12-2;/* 12 = param header, 2:no packed */
4022
4023
4d506758
HJ
4024 kfree(pmlmepriv->wps_probe_resp_ie);
4025 pmlmepriv->wps_probe_resp_ie = NULL;
554c0a3a 4026
c77761d6 4027 if (ie_len > 0) {
554c0a3a
HG
4028 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
4029 pmlmepriv->wps_probe_resp_ie_len = ie_len;
4030 if (pmlmepriv->wps_probe_resp_ie == NULL) {
4031 DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4032 return -EINVAL;
4033 }
4034 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
4035 }
4036
4037
4038 return ret;
4039
4040}
4041
4042static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
4043{
4044 int ret = 0;
4045 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4046 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4047 int ie_len;
4048
4049 DBG_871X("%s, len =%d\n", __func__, len);
4050
4051 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4052 return -EINVAL;
4053
4054 ie_len = len-12-2;/* 12 = param header, 2:no packed */
4055
4056
4d506758
HJ
4057 kfree(pmlmepriv->wps_assoc_resp_ie);
4058 pmlmepriv->wps_assoc_resp_ie = NULL;
554c0a3a 4059
c77761d6 4060 if (ie_len > 0) {
554c0a3a
HG
4061 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
4062 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
4063 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
4064 DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4065 return -EINVAL;
4066 }
4067
4068 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
4069 }
4070
4071
4072 return ret;
4073
4074}
4075
4076static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
4077{
4078 int ret = 0;
4079 struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
4080 struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
4081 struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
4082 struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
4083 int ie_len;
4084 u8 *ssid_ie;
4085 char ssid[NDIS_802_11_LENGTH_SSID + 1];
4086 sint ssid_len;
4087 u8 ignore_broadcast_ssid;
4088
4089 if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
4090 return -EPERM;
4091
4092 if (param->u.bcn_ie.reserved[0] != 0xea)
4093 return -EINVAL;
4094
4095 mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
4096
4097 ie_len = len-12-2;/* 12 = param header, 2:no packed */
4098 ssid_ie = rtw_get_ie(param->u.bcn_ie.buf, WLAN_EID_SSID, &ssid_len, ie_len);
4099
4100 if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
4101 struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network;
4102 struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network;
4103
4104 memcpy(ssid, ssid_ie+2, ssid_len);
4105 ssid[ssid_len] = 0x0;
4106
4107 if (0)
4108 DBG_871X(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
4109 ssid, ssid_len,
4110 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
4111 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
4112
4113 memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
4114 pbss_network->Ssid.SsidLength = ssid_len;
4115 memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
4116 pbss_network_ext->Ssid.SsidLength = ssid_len;
4117
4118 if (0)
4119 DBG_871X(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
4120 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
4121 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
4122 }
4123
4124 DBG_871X(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
4125 ignore_broadcast_ssid, ssid, ssid_len);
4126
4127 return ret;
4128}
4129
4130static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
4131{
554c0a3a
HG
4132 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4133 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4134
4135 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4136 return -EINVAL;
4137
4138 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4139 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230 4140 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
554c0a3a
HG
4141 return -EINVAL;
4142 }
4143
4769aae3
SK
4144 rtw_acl_remove_sta(padapter, param->sta_addr);
4145 return 0;
554c0a3a
HG
4146
4147}
4148
4149static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
4150{
554c0a3a
HG
4151 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4152 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4153
4154 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4155 return -EINVAL;
4156
4157 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4158 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
f85ac230 4159 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
554c0a3a
HG
4160 return -EINVAL;
4161 }
4162
dedc1a73 4163 return rtw_acl_add_sta(padapter, param->sta_addr);
554c0a3a
HG
4164
4165}
4166
4167static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
4168{
4169 int ret = 0;
4170 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4171 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4172
4173 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4174 return -EINVAL;
4175
4176 rtw_set_macaddr_acl(padapter, param->u.mlme.command);
4177
4178 return ret;
4179}
4180
4181static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
4182{
4183 struct ieee_param *param;
4184 int ret = 0;
4185 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4186
4187 /* DBG_871X("%s\n", __func__); */
4188
4189 /*
4190 * this function is expect to call in master mode, which allows no power saving
4191 * so, we just check hw_init_completed
4192 */
4193
9a4556bd
LF
4194 if (!padapter->hw_init_completed)
4195 return -EPERM;
554c0a3a 4196
9a4556bd
LF
4197 if (!p->pointer || p->length != sizeof(*param))
4198 return -EINVAL;
554c0a3a 4199
2ef2b7c2 4200 param = rtw_malloc(p->length);
9a4556bd
LF
4201 if (param == NULL)
4202 return -ENOMEM;
554c0a3a 4203
f85ac230 4204 if (copy_from_user(param, p->pointer, p->length)) {
428715ba 4205 kfree(param);
9a4556bd 4206 return -EFAULT;
554c0a3a
HG
4207 }
4208
4209 /* DBG_871X("%s, cmd =%d\n", __func__, param->cmd); */
4210
f85ac230 4211 switch (param->cmd) {
2dd67029 4212 case RTL871X_HOSTAPD_FLUSH:
554c0a3a 4213
371ec021 4214 rtw_hostapd_sta_flush(dev);
554c0a3a 4215
2dd67029 4216 break;
554c0a3a 4217
2dd67029 4218 case RTL871X_HOSTAPD_ADD_STA:
554c0a3a 4219
2dd67029 4220 ret = rtw_add_sta(dev, param);
554c0a3a 4221
2dd67029 4222 break;
554c0a3a 4223
2dd67029 4224 case RTL871X_HOSTAPD_REMOVE_STA:
554c0a3a 4225
2dd67029 4226 ret = rtw_del_sta(dev, param);
554c0a3a 4227
2dd67029 4228 break;
554c0a3a 4229
2dd67029 4230 case RTL871X_HOSTAPD_SET_BEACON:
554c0a3a 4231
2dd67029 4232 ret = rtw_set_beacon(dev, param, p->length);
554c0a3a 4233
2dd67029 4234 break;
554c0a3a 4235
2dd67029 4236 case RTL871X_SET_ENCRYPTION:
554c0a3a 4237
2dd67029 4238 ret = rtw_set_encryption(dev, param, p->length);
554c0a3a 4239
2dd67029 4240 break;
554c0a3a 4241
2dd67029 4242 case RTL871X_HOSTAPD_GET_WPAIE_STA:
554c0a3a 4243
2dd67029 4244 ret = rtw_get_sta_wpaie(dev, param);
554c0a3a 4245
2dd67029 4246 break;
554c0a3a 4247
2dd67029 4248 case RTL871X_HOSTAPD_SET_WPS_BEACON:
554c0a3a 4249
2dd67029 4250 ret = rtw_set_wps_beacon(dev, param, p->length);
554c0a3a 4251
2dd67029 4252 break;
554c0a3a 4253
2dd67029 4254 case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
554c0a3a 4255
2dd67029 4256 ret = rtw_set_wps_probe_resp(dev, param, p->length);
554c0a3a 4257
2dd67029 4258 break;
554c0a3a 4259
2dd67029 4260 case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
554c0a3a 4261
2dd67029 4262 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
554c0a3a 4263
2dd67029 4264 break;
554c0a3a 4265
2dd67029 4266 case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
554c0a3a 4267
2dd67029 4268 ret = rtw_set_hidden_ssid(dev, param, p->length);
554c0a3a 4269
2dd67029 4270 break;
554c0a3a 4271
2dd67029 4272 case RTL871X_HOSTAPD_GET_INFO_STA:
554c0a3a 4273
2dd67029 4274 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
554c0a3a 4275
2dd67029 4276 break;
554c0a3a 4277
2dd67029 4278 case RTL871X_HOSTAPD_SET_MACADDR_ACL:
554c0a3a 4279
2dd67029 4280 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
554c0a3a 4281
2dd67029 4282 break;
554c0a3a 4283
2dd67029 4284 case RTL871X_HOSTAPD_ACL_ADD_STA:
554c0a3a 4285
2dd67029 4286 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
554c0a3a 4287
2dd67029 4288 break;
554c0a3a 4289
2dd67029 4290 case RTL871X_HOSTAPD_ACL_REMOVE_STA:
554c0a3a 4291
2dd67029 4292 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
554c0a3a 4293
2dd67029 4294 break;
554c0a3a 4295
2dd67029
PM
4296 default:
4297 DBG_871X("Unknown hostapd request: %d\n", param->cmd);
4298 ret = -EOPNOTSUPP;
4299 break;
554c0a3a
HG
4300
4301 }
4302
4303 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
4304 ret = -EFAULT;
4305
428715ba 4306 kfree(param);
554c0a3a 4307 return ret;
554c0a3a
HG
4308}
4309
4310static int rtw_wx_set_priv(struct net_device *dev,
4311 struct iw_request_info *info,
4312 union iwreq_data *awrq,
4313 char *extra)
4314{
4315
f55a6d45 4316#ifdef DEBUG_RTW_WX_SET_PRIV
554c0a3a
HG
4317 char *ext_dbg;
4318#endif
4319
4320 int ret = 0;
4321 int len = 0;
4322 char *ext;
4323
4324 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
a7dd567e 4325 struct iw_point *dwrq = (struct iw_point *)awrq;
554c0a3a
HG
4326
4327 /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n")); */
4328 if (dwrq->length == 0)
4329 return -EFAULT;
4330
4331 len = dwrq->length;
4332 if (!(ext = vmalloc(len)))
4333 return -ENOMEM;
4334
4335 if (copy_from_user(ext, dwrq->pointer, len)) {
4336 vfree(ext);
4337 return -EFAULT;
4338 }
4339
4340
4341 /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, */
4342 /* ("rtw_wx_set_priv: %s req =%s\n", */
4343 /* dev->name, ext)); */
4344
f55a6d45 4345 #ifdef DEBUG_RTW_WX_SET_PRIV
f85ac230 4346 if (!(ext_dbg = vmalloc(len))) {
554c0a3a
HG
4347 vfree(ext, len);
4348 return -ENOMEM;
4349 }
4350
4351 memcpy(ext_dbg, ext, len);
4352 #endif
4353
4354 /* added for wps2.0 @20110524 */
f85ac230 4355 if (dwrq->flags == 0x8766 && len > 8) {
554c0a3a
HG
4356 u32 cp_sz;
4357 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4358 u8 *probereq_wpsie = ext;
4359 int probereq_wpsie_len = len;
c77761d6 4360 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
554c0a3a
HG
4361
4362 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
f85ac230 4363 (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
c77761d6 4364 cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
554c0a3a 4365
f85ac230 4366 if (pmlmepriv->wps_probe_req_ie) {
554c0a3a
HG
4367 pmlmepriv->wps_probe_req_ie_len = 0;
4368 kfree(pmlmepriv->wps_probe_req_ie);
4369 pmlmepriv->wps_probe_req_ie = NULL;
4370 }
4371
4372 pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
4373 if (pmlmepriv->wps_probe_req_ie == NULL) {
4374 printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4375 ret = -EINVAL;
4376 goto FREE_EXT;
4377
4378 }
4379
4380 memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
4381 pmlmepriv->wps_probe_req_ie_len = cp_sz;
4382
4383 }
4384
4385 goto FREE_EXT;
4386
4387 }
4388
4389 if (len >= WEXT_CSCAN_HEADER_SIZE
f85ac230 4390 && !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
554c0a3a
HG
4391 ret = rtw_wx_set_scan(dev, info, awrq, ext);
4392 goto FREE_EXT;
4393 }
4394
4395FREE_EXT:
4396
4397 vfree(ext);
f55a6d45 4398 #ifdef DEBUG_RTW_WX_SET_PRIV
554c0a3a
HG
4399 vfree(ext_dbg);
4400 #endif
4401
4402 /* DBG_871X("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret =%d\n", */
4403 /* dev->name, ret); */
4404
4405 return ret;
4406
4407}
4408
4409static int rtw_pm_set(struct net_device *dev,
4410 struct iw_request_info *info,
4411 union iwreq_data *wrqu, char *extra)
4412{
4413 int ret = 0;
4414 unsigned mode = 0;
4415 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4416
4417 DBG_871X("[%s] extra = %s\n", __func__, extra);
4418
f85ac230 4419 if (!memcmp(extra, "lps =", 4)) {
554c0a3a
HG
4420 sscanf(extra+4, "%u", &mode);
4421 ret = rtw_pm_set_lps(padapter, mode);
f85ac230 4422 } else if (!memcmp(extra, "ips =", 4)) {
554c0a3a
HG
4423 sscanf(extra+4, "%u", &mode);
4424 ret = rtw_pm_set_ips(padapter, mode);
f85ac230 4425 } else {
554c0a3a
HG
4426 ret = -EINVAL;
4427 }
4428
4429 return ret;
4430}
4431
554c0a3a
HG
4432static int rtw_test(
4433 struct net_device *dev,
4434 struct iw_request_info *info,
4435 union iwreq_data *wrqu, char *extra)
4436{
4437 u32 len;
4438 u8 *pbuf, *pch;
4439 char *ptmp;
4440 u8 *delim = ",";
4441 struct adapter *padapter = rtw_netdev_priv(dev);
4442
4443
4444 DBG_871X("+%s\n", __func__);
4445 len = wrqu->data.length;
4446
2ef2b7c2 4447 pbuf = rtw_zmalloc(len);
554c0a3a
HG
4448 if (pbuf == NULL) {
4449 DBG_871X("%s: no memory!\n", __func__);
4450 return -ENOMEM;
4451 }
4452
4453 if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
4454 kfree(pbuf);
4455 DBG_871X("%s: copy from user fail!\n", __func__);
4456 return -EFAULT;
4457 }
4458 DBG_871X("%s: string =\"%s\"\n", __func__, pbuf);
4459
a7dd567e 4460 ptmp = (char *)pbuf;
554c0a3a
HG
4461 pch = strsep(&ptmp, delim);
4462 if ((pch == NULL) || (strlen(pch) == 0)) {
4463 kfree(pbuf);
4464 DBG_871X("%s: parameter error(level 1)!\n", __func__);
4465 return -EFAULT;
4466 }
4467
4468 if (strcmp(pch, "bton") == 0)
7d6a6e7b 4469 hal_btcoex_SetManualControl(padapter, false);
554c0a3a
HG
4470
4471 if (strcmp(pch, "btoff") == 0)
7d6a6e7b 4472 hal_btcoex_SetManualControl(padapter, true);
554c0a3a 4473
f85ac230 4474 if (strcmp(pch, "h2c") == 0) {
554c0a3a
HG
4475 u8 param[8];
4476 u8 count = 0;
4477 u32 tmp;
4478 u8 i;
4479 u32 pos;
4480 s32 ret;
4481
4482
4483 do {
4484 pch = strsep(&ptmp, delim);
4485 if ((pch == NULL) || (strlen(pch) == 0))
4486 break;
4487
4488 sscanf(pch, "%x", &tmp);
4489 param[count++] = (u8)tmp;
4490 } while (count < 8);
4491
4492 if (count == 0) {
4493 kfree(pbuf);
4494 DBG_871X("%s: parameter error(level 2)!\n", __func__);
4495 return -EFAULT;
4496 }
4497
4498 ret = rtw_hal_fill_h2c_cmd(padapter, param[0], count-1, &param[1]);
4499
4500 pos = sprintf(extra, "H2C ID = 0x%02x content =", param[0]);
c77761d6 4501 for (i = 1; i < count; i++)
554c0a3a 4502 pos += sprintf(extra+pos, "%02x,", param[i]);
554c0a3a
HG
4503 extra[pos] = 0;
4504 pos--;
4505 pos += sprintf(extra+pos, " %s", ret == _FAIL?"FAIL":"OK");
4506
4507 wrqu->data.length = strlen(extra) + 1;
4508 }
4509
4510 kfree(pbuf);
4511 return 0;
4512}
4513
f85ac230 4514static iw_handler rtw_handlers[] = {
554c0a3a
HG
4515 NULL, /* SIOCSIWCOMMIT */
4516 rtw_wx_get_name, /* SIOCGIWNAME */
4517 dummy, /* SIOCSIWNWID */
4518 dummy, /* SIOCGIWNWID */
4519 rtw_wx_set_freq, /* SIOCSIWFREQ */
4520 rtw_wx_get_freq, /* SIOCGIWFREQ */
4521 rtw_wx_set_mode, /* SIOCSIWMODE */
4522 rtw_wx_get_mode, /* SIOCGIWMODE */
4523 dummy, /* SIOCSIWSENS */
4524 rtw_wx_get_sens, /* SIOCGIWSENS */
4525 NULL, /* SIOCSIWRANGE */
4526 rtw_wx_get_range, /* SIOCGIWRANGE */
4527 rtw_wx_set_priv, /* SIOCSIWPRIV */
4528 NULL, /* SIOCGIWPRIV */
4529 NULL, /* SIOCSIWSTATS */
4530 NULL, /* SIOCGIWSTATS */
4531 dummy, /* SIOCSIWSPY */
4532 dummy, /* SIOCGIWSPY */
4533 NULL, /* SIOCGIWTHRSPY */
4534 NULL, /* SIOCWIWTHRSPY */
4535 rtw_wx_set_wap, /* SIOCSIWAP */
4536 rtw_wx_get_wap, /* SIOCGIWAP */
4537 rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */
4538 dummy, /* SIOCGIWAPLIST -- depricated */
4539 rtw_wx_set_scan, /* SIOCSIWSCAN */
4540 rtw_wx_get_scan, /* SIOCGIWSCAN */
4541 rtw_wx_set_essid, /* SIOCSIWESSID */
4542 rtw_wx_get_essid, /* SIOCGIWESSID */
4543 dummy, /* SIOCSIWNICKN */
4544 rtw_wx_get_nick, /* SIOCGIWNICKN */
4545 NULL, /* -- hole -- */
4546 NULL, /* -- hole -- */
4547 rtw_wx_set_rate, /* SIOCSIWRATE */
4548 rtw_wx_get_rate, /* SIOCGIWRATE */
4549 rtw_wx_set_rts, /* SIOCSIWRTS */
4550 rtw_wx_get_rts, /* SIOCGIWRTS */
4551 rtw_wx_set_frag, /* SIOCSIWFRAG */
4552 rtw_wx_get_frag, /* SIOCGIWFRAG */
4553 dummy, /* SIOCSIWTXPOW */
4554 dummy, /* SIOCGIWTXPOW */
4555 dummy, /* SIOCSIWRETRY */
4556 rtw_wx_get_retry, /* SIOCGIWRETRY */
4557 rtw_wx_set_enc, /* SIOCSIWENCODE */
4558 rtw_wx_get_enc, /* SIOCGIWENCODE */
4559 dummy, /* SIOCSIWPOWER */
4560 rtw_wx_get_power, /* SIOCGIWPOWER */
4561 NULL, /*---hole---*/
4562 NULL, /*---hole---*/
4563 rtw_wx_set_gen_ie, /* SIOCSIWGENIE */
4564 NULL, /* SIOCGWGENIE */
4565 rtw_wx_set_auth, /* SIOCSIWAUTH */
4566 NULL, /* SIOCGIWAUTH */
4567 rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
4568 NULL, /* SIOCGIWENCODEEXT */
4569 rtw_wx_set_pmkid, /* SIOCSIWPMKSA */
4570 NULL, /*---hole---*/
4571};
4572
4573static const struct iw_priv_args rtw_private_args[] = {
4574 {
4575 SIOCIWFIRSTPRIV + 0x0,
4576 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
4577 },
4578 {
4579 SIOCIWFIRSTPRIV + 0x1,
4580 IW_PRIV_TYPE_CHAR | 0x7FF,
4581 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
4582 },
4583 {
4584 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
4585 },
4586 {
4587 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
4588 },
4589 {
4590 SIOCIWFIRSTPRIV + 0x4,
4591 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
4592 },
4593 {
4594 SIOCIWFIRSTPRIV + 0x5,
4595 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
4596 },
4597 {
4598 SIOCIWFIRSTPRIV + 0x6,
4599 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
4600 },
4601/* for PLATFORM_MT53XX */
4602 {
4603 SIOCIWFIRSTPRIV + 0x7,
4604 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
4605 },
4606 {
4607 SIOCIWFIRSTPRIV + 0x8,
4608 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
4609 },
4610 {
4611 SIOCIWFIRSTPRIV + 0x9,
4612 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
4613 },
4614
4615/* for RTK_DMP_PLATFORM */
4616 {
4617 SIOCIWFIRSTPRIV + 0xA,
4618 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
4619 },
4620
4621 {
4622 SIOCIWFIRSTPRIV + 0xB,
4623 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
4624 },
4625 {
4626 SIOCIWFIRSTPRIV + 0xC,
4627 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
4628 },
4629 {
4630 SIOCIWFIRSTPRIV + 0xD,
4631 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
4632 },
4633 {
4634 SIOCIWFIRSTPRIV + 0x10,
4635 IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
4636 },
4637 {
4638 SIOCIWFIRSTPRIV + 0x11,
c77761d6 4639 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "p2p_get"
554c0a3a
HG
4640 },
4641 {
4642 SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
4643 },
4644 {
4645 SIOCIWFIRSTPRIV + 0x13,
c77761d6 4646 IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, "p2p_get2"
554c0a3a
HG
4647 },
4648 {
4649 SIOCIWFIRSTPRIV + 0x14,
4650 IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
4651 },
4652 {
4653 SIOCIWFIRSTPRIV + 0x15,
c77761d6 4654 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, "tdls_get"
554c0a3a
HG
4655 },
4656 {
4657 SIOCIWFIRSTPRIV + 0x16,
4658 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
4659 },
4660
c77761d6 4661 {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
554c0a3a
HG
4662 {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
4663 {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
4664 {
4665 SIOCIWFIRSTPRIV + 0x1D,
4666 IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
4667 },
4668
554c0a3a 4669#ifdef CONFIG_WOWLAN
c77761d6 4670 { MP_WOW_ENABLE, IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" }, /* set */
554c0a3a
HG
4671#endif
4672#ifdef CONFIG_AP_WOWLAN
c77761d6 4673 { MP_AP_WOW_ENABLE, IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, /* set */
554c0a3a
HG
4674#endif
4675};
4676
f85ac230 4677static iw_handler rtw_private_handler[] = {
554c0a3a
HG
4678 rtw_wx_write32, /* 0x00 */
4679 rtw_wx_read32, /* 0x01 */
4680 rtw_drvext_hdl, /* 0x02 */
55ecd411 4681 NULL, /* 0x03 */
554c0a3a
HG
4682
4683/* for MM DTV platform */
4684 rtw_get_ap_info, /* 0x04 */
4685
4686 rtw_set_pid, /* 0x05 */
4687 rtw_wps_start, /* 0x06 */
4688
4689/* for PLATFORM_MT53XX */
4690 rtw_wx_get_sensitivity, /* 0x07 */
4691 rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */
4692 rtw_wx_set_mtk_wps_ie, /* 0x09 */
4693
4694/* for RTK_DMP_PLATFORM */
4695/* Set Channel depend on the country code */
4696 rtw_wx_set_channel_plan, /* 0x0A */
4697
4698 rtw_dbg_port, /* 0x0B */
4699 rtw_wx_write_rf, /* 0x0C */
4700 rtw_wx_read_rf, /* 0x0D */
4701 rtw_wx_priv_null, /* 0x0E */
4702 rtw_wx_priv_null, /* 0x0F */
4703 rtw_p2p_set, /* 0x10 */
4704 rtw_p2p_get, /* 0x11 */
4705 NULL, /* 0x12 */
4706 rtw_p2p_get2, /* 0x13 */
4707
55ecd411
AS
4708 NULL, /* 0x14 */
4709 NULL, /* 0x15 */
554c0a3a
HG
4710
4711 rtw_pm_set, /* 0x16 */
4712 rtw_wx_priv_null, /* 0x17 */
4713 rtw_rereg_nd_name, /* 0x18 */
4714 rtw_wx_priv_null, /* 0x19 */
55ecd411
AS
4715 NULL, /* 0x1A */
4716 NULL, /* 0x1B */
554c0a3a
HG
4717 NULL, /* 0x1C is reserved for hostapd */
4718 rtw_test, /* 0x1D */
554c0a3a
HG
4719};
4720
4721static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
4722{
4723 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
c77761d6 4724 struct iw_statistics *piwstats = &padapter->iwstats;
554c0a3a
HG
4725 int tmp_level = 0;
4726 int tmp_qual = 0;
4727 int tmp_noise = 0;
4728
f85ac230 4729 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
554c0a3a
HG
4730 piwstats->qual.qual = 0;
4731 piwstats->qual.level = 0;
4732 piwstats->qual.noise = 0;
4733 /* DBG_871X("No link level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); */
f85ac230 4734 } else {
554c0a3a
HG
4735 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
4736 tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
4737 #else
4738 #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
4739 {
4740 /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
4741
4742 struct hal_com_data *pHal = GET_HAL_DATA(padapter);
4743
4744 tmp_level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, padapter->recvpriv.signal_strength);
4745 }
4746 #else
4747 tmp_level = padapter->recvpriv.signal_strength;
4748 #endif
4749 #endif
4750
4751 tmp_qual = padapter->recvpriv.signal_qual;
4752#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
4753 if (rtw_linked_check(padapter)) {
4754 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4755 struct noise_info info;
4756 info.bPauseDIG = true;
4757 info.IGIValue = 0x1e;
4758 info.max_time = 100;/* ms */
4759 info.chan = pmlmeext->cur_channel ;/* rtw_get_oper_ch(padapter); */
4760 rtw_ps_deny(padapter, PS_DENY_IOCTL);
4761 LeaveAllPowerSaveModeDirect(padapter);
4762
c77761d6 4763 rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false);
554c0a3a
HG
4764 /* ODM_InbandNoise_Monitor(podmpriv, true, 0x20, 100); */
4765 rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
c77761d6 4766 rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(info.chan), &(padapter->recvpriv.noise));
554c0a3a
HG
4767 DBG_871X("chan:%d, noise_level:%d\n", info.chan, padapter->recvpriv.noise);
4768 }
4769#endif
4770 tmp_noise = padapter->recvpriv.noise;
4771 DBG_871X("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise, padapter->recvpriv.rssi);
4772
4773 piwstats->qual.level = tmp_level;
4774 piwstats->qual.qual = tmp_qual;
4775 piwstats->qual.noise = tmp_noise;
4776 }
4777 piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* IW_QUAL_DBM; */
4778
4779 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
4780 piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
4781 #endif
4782
4783 return &padapter->iwstats;
4784}
4785
f85ac230 4786struct iw_handler_def rtw_handlers_def = {
554c0a3a 4787 .standard = rtw_handlers,
60db8d10 4788 .num_standard = ARRAY_SIZE(rtw_handlers),
554c0a3a
HG
4789#if defined(CONFIG_WEXT_PRIV)
4790 .private = rtw_private_handler,
4791 .private_args = (struct iw_priv_args *)rtw_private_args,
60db8d10
JL
4792 .num_private = ARRAY_SIZE(rtw_private_handler),
4793 .num_private_args = ARRAY_SIZE(rtw_private_args),
554c0a3a
HG
4794#endif
4795 .get_wireless_stats = rtw_get_wireless_stats,
4796};
4797
4798/* copy from net/wireless/wext.c start */
4799/* ---------------------------------------------------------------- */
4800/*
4801 * Calculate size of private arguments
4802 */
4803static const char iw_priv_type_size[] = {
4804 0, /* IW_PRIV_TYPE_NONE */
4805 1, /* IW_PRIV_TYPE_BYTE */
4806 1, /* IW_PRIV_TYPE_CHAR */
4807 0, /* Not defined */
4808 sizeof(__u32), /* IW_PRIV_TYPE_INT */
4809 sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
4810 sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
4811 0, /* Not defined */
4812};
4813
4814static int get_priv_size(__u16 args)
4815{
4816 int num = args & IW_PRIV_SIZE_MASK;
4817 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
4818
4819 return num * iw_priv_type_size[type];
4820}
4821/* copy from net/wireless/wext.c end */
4822
4823static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
4824{
4825 int err = 0;
4826 u8 *input = NULL;
4827 u32 input_len = 0;
4828 const char delim[] = " ";
4829 u8 *output = NULL;
4830 u32 output_len = 0;
4831 u32 count = 0;
4832 u8 *buffer = NULL;
4833 u32 buffer_len = 0;
4834 char *ptr = NULL;
4835 u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */
4836 u32 cmdlen;
4837 s32 len;
4838 u8 *extra = NULL;
4839 u32 extra_size = 0;
4840
4841 s32 k;
4842 const iw_handler *priv; /* Private ioctl */
4843 const struct iw_priv_args *priv_args; /* Private ioctl description */
554c0a3a
HG
4844 u32 num_priv_args; /* Number of descriptions */
4845 iw_handler handler;
4846 int temp;
4847 int subcmd = 0; /* sub-ioctl index */
4848 int offset = 0; /* Space for sub-ioctl index */
4849
4850 union iwreq_data wdata;
4851
4852
4853 memcpy(&wdata, wrq_data, sizeof(wdata));
4854
4855 input_len = 2048;
4856 input = rtw_zmalloc(input_len);
4857 if (NULL == input)
4858 return -ENOMEM;
4859 if (copy_from_user(input, wdata.data.pointer, input_len)) {
4860 err = -EFAULT;
4861 goto exit;
4862 }
4863 ptr = input;
4864 len = strlen(input);
4865
4866 sscanf(ptr, "%16s", cmdname);
4867 cmdlen = strlen(cmdname);
4868 DBG_8192C("%s: cmd =%s\n", __func__, cmdname);
4869
4870 /* skip command string */
4871 if (cmdlen > 0)
4872 cmdlen += 1; /* skip one space */
4873 ptr += cmdlen;
4874 len -= cmdlen;
4875 DBG_8192C("%s: parameters =%s\n", __func__, ptr);
4876
4877 priv = rtw_private_handler;
4878 priv_args = rtw_private_args;
60db8d10 4879 num_priv_args = ARRAY_SIZE(rtw_private_args);
554c0a3a
HG
4880
4881 if (num_priv_args == 0) {
4882 err = -EOPNOTSUPP;
4883 goto exit;
4884 }
4885
4886 /* Search the correct ioctl */
4887 k = -1;
4888 while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
4889
4890 /* If not found... */
4891 if (k == num_priv_args) {
4892 err = -EOPNOTSUPP;
4893 goto exit;
4894 }
4895
4896 /* Watch out for sub-ioctls ! */
f85ac230 4897 if (priv_args[k].cmd < SIOCDEVPRIVATE) {
554c0a3a
HG
4898 int j = -1;
4899
4900 /* Find the matching *real* ioctl */
4901 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
4902 (priv_args[j].set_args != priv_args[k].set_args) ||
4903 (priv_args[j].get_args != priv_args[k].get_args)));
4904
4905 /* If not found... */
4906 if (j == num_priv_args) {
4907 err = -EINVAL;
4908 goto exit;
4909 }
4910
4911 /* Save sub-ioctl number */
4912 subcmd = priv_args[k].cmd;
4913 /* Reserve one int (simplify alignment issues) */
4914 offset = sizeof(__u32);
4915 /* Use real ioctl definition from now on */
4916 k = j;
4917 }
4918
4919 buffer = rtw_zmalloc(4096);
4920 if (NULL == buffer) {
4921 err = -ENOMEM;
4922 goto exit;
4923 }
4924
4925 /* If we have to set some data */
4926 if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
f85ac230 4927 (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
554c0a3a
HG
4928 u8 *str;
4929
f85ac230 4930 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
2dd67029
PM
4931 case IW_PRIV_TYPE_BYTE:
4932 /* Fetch args */
4933 count = 0;
4934 do {
4935 str = strsep(&ptr, delim);
4936 if (NULL == str) break;
4937 sscanf(str, "%i", &temp);
4938 buffer[count++] = (u8)temp;
4939 } while (1);
4940 buffer_len = count;
4941
4942 /* Number of args to fetch */
4943 wdata.data.length = count;
4944 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
4945 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
554c0a3a 4946
2dd67029 4947 break;
554c0a3a 4948
2dd67029
PM
4949 case IW_PRIV_TYPE_INT:
4950 /* Fetch args */
4951 count = 0;
4952 do {
4953 str = strsep(&ptr, delim);
4954 if (NULL == str) break;
4955 sscanf(str, "%i", &temp);
a7dd567e 4956 ((s32 *)buffer)[count++] = (s32)temp;
2dd67029
PM
4957 } while (1);
4958 buffer_len = count * sizeof(s32);
4959
4960 /* Number of args to fetch */
4961 wdata.data.length = count;
4962 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
4963 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
554c0a3a 4964
2dd67029 4965 break;
554c0a3a 4966
2dd67029
PM
4967 case IW_PRIV_TYPE_CHAR:
4968 if (len > 0) {
4969 /* Size of the string to fetch */
4970 wdata.data.length = len;
4971 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
4972 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
554c0a3a 4973
2dd67029
PM
4974 /* Fetch string */
4975 memcpy(buffer, ptr, wdata.data.length);
4976 } else {
4977 wdata.data.length = 1;
4978 buffer[0] = '\0';
4979 }
4980 buffer_len = wdata.data.length;
4981 break;
554c0a3a 4982
2dd67029
PM
4983 default:
4984 DBG_8192C("%s: Not yet implemented...\n", __func__);
4985 err = -1;
4986 goto exit;
554c0a3a
HG
4987 }
4988
4989 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
f85ac230 4990 (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
554c0a3a
HG
4991 DBG_8192C("%s: The command %s needs exactly %d argument(s)...\n",
4992 __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
4993 err = -EINVAL;
4994 goto exit;
4995 }
f85ac230 4996 } else { /* if args to set */
554c0a3a
HG
4997 wdata.data.length = 0L;
4998 }
4999
5000 /* Those two tests are important. They define how the driver
5001 * will have to handle the data */
5002 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
f85ac230 5003 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
554c0a3a
HG
5004 /* First case : all SET args fit within wrq */
5005 if (offset)
5006 wdata.mode = subcmd;
5007 memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
f85ac230 5008 } else {
554c0a3a
HG
5009 if ((priv_args[k].set_args == 0) &&
5010 (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
f85ac230 5011 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
554c0a3a
HG
5012 /* Second case : no SET args, GET args fit within wrq */
5013 if (offset)
5014 wdata.mode = subcmd;
f85ac230 5015 } else {
554c0a3a
HG
5016 /* Third case : args won't fit in wrq, or variable number of args */
5017 if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
5018 err = -EFAULT;
5019 goto exit;
5020 }
5021 wdata.data.flags = subcmd;
5022 }
5023 }
5024
5025 kfree(input);
5026 input = NULL;
5027
5028 extra_size = 0;
f85ac230 5029 if (IW_IS_SET(priv_args[k].cmd)) {
554c0a3a
HG
5030 /* Size of set arguments */
5031 extra_size = get_priv_size(priv_args[k].set_args);
5032
5033 /* Does it fits in iwr ? */
5034 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
5035 ((extra_size + offset) <= IFNAMSIZ))
5036 extra_size = 0;
5037 } else {
5038 /* Size of get arguments */
5039 extra_size = get_priv_size(priv_args[k].get_args);
5040
5041 /* Does it fits in iwr ? */
5042 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
5043 (extra_size <= IFNAMSIZ))
5044 extra_size = 0;
5045 }
5046
5047 if (extra_size == 0) {
5048 extra = (u8 *)&wdata;
5049 kfree(buffer);
5050 buffer = NULL;
5051 } else
5052 extra = buffer;
5053
5054 handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
5055 err = handler(dev, NULL, &wdata, extra);
5056
5057 /* If we have to get some data */
5058 if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
f85ac230 5059 (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
554c0a3a
HG
5060 int j;
5061 int n = 0; /* number of args */
5062 u8 str[20] = {0};
5063
5064 /* Check where is the returned data */
5065 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
5066 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
5067 n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
5068 else
5069 n = wdata.data.length;
5070
5071 output = rtw_zmalloc(4096);
5072 if (NULL == output) {
5073 err = -ENOMEM;
5074 goto exit;
5075 }
5076
f85ac230 5077 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
2dd67029
PM
5078 case IW_PRIV_TYPE_BYTE:
5079 /* Display args */
5080 for (j = 0; j < n; j++) {
5081 sprintf(str, "%d ", extra[j]);
5082 len = strlen(str);
5083 output_len = strlen(output);
5084 if ((output_len + len + 1) > 4096) {
5085 err = -E2BIG;
5086 goto exit;
554c0a3a 5087 }
2dd67029
PM
5088 memcpy(output+output_len, str, len);
5089 }
5090 break;
554c0a3a 5091
2dd67029
PM
5092 case IW_PRIV_TYPE_INT:
5093 /* Display args */
5094 for (j = 0; j < n; j++) {
a7dd567e 5095 sprintf(str, "%d ", ((__s32 *)extra)[j]);
2dd67029
PM
5096 len = strlen(str);
5097 output_len = strlen(output);
5098 if ((output_len + len + 1) > 4096) {
5099 err = -E2BIG;
5100 goto exit;
554c0a3a 5101 }
2dd67029
PM
5102 memcpy(output+output_len, str, len);
5103 }
5104 break;
554c0a3a 5105
2dd67029
PM
5106 case IW_PRIV_TYPE_CHAR:
5107 /* Display args */
5108 memcpy(output, extra, n);
5109 break;
554c0a3a 5110
2dd67029
PM
5111 default:
5112 DBG_8192C("%s: Not yet implemented...\n", __func__);
5113 err = -1;
5114 goto exit;
554c0a3a
HG
5115 }
5116
5117 output_len = strlen(output) + 1;
5118 wrq_data->data.length = output_len;
5119 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
5120 err = -EFAULT;
5121 goto exit;
5122 }
f85ac230 5123 } else { /* if args to set */
554c0a3a
HG
5124 wrq_data->data.length = 0;
5125 }
5126
5127exit:
7ad61a38
AP
5128 kfree(input);
5129 kfree(buffer);
5130 kfree(output);
554c0a3a
HG
5131
5132 return err;
5133}
5134
5135int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
5136{
5137 struct iwreq *wrq = (struct iwreq *)rq;
5138 int ret = 0;
5139
f85ac230 5140 switch (cmd) {
2dd67029
PM
5141 case RTL_IOCTL_WPA_SUPPLICANT:
5142 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
5143 break;
5144 case RTL_IOCTL_HOSTAPD:
5145 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
5146 break;
5147 case SIOCDEVPRIVATE:
5148 ret = rtw_ioctl_wext_private(dev, &wrq->u);
5149 break;
5150 default:
5151 ret = -EOPNOTSUPP;
5152 break;
554c0a3a
HG
5153 }
5154
5155 return ret;
5156}