Staging: rtl8712: Clean up tests if NULL returned on failure
[deliverable/linux.git] / drivers / staging / rtl8712 / rtl871x_ioctl_linux.c
1 /******************************************************************************
2 * rtl871x_ioctl_linux.c
3 *
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
22 *
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
26 *
27 ******************************************************************************/
28
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
31
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.h"
36 #include "wifi.h"
37 #include "rtl871x_mlme.h"
38 #include "rtl871x_ioctl.h"
39 #include "rtl871x_ioctl_set.h"
40 #include "rtl871x_mp_ioctl.h"
41 #include "mlme_osdep.h"
42 #include <linux/wireless.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/io.h>
46 #include <linux/semaphore.h>
47 #include <net/iw_handler.h>
48 #include <linux/if_arp.h>
49 #include <linux/etherdevice.h>
50
51
52 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
53
54 #define SCAN_ITEM_SIZE 768
55 #define MAX_CUSTOM_LEN 64
56 #define RATE_COUNT 4
57
58
59 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
60 6000000, 9000000, 12000000, 18000000,
61 24000000, 36000000, 48000000, 54000000};
62
63 static const long ieee80211_wlan_frequencies[] = {
64 2412, 2417, 2422, 2427,
65 2432, 2437, 2442, 2447,
66 2452, 2457, 2462, 2467,
67 2472, 2484
68 };
69
70 static const char * const iw_operation_mode[] = {
71 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
72 "Monitor"
73 };
74
75 void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
76 {
77 union iwreq_data wrqu;
78 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
79
80 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
81 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
82 ETH_ALEN);
83 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
84 }
85
86 void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
87 {
88 union iwreq_data wrqu;
89
90 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
91 eth_zero_addr(wrqu.ap_addr.sa_data);
92 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
93 }
94
95 static inline void handle_pairwise_key(struct sta_info *psta,
96 struct ieee_param *param,
97 struct _adapter *padapter)
98 {
99 /* pairwise key */
100 memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
101 (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
102 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
103 memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
104 key[16]), 8);
105 memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
106 key[24]), 8);
107 padapter->securitypriv. busetkipkey = false;
108 mod_timer(&padapter->securitypriv.tkip_timer,
109 jiffies + msecs_to_jiffies(50));
110 }
111 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
112 }
113
114 static inline void handle_group_key(struct ieee_param *param,
115 struct _adapter *padapter)
116 {
117 if (param->u.crypt.idx > 0 &&
118 param->u.crypt.idx < 3) {
119 /* group key idx is 1 or 2 */
120 memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
121 idx - 1].skey, param->u.crypt.key,
122 (param->u.crypt.key_len > 16 ? 16 :
123 param->u.crypt.key_len));
124 memcpy(padapter->securitypriv.XGrptxmickey[param->
125 u.crypt.idx - 1].skey, &(param->u.crypt.key[16]), 8);
126 memcpy(padapter->securitypriv. XGrprxmickey[param->
127 u.crypt.idx - 1].skey, &(param->u.crypt.key[24]), 8);
128 padapter->securitypriv.binstallGrpkey = true;
129 r8712_set_key(padapter, &padapter->securitypriv,
130 param->u.crypt.idx);
131 if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
132 if (padapter->registrypriv.power_mgnt != padapter->
133 pwrctrlpriv.pwr_mode)
134 mod_timer(&padapter->mlmepriv.dhcp_timer,
135 jiffies + msecs_to_jiffies(60000));
136 }
137 }
138 }
139
140 static noinline_for_stack char *translate_scan(struct _adapter *padapter,
141 struct iw_request_info *info,
142 struct wlan_network *pnetwork,
143 char *start, char *stop)
144 {
145 struct iw_event iwe;
146 struct ieee80211_ht_cap *pht_capie;
147 char *current_val;
148 s8 *p;
149 u32 i = 0, ht_ielen = 0;
150 u16 cap, ht_cap = false, mcs_rate;
151 u8 rssi;
152
153 if ((pnetwork->network.Configuration.DSConfig < 1) ||
154 (pnetwork->network.Configuration.DSConfig > 14)) {
155 if (pnetwork->network.Configuration.DSConfig < 1)
156 pnetwork->network.Configuration.DSConfig = 1;
157 else
158 pnetwork->network.Configuration.DSConfig = 14;
159 }
160 /* AP MAC address */
161 iwe.cmd = SIOCGIWAP;
162 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
163 ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
164 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
165 /* Add the ESSID */
166 iwe.cmd = SIOCGIWESSID;
167 iwe.u.data.flags = 1;
168 iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
169 start = iwe_stream_add_point(info, start, stop, &iwe,
170 pnetwork->network.Ssid.Ssid);
171 /* parsing HT_CAP_IE */
172 p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
173 &ht_ielen, pnetwork->network.IELength - 12);
174 if (p && ht_ielen > 0) {
175 ht_cap = true;
176 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
177 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
178 }
179 /* Add the protocol name */
180 iwe.cmd = SIOCGIWNAME;
181 if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
182 if (ht_cap)
183 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
184 else
185 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
186 } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
187 if (ht_cap)
188 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
189 else
190 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
191 } else {
192 if (ht_cap)
193 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
194 else
195 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
196 }
197 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
198 /* Add mode */
199 iwe.cmd = SIOCGIWMODE;
200 memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
201 2);
202 cap = le16_to_cpu(cap);
203 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
204 if (cap & WLAN_CAPABILITY_BSS)
205 iwe.u.mode = (u32)IW_MODE_MASTER;
206 else
207 iwe.u.mode = (u32)IW_MODE_ADHOC;
208 start = iwe_stream_add_event(info, start, stop, &iwe,
209 IW_EV_UINT_LEN);
210 }
211 /* Add frequency/channel */
212 iwe.cmd = SIOCGIWFREQ;
213 {
214 /* check legal index */
215 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
216
217 if (dsconfig >= 1 && dsconfig <= sizeof(
218 ieee80211_wlan_frequencies) / sizeof(long))
219 iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
220 pnetwork->network.Configuration.
221 DSConfig - 1] * 100000);
222 else
223 iwe.u.freq.m = 0;
224 }
225 iwe.u.freq.e = (s16)1;
226 iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
227 start = iwe_stream_add_event(info, start, stop, &iwe,
228 IW_EV_FREQ_LEN);
229 /* Add encryption capability */
230 iwe.cmd = SIOCGIWENCODE;
231 if (cap & WLAN_CAPABILITY_PRIVACY)
232 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
233 IW_ENCODE_NOKEY);
234 else
235 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
236 iwe.u.data.length = (u16)0;
237 start = iwe_stream_add_point(info, start, stop, &iwe,
238 pnetwork->network.Ssid.Ssid);
239 /*Add basic and extended rates */
240 current_val = start + iwe_stream_lcp_len(info);
241 iwe.cmd = SIOCGIWRATE;
242 iwe.u.bitrate.fixed = 0;
243 iwe.u.bitrate.disabled = 0;
244 iwe.u.bitrate.value = 0;
245 i = 0;
246 while (pnetwork->network.rates[i] != 0) {
247 /* Bit rate given in 500 kb/s units */
248 iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
249 0x7F) * 500000;
250 current_val = iwe_stream_add_value(info, start, current_val,
251 stop, &iwe, IW_EV_PARAM_LEN);
252 }
253 /* Check if we added any event */
254 if ((current_val - start) > iwe_stream_lcp_len(info))
255 start = current_val;
256 /* parsing WPA/WPA2 IE */
257 {
258 u8 buf[MAX_WPA_IE_LEN];
259 u8 wpa_ie[255], rsn_ie[255];
260 u16 wpa_len = 0, rsn_len = 0;
261 int n;
262
263 r8712_get_sec_ie(pnetwork->network.IEs,
264 pnetwork->network.IELength, rsn_ie, &rsn_len,
265 wpa_ie, &wpa_len);
266 if (wpa_len > 0) {
267 memset(buf, 0, MAX_WPA_IE_LEN);
268 n = sprintf(buf, "wpa_ie=");
269 for (i = 0; i < wpa_len; i++) {
270 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
271 "%02x", wpa_ie[i]);
272 if (n >= MAX_WPA_IE_LEN)
273 break;
274 }
275 memset(&iwe, 0, sizeof(iwe));
276 iwe.cmd = IWEVCUSTOM;
277 iwe.u.data.length = (u16)strlen(buf);
278 start = iwe_stream_add_point(info, start, stop,
279 &iwe, buf);
280 memset(&iwe, 0, sizeof(iwe));
281 iwe.cmd = IWEVGENIE;
282 iwe.u.data.length = (u16)wpa_len;
283 start = iwe_stream_add_point(info, start, stop,
284 &iwe, wpa_ie);
285 }
286 if (rsn_len > 0) {
287 memset(buf, 0, MAX_WPA_IE_LEN);
288 n = sprintf(buf, "rsn_ie=");
289 for (i = 0; i < rsn_len; i++) {
290 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
291 "%02x", rsn_ie[i]);
292 if (n >= MAX_WPA_IE_LEN)
293 break;
294 }
295 memset(&iwe, 0, sizeof(iwe));
296 iwe.cmd = IWEVCUSTOM;
297 iwe.u.data.length = strlen(buf);
298 start = iwe_stream_add_point(info, start, stop,
299 &iwe, buf);
300 memset(&iwe, 0, sizeof(iwe));
301 iwe.cmd = IWEVGENIE;
302 iwe.u.data.length = rsn_len;
303 start = iwe_stream_add_point(info, start, stop, &iwe,
304 rsn_ie);
305 }
306 }
307
308 { /* parsing WPS IE */
309 u8 wps_ie[512];
310 uint wps_ielen;
311
312 if (r8712_get_wps_ie(pnetwork->network.IEs,
313 pnetwork->network.IELength,
314 wps_ie, &wps_ielen)) {
315 if (wps_ielen > 2) {
316 iwe.cmd = IWEVGENIE;
317 iwe.u.data.length = (u16)wps_ielen;
318 start = iwe_stream_add_point(info, start, stop,
319 &iwe, wps_ie);
320 }
321 }
322 }
323 /* Add quality statistics */
324 iwe.cmd = IWEVQUAL;
325 rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
326 /* we only update signal_level (signal strength) that is rssi. */
327 iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
328 IW_QUAL_NOISE_INVALID);
329 iwe.u.qual.level = rssi; /* signal strength */
330 iwe.u.qual.qual = 0; /* signal quality */
331 iwe.u.qual.noise = 0; /* noise level */
332 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
333 /* how to translate rssi to ?% */
334 return start;
335 }
336
337 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
338 {
339 struct _adapter *padapter = netdev_priv(dev);
340 int ret = 0;
341
342 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
343 padapter->securitypriv.ndisencryptstatus =
344 Ndis802_11Encryption1Enabled;
345 padapter->securitypriv.ndisauthtype =
346 Ndis802_11AuthModeAutoSwitch;
347 padapter->securitypriv.AuthAlgrthm = 3;
348 } else if (value & AUTH_ALG_SHARED_KEY) {
349 padapter->securitypriv.ndisencryptstatus =
350 Ndis802_11Encryption1Enabled;
351 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
352 padapter->securitypriv.AuthAlgrthm = 1;
353 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
354 if (padapter->securitypriv.ndisauthtype <
355 Ndis802_11AuthModeWPAPSK) {
356 padapter->securitypriv.ndisauthtype =
357 Ndis802_11AuthModeOpen;
358 padapter->securitypriv.AuthAlgrthm = 0;
359 }
360 } else {
361 ret = -EINVAL;
362 }
363 return ret;
364 }
365
366 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
367 u32 param_len)
368 {
369 int ret = 0;
370 u32 wep_key_idx, wep_key_len = 0;
371 struct NDIS_802_11_WEP *pwep = NULL;
372 struct _adapter *padapter = netdev_priv(dev);
373 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
374 struct security_priv *psecuritypriv = &padapter->securitypriv;
375
376 param->u.crypt.err = 0;
377 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
378 if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
379 param->u.crypt.key_len)
380 return -EINVAL;
381 if (is_broadcast_ether_addr(param->sta_addr)) {
382 if (param->u.crypt.idx >= WEP_KEYS) {
383 /* for large key indices, set the default (0) */
384 param->u.crypt.idx = 0;
385 }
386 } else {
387 return -EINVAL;
388 }
389 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
390 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
391 padapter->securitypriv.ndisencryptstatus =
392 Ndis802_11Encryption1Enabled;
393 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
394 padapter->securitypriv.XGrpPrivacy = _WEP40_;
395 wep_key_idx = param->u.crypt.idx;
396 wep_key_len = param->u.crypt.key_len;
397 if (wep_key_idx >= WEP_KEYS)
398 wep_key_idx = 0;
399 if (wep_key_len > 0) {
400 wep_key_len = wep_key_len <= 5 ? 5 : 13;
401 pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
402 if (pwep == NULL)
403 return -ENOMEM;
404 pwep->KeyLength = wep_key_len;
405 pwep->Length = wep_key_len +
406 FIELD_OFFSET(struct NDIS_802_11_WEP,
407 KeyMaterial);
408 if (wep_key_len == 13) {
409 padapter->securitypriv.PrivacyAlgrthm =
410 _WEP104_;
411 padapter->securitypriv.XGrpPrivacy =
412 _WEP104_;
413 }
414 } else {
415 return -EINVAL;
416 }
417 pwep->KeyIndex = wep_key_idx;
418 pwep->KeyIndex |= 0x80000000;
419 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
420 if (param->u.crypt.set_tx) {
421 if (r8712_set_802_11_add_wep(padapter, pwep) ==
422 (u8)_FAIL)
423 ret = -EOPNOTSUPP;
424 } else {
425 /* don't update "psecuritypriv->PrivacyAlgrthm" and
426 * "psecuritypriv->PrivacyKeyIndex=keyid", but can
427 * r8712_set_key to fw/cam
428 */
429 if (wep_key_idx >= WEP_KEYS) {
430 ret = -EOPNOTSUPP;
431 goto exit;
432 }
433 memcpy(&(psecuritypriv->DefKey[wep_key_idx].
434 skey[0]), pwep->KeyMaterial,
435 pwep->KeyLength);
436 psecuritypriv->DefKeylen[wep_key_idx] =
437 pwep->KeyLength;
438 r8712_set_key(padapter, psecuritypriv, wep_key_idx);
439 }
440 goto exit;
441 }
442 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
443 struct sta_info *psta, *pbcmc_sta;
444 struct sta_priv *pstapriv = &padapter->stapriv;
445
446 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
447 WIFI_MP_STATE)) { /* sta mode */
448 psta = r8712_get_stainfo(pstapriv,
449 get_bssid(pmlmepriv));
450 if (psta) {
451 psta->ieee8021x_blocked = false;
452 if ((padapter->securitypriv.ndisencryptstatus ==
453 Ndis802_11Encryption2Enabled) ||
454 (padapter->securitypriv.ndisencryptstatus ==
455 Ndis802_11Encryption3Enabled))
456 psta->XPrivacy = padapter->
457 securitypriv.PrivacyAlgrthm;
458 if (param->u.crypt.set_tx == 1)
459 handle_pairwise_key(psta, param,
460 padapter);
461 else /* group key */
462 handle_group_key(param, padapter);
463 }
464 pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
465 if (pbcmc_sta) {
466 pbcmc_sta->ieee8021x_blocked = false;
467 if ((padapter->securitypriv.ndisencryptstatus ==
468 Ndis802_11Encryption2Enabled) ||
469 (padapter->securitypriv.ndisencryptstatus ==
470 Ndis802_11Encryption3Enabled))
471 pbcmc_sta->XPrivacy =
472 padapter->securitypriv.
473 PrivacyAlgrthm;
474 }
475 }
476 }
477 exit:
478 kfree(pwep);
479 return ret;
480 }
481
482 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
483 unsigned short ielen)
484 {
485 u8 *buf = NULL;
486 int group_cipher = 0, pairwise_cipher = 0;
487 int ret = 0;
488
489 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
490 return -EINVAL;
491 if (ielen) {
492 buf = kmemdup(pie, ielen, GFP_ATOMIC);
493 if (buf == NULL)
494 return -ENOMEM;
495 if (ielen < RSN_HEADER_LEN) {
496 ret = -EINVAL;
497 goto exit;
498 }
499 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
500 &pairwise_cipher) == _SUCCESS) {
501 padapter->securitypriv.AuthAlgrthm = 2;
502 padapter->securitypriv.ndisauthtype =
503 Ndis802_11AuthModeWPAPSK;
504 }
505 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
506 &pairwise_cipher) == _SUCCESS) {
507 padapter->securitypriv.AuthAlgrthm = 2;
508 padapter->securitypriv.ndisauthtype =
509 Ndis802_11AuthModeWPA2PSK;
510 }
511 switch (group_cipher) {
512 case WPA_CIPHER_NONE:
513 padapter->securitypriv.XGrpPrivacy =
514 _NO_PRIVACY_;
515 padapter->securitypriv.ndisencryptstatus =
516 Ndis802_11EncryptionDisabled;
517 break;
518 case WPA_CIPHER_WEP40:
519 padapter->securitypriv.XGrpPrivacy = _WEP40_;
520 padapter->securitypriv.ndisencryptstatus =
521 Ndis802_11Encryption1Enabled;
522 break;
523 case WPA_CIPHER_TKIP:
524 padapter->securitypriv.XGrpPrivacy = _TKIP_;
525 padapter->securitypriv.ndisencryptstatus =
526 Ndis802_11Encryption2Enabled;
527 break;
528 case WPA_CIPHER_CCMP:
529 padapter->securitypriv.XGrpPrivacy = _AES_;
530 padapter->securitypriv.ndisencryptstatus =
531 Ndis802_11Encryption3Enabled;
532 break;
533 case WPA_CIPHER_WEP104:
534 padapter->securitypriv.XGrpPrivacy = _WEP104_;
535 padapter->securitypriv.ndisencryptstatus =
536 Ndis802_11Encryption1Enabled;
537 break;
538 }
539 switch (pairwise_cipher) {
540 case WPA_CIPHER_NONE:
541 padapter->securitypriv.PrivacyAlgrthm =
542 _NO_PRIVACY_;
543 padapter->securitypriv.ndisencryptstatus =
544 Ndis802_11EncryptionDisabled;
545 break;
546 case WPA_CIPHER_WEP40:
547 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
548 padapter->securitypriv.ndisencryptstatus =
549 Ndis802_11Encryption1Enabled;
550 break;
551 case WPA_CIPHER_TKIP:
552 padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
553 padapter->securitypriv.ndisencryptstatus =
554 Ndis802_11Encryption2Enabled;
555 break;
556 case WPA_CIPHER_CCMP:
557 padapter->securitypriv.PrivacyAlgrthm = _AES_;
558 padapter->securitypriv.ndisencryptstatus =
559 Ndis802_11Encryption3Enabled;
560 break;
561 case WPA_CIPHER_WEP104:
562 padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
563 padapter->securitypriv.ndisencryptstatus =
564 Ndis802_11Encryption1Enabled;
565 break;
566 }
567 padapter->securitypriv.wps_phase = false;
568 {/* set wps_ie */
569 u16 cnt = 0;
570 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
571
572 while (cnt < ielen) {
573 eid = buf[cnt];
574
575 if ((eid == _VENDOR_SPECIFIC_IE_) &&
576 (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
577 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
578 padapter->securitypriv.wps_ie_len =
579 ((buf[cnt + 1] + 2) <
580 (MAX_WPA_IE_LEN << 2)) ?
581 (buf[cnt + 1] + 2) :
582 (MAX_WPA_IE_LEN << 2);
583 memcpy(padapter->securitypriv.wps_ie,
584 &buf[cnt],
585 padapter->securitypriv.wps_ie_len);
586 padapter->securitypriv.wps_phase =
587 true;
588 netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
589 cnt += buf[cnt + 1] + 2;
590 break;
591 } else {
592 cnt += buf[cnt + 1] + 2;
593 }
594 }
595 }
596 }
597 exit:
598 kfree(buf);
599 return ret;
600 }
601
602 static int r8711_wx_get_name(struct net_device *dev,
603 struct iw_request_info *info,
604 union iwreq_data *wrqu, char *extra)
605 {
606 struct _adapter *padapter = netdev_priv(dev);
607 u32 ht_ielen = 0;
608 char *p;
609 u8 ht_cap = false;
610 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
611 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
612 u8 *prates;
613
614 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ==
615 true) {
616 /* parsing HT_CAP_IE */
617 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
618 &ht_ielen, pcur_bss->IELength - 12);
619 if (p && ht_ielen > 0)
620 ht_cap = true;
621 prates = pcur_bss->rates;
622 if (r8712_is_cckratesonly_included(prates)) {
623 if (ht_cap)
624 snprintf(wrqu->name, IFNAMSIZ,
625 "IEEE 802.11bn");
626 else
627 snprintf(wrqu->name, IFNAMSIZ,
628 "IEEE 802.11b");
629 } else if (r8712_is_cckrates_included(prates)) {
630 if (ht_cap)
631 snprintf(wrqu->name, IFNAMSIZ,
632 "IEEE 802.11bgn");
633 else
634 snprintf(wrqu->name, IFNAMSIZ,
635 "IEEE 802.11bg");
636 } else {
637 if (ht_cap)
638 snprintf(wrqu->name, IFNAMSIZ,
639 "IEEE 802.11gn");
640 else
641 snprintf(wrqu->name, IFNAMSIZ,
642 "IEEE 802.11g");
643 }
644 } else {
645 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
646 }
647 return 0;
648 }
649
650 static const long frequency_list[] = {
651 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
652 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
653 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
654 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
655 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
656 5825
657 };
658
659 static int r8711_wx_set_freq(struct net_device *dev,
660 struct iw_request_info *info,
661 union iwreq_data *wrqu, char *extra)
662 {
663 struct _adapter *padapter = netdev_priv(dev);
664 struct iw_freq *fwrq = &wrqu->freq;
665 int rc = 0;
666
667 /* If setting by frequency, convert to a channel */
668 if ((fwrq->e == 1) &&
669 (fwrq->m >= (int) 2.412e8) &&
670 (fwrq->m <= (int) 2.487e8)) {
671 int f = fwrq->m / 100000;
672 int c = 0;
673
674 while ((c < 14) && (f != frequency_list[c]))
675 c++;
676 fwrq->e = 0;
677 fwrq->m = c + 1;
678 }
679 /* Setting by channel number */
680 if ((fwrq->m > 14) || (fwrq->e > 0)) {
681 rc = -EOPNOTSUPP;
682 } else {
683 int channel = fwrq->m;
684
685 if ((channel < 1) || (channel > 14)) {
686 rc = -EINVAL;
687 } else {
688 /* Yes ! We can set it !!! */
689 padapter->registrypriv.channel = channel;
690 }
691 }
692 return rc;
693 }
694
695 static int r8711_wx_get_freq(struct net_device *dev,
696 struct iw_request_info *info,
697 union iwreq_data *wrqu, char *extra)
698 {
699 struct _adapter *padapter = netdev_priv(dev);
700 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
701 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
702
703 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
704 wrqu->freq.m = ieee80211_wlan_frequencies[
705 pcur_bss->Configuration.DSConfig - 1] * 100000;
706 wrqu->freq.e = 1;
707 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
708 } else {
709 return -ENOLINK;
710 }
711 return 0;
712 }
713
714 static int r8711_wx_set_mode(struct net_device *dev,
715 struct iw_request_info *a,
716 union iwreq_data *wrqu, char *b)
717 {
718 struct _adapter *padapter = netdev_priv(dev);
719 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
720
721 switch (wrqu->mode) {
722 case IW_MODE_AUTO:
723 networkType = Ndis802_11AutoUnknown;
724 break;
725 case IW_MODE_ADHOC:
726 networkType = Ndis802_11IBSS;
727 break;
728 case IW_MODE_MASTER:
729 networkType = Ndis802_11APMode;
730 break;
731 case IW_MODE_INFRA:
732 networkType = Ndis802_11Infrastructure;
733 break;
734 default:
735 return -EINVAL;
736 }
737 if (Ndis802_11APMode == networkType)
738 r8712_setopmode_cmd(padapter, networkType);
739 else
740 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
741
742 r8712_set_802_11_infrastructure_mode(padapter, networkType);
743 return 0;
744 }
745
746 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
747 union iwreq_data *wrqu, char *b)
748 {
749 struct _adapter *padapter = netdev_priv(dev);
750 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
751
752 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
753 wrqu->mode = IW_MODE_INFRA;
754 else if (check_fwstate(pmlmepriv,
755 WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
756 wrqu->mode = IW_MODE_ADHOC;
757 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
758 wrqu->mode = IW_MODE_MASTER;
759 else
760 wrqu->mode = IW_MODE_AUTO;
761 return 0;
762 }
763
764 static int r871x_wx_set_pmkid(struct net_device *dev,
765 struct iw_request_info *a,
766 union iwreq_data *wrqu, char *extra)
767 {
768 struct _adapter *padapter = netdev_priv(dev);
769 struct security_priv *psecuritypriv = &padapter->securitypriv;
770 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
771 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
772 u8 strIssueBssid[ETH_ALEN] = {0x00};
773 u8 j, blInserted = false;
774 int intReturn = false;
775
776 /*
777 * There are the BSSID information in the bssid.sa_data array.
778 * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
779 * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
780 * wpa_supplicant wants to add a PMKID/BSSID to driver.
781 * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
782 * remove a PMKID/BSSID from driver.
783 */
784 if (pPMK == NULL)
785 return -EINVAL;
786 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
787 switch (pPMK->cmd) {
788 case IW_PMKSA_ADD:
789 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
790 return intReturn;
791 intReturn = true;
792 blInserted = false;
793 /* overwrite PMKID */
794 for (j = 0; j < NUM_PMKID_CACHE; j++) {
795 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
796 strIssueBssid, ETH_ALEN)) {
797 /* BSSID is matched, the same AP => rewrite
798 * with new PMKID.
799 */
800 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
801 __func__);
802 memcpy(psecuritypriv->PMKIDList[j].PMKID,
803 pPMK->pmkid, IW_PMKID_LEN);
804 psecuritypriv->PMKIDList[j].bUsed = true;
805 psecuritypriv->PMKIDIndex = j + 1;
806 blInserted = true;
807 break;
808 }
809 }
810 if (!blInserted) {
811 /* Find a new entry */
812 netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
813 __func__, psecuritypriv->PMKIDIndex);
814 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
815 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
816 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
817 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
818 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
819 bUsed = true;
820 psecuritypriv->PMKIDIndex++;
821 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
822 psecuritypriv->PMKIDIndex = 0;
823 }
824 break;
825 case IW_PMKSA_REMOVE:
826 intReturn = true;
827 for (j = 0; j < NUM_PMKID_CACHE; j++) {
828 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
829 strIssueBssid, ETH_ALEN)) {
830 /* BSSID is matched, the same AP => Remove
831 * this PMKID information and reset it.
832 */
833 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
834 psecuritypriv->PMKIDList[j].bUsed = false;
835 break;
836 }
837 }
838 break;
839 case IW_PMKSA_FLUSH:
840 memset(psecuritypriv->PMKIDList, 0,
841 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
842 psecuritypriv->PMKIDIndex = 0;
843 intReturn = true;
844 break;
845 default:
846 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
847 intReturn = false;
848 break;
849 }
850 return intReturn;
851 }
852
853 static int r8711_wx_get_sens(struct net_device *dev,
854 struct iw_request_info *info,
855 union iwreq_data *wrqu, char *extra)
856 {
857 wrqu->sens.value = 0;
858 wrqu->sens.fixed = 0; /* no auto select */
859 wrqu->sens.disabled = 1;
860 return 0;
861 }
862
863 static int r8711_wx_get_range(struct net_device *dev,
864 struct iw_request_info *info,
865 union iwreq_data *wrqu, char *extra)
866 {
867 struct iw_range *range = (struct iw_range *)extra;
868 u16 val;
869 int i;
870
871 wrqu->data.length = sizeof(*range);
872 memset(range, 0, sizeof(*range));
873 /* Let's try to keep this struct in the same order as in
874 * linux/include/wireless.h
875 */
876
877 /* TODO: See what values we can set, and remove the ones we can't
878 * set, or fill them with some default data.
879 */
880 /* ~5 Mb/s real (802.11b) */
881 range->throughput = 5 * 1000 * 1000;
882 /* TODO: 8711 sensitivity ? */
883 /* signal level threshold range */
884 /* percent values between 0 and 100. */
885 range->max_qual.qual = 100;
886 range->max_qual.level = 100;
887 range->max_qual.noise = 100;
888 range->max_qual.updated = 7; /* Updated all three */
889 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
890 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
891 range->avg_qual.level = 0x100 - 78;
892 range->avg_qual.noise = 0;
893 range->avg_qual.updated = 7; /* Updated all three */
894 range->num_bitrates = RATE_COUNT;
895 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
896 range->bitrate[i] = rtl8180_rates[i];
897 range->min_frag = MIN_FRAG_THRESHOLD;
898 range->max_frag = MAX_FRAG_THRESHOLD;
899 range->pm_capa = 0;
900 range->we_version_compiled = WIRELESS_EXT;
901 range->we_version_source = 16;
902 range->num_channels = 14;
903 for (i = 0, val = 0; i < 14; i++) {
904 /* Include only legal frequencies for some countries */
905 range->freq[val].i = i + 1;
906 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
907 range->freq[val].e = 1;
908 val++;
909 if (val == IW_MAX_FREQUENCIES)
910 break;
911 }
912 range->num_frequency = val;
913 range->enc_capa = IW_ENC_CAPA_WPA |
914 IW_ENC_CAPA_WPA2 |
915 IW_ENC_CAPA_CIPHER_TKIP |
916 IW_ENC_CAPA_CIPHER_CCMP;
917 return 0;
918 }
919
920 static int r8711_wx_get_rate(struct net_device *dev,
921 struct iw_request_info *info,
922 union iwreq_data *wrqu, char *extra);
923
924 static int r871x_wx_set_priv(struct net_device *dev,
925 struct iw_request_info *info,
926 union iwreq_data *awrq,
927 char *extra)
928 {
929 int ret = 0, len = 0;
930 char *ext;
931 struct _adapter *padapter = netdev_priv(dev);
932 struct iw_point *dwrq = (struct iw_point *)awrq;
933
934 len = dwrq->length;
935 ext = memdup_user(dwrq->pointer, len);
936 if (IS_ERR(ext))
937 return PTR_ERR(ext);
938
939 if (!strcasecmp(ext, "RSSI")) {
940 /*Return received signal strength indicator in -db for */
941 /* current AP */
942 /*<ssid> Rssi xx */
943 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
944 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
945 /*static u8 xxxx; */
946 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
947 sprintf(ext, "%s rssi %d",
948 pcur_network->network.Ssid.Ssid,
949 /*(xxxx=xxxx+10) */
950 ((padapter->recvpriv.fw_rssi) >> 1) - 95
951 /*pcur_network->network.Rssi */
952 );
953 } else {
954 sprintf(ext, "OK");
955 }
956 } else if (!strcasecmp(ext, "LINKSPEED")) {
957 /*Return link speed in MBPS */
958 /*LinkSpeed xx */
959 union iwreq_data wrqd;
960 int ret_inner;
961 int mbps;
962
963 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
964 if (ret_inner != 0)
965 mbps = 0;
966 else
967 mbps = wrqd.bitrate.value / 1000000;
968 sprintf(ext, "LINKSPEED %d", mbps);
969 } else if (!strcasecmp(ext, "MACADDR")) {
970 /*Return mac address of the station */
971 /* Macaddr = xx:xx:xx:xx:xx:xx */
972 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
973 } else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
974 /*Set scan type to active */
975 /*OK if successful */
976 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
977
978 pmlmepriv->passive_mode = 1;
979 sprintf(ext, "OK");
980 } else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
981 /*Set scan type to passive */
982 /*OK if successful */
983 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
984
985 pmlmepriv->passive_mode = 0;
986 sprintf(ext, "OK");
987 } else if (!strncmp(ext, "DCE-E", 5)) {
988 /*Set scan type to passive */
989 /*OK if successful */
990 r8712_disconnectCtrlEx_cmd(padapter
991 , 1 /*u32 enableDrvCtrl */
992 , 5 /*u32 tryPktCnt */
993 , 100 /*u32 tryPktInterval */
994 , 5000 /*u32 firstStageTO */
995 );
996 sprintf(ext, "OK");
997 } else if (!strncmp(ext, "DCE-D", 5)) {
998 /*Set scan type to passive */
999 /*OK if successfu */
1000 r8712_disconnectCtrlEx_cmd(padapter
1001 , 0 /*u32 enableDrvCtrl */
1002 , 5 /*u32 tryPktCnt */
1003 , 100 /*u32 tryPktInterval */
1004 , 5000 /*u32 firstStageTO */
1005 );
1006 sprintf(ext, "OK");
1007 } else {
1008 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1009 __func__, ext);
1010 goto FREE_EXT;
1011 }
1012 if (copy_to_user(dwrq->pointer, ext,
1013 min(dwrq->length, (__u16)(strlen(ext) + 1))))
1014 ret = -EFAULT;
1015
1016 FREE_EXT:
1017 kfree(ext);
1018 return ret;
1019 }
1020
1021 /* set bssid flow
1022 * s1. set_802_11_infrastructure_mode()
1023 * s2. set_802_11_authentication_mode()
1024 * s3. set_802_11_encryption_mode()
1025 * s4. set_802_11_bssid()
1026 *
1027 * This function intends to handle the Set AP command, which specifies the
1028 * MAC# of a preferred Access Point.
1029 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1030 *
1031 * For this operation to succeed, there is no need for the interface to be up.
1032 *
1033 */
1034 static int r8711_wx_set_wap(struct net_device *dev,
1035 struct iw_request_info *info,
1036 union iwreq_data *awrq,
1037 char *extra)
1038 {
1039 int ret = -EINPROGRESS;
1040 struct _adapter *padapter = netdev_priv(dev);
1041 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1042 struct __queue *queue = &pmlmepriv->scanned_queue;
1043 struct sockaddr *temp = (struct sockaddr *)awrq;
1044 unsigned long irqL;
1045 struct list_head *phead;
1046 u8 *dst_bssid;
1047 struct wlan_network *pnetwork = NULL;
1048 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1049
1050 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1051 return -EBUSY;
1052 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1053 return ret;
1054 if (temp->sa_family != ARPHRD_ETHER)
1055 return -EINVAL;
1056 authmode = padapter->securitypriv.ndisauthtype;
1057 spin_lock_irqsave(&queue->lock, irqL);
1058 phead = &queue->queue;
1059 pmlmepriv->pscanned = phead->next;
1060 while (1) {
1061 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1062 break;
1063 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1064 struct wlan_network, list);
1065 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1066 dst_bssid = pnetwork->network.MacAddress;
1067 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1068 r8712_set_802_11_infrastructure_mode(padapter,
1069 pnetwork->network.InfrastructureMode);
1070 break;
1071 }
1072 }
1073 spin_unlock_irqrestore(&queue->lock, irqL);
1074 if (!ret) {
1075 if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
1076 ret = -ENOMEM;
1077 } else {
1078 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1079 ret = -1;
1080 }
1081 }
1082 return ret;
1083 }
1084
1085 static int r8711_wx_get_wap(struct net_device *dev,
1086 struct iw_request_info *info,
1087 union iwreq_data *wrqu, char *extra)
1088 {
1089 struct _adapter *padapter = netdev_priv(dev);
1090 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1091 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1092
1093 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1094 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1095 WIFI_AP_STATE))
1096 ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
1097 else
1098 eth_zero_addr(wrqu->ap_addr.sa_data);
1099 return 0;
1100 }
1101
1102 static int r871x_wx_set_mlme(struct net_device *dev,
1103 struct iw_request_info *info,
1104 union iwreq_data *wrqu, char *extra)
1105 {
1106 int ret = 0;
1107 struct _adapter *padapter = netdev_priv(dev);
1108 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1109
1110 if (mlme == NULL)
1111 return -1;
1112 switch (mlme->cmd) {
1113 case IW_MLME_DEAUTH:
1114 if (!r8712_set_802_11_disassociate(padapter))
1115 ret = -1;
1116 break;
1117 case IW_MLME_DISASSOC:
1118 if (!r8712_set_802_11_disassociate(padapter))
1119 ret = -1;
1120 break;
1121 default:
1122 return -EOPNOTSUPP;
1123 }
1124 return ret;
1125 }
1126
1127 /**
1128 *
1129 * This function intends to handle the Set Scan command.
1130 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1131 *
1132 * For this operation to succeed, the interface is brought Up beforehand.
1133 *
1134 */
1135 static int r8711_wx_set_scan(struct net_device *dev,
1136 struct iw_request_info *a,
1137 union iwreq_data *wrqu, char *extra)
1138 {
1139 struct _adapter *padapter = netdev_priv(dev);
1140 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1141 u8 status = true;
1142
1143 if (padapter->bDriverStopped) {
1144 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1145 __func__, padapter->bDriverStopped);
1146 return -1;
1147 }
1148 if (!padapter->bup)
1149 return -ENETDOWN;
1150 if (!padapter->hw_init_completed)
1151 return -1;
1152 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
1153 (pmlmepriv->sitesurveyctrl.traffic_busy))
1154 return 0;
1155 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1156 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1157
1158 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1159 struct ndis_802_11_ssid ssid;
1160 unsigned long irqL;
1161 u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1162
1163 memset((unsigned char *)&ssid, 0,
1164 sizeof(struct ndis_802_11_ssid));
1165 memcpy(ssid.Ssid, req->essid, len);
1166 ssid.SsidLength = len;
1167 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1168 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1169 _FW_UNDER_LINKING)) ||
1170 (pmlmepriv->sitesurveyctrl.traffic_busy)) {
1171 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1172 status = false;
1173 } else {
1174 status = r8712_sitesurvey_cmd(padapter, &ssid);
1175 }
1176 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1177 }
1178 } else {
1179 status = r8712_set_802_11_bssid_list_scan(padapter);
1180 }
1181 if (!status)
1182 return -1;
1183 return 0;
1184 }
1185
1186 static int r8711_wx_get_scan(struct net_device *dev,
1187 struct iw_request_info *a,
1188 union iwreq_data *wrqu, char *extra)
1189 {
1190 struct _adapter *padapter = netdev_priv(dev);
1191 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1192 struct __queue *queue = &pmlmepriv->scanned_queue;
1193 struct wlan_network *pnetwork = NULL;
1194 unsigned long irqL;
1195 struct list_head *plist, *phead;
1196 char *ev = extra;
1197 char *stop = ev + wrqu->data.length;
1198 u32 ret = 0, cnt = 0;
1199
1200 if (padapter->bDriverStopped)
1201 return -EINVAL;
1202 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1203 _FW_UNDER_LINKING)) {
1204 msleep(30);
1205 cnt++;
1206 if (cnt > 100)
1207 break;
1208 }
1209 spin_lock_irqsave(&queue->lock, irqL);
1210 phead = &queue->queue;
1211 plist = phead->next;
1212 while (1) {
1213 if (end_of_queue_search(phead, plist))
1214 break;
1215 if ((stop - ev) < SCAN_ITEM_SIZE) {
1216 ret = -E2BIG;
1217 break;
1218 }
1219 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1220 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1221 plist = plist->next;
1222 }
1223 spin_unlock_irqrestore(&queue->lock, irqL);
1224 wrqu->data.length = ev - extra;
1225 wrqu->data.flags = 0;
1226 return ret;
1227 }
1228
1229 /* set ssid flow
1230 * s1. set_802_11_infrastructure_mode()
1231 * s2. set_802_11_authenticaion_mode()
1232 * s3. set_802_11_encryption_mode()
1233 * s4. set_802_11_ssid()
1234 *
1235 * This function intends to handle the Set ESSID command.
1236 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1237 *
1238 * For this operation to succeed, there is no need for the interface to be Up.
1239 *
1240 */
1241 static int r8711_wx_set_essid(struct net_device *dev,
1242 struct iw_request_info *a,
1243 union iwreq_data *wrqu, char *extra)
1244 {
1245 struct _adapter *padapter = netdev_priv(dev);
1246 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1247 struct __queue *queue = &pmlmepriv->scanned_queue;
1248 struct wlan_network *pnetwork = NULL;
1249 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1250 struct ndis_802_11_ssid ndis_ssid;
1251 u8 *dst_ssid, *src_ssid;
1252 struct list_head *phead;
1253 u32 len;
1254
1255 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1256 return -EBUSY;
1257 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1258 return 0;
1259 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1260 return -E2BIG;
1261 authmode = padapter->securitypriv.ndisauthtype;
1262 if (wrqu->essid.flags && wrqu->essid.length) {
1263 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1264 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1265 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1266 ndis_ssid.SsidLength = len;
1267 memcpy(ndis_ssid.Ssid, extra, len);
1268 src_ssid = ndis_ssid.Ssid;
1269 phead = &queue->queue;
1270 pmlmepriv->pscanned = phead->next;
1271 while (1) {
1272 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1273 break;
1274 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1275 struct wlan_network, list);
1276 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1277 dst_ssid = pnetwork->network.Ssid.Ssid;
1278 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1279 && (pnetwork->network.Ssid.SsidLength ==
1280 ndis_ssid.SsidLength)) {
1281 if (check_fwstate(pmlmepriv,
1282 WIFI_ADHOC_STATE)) {
1283 if (pnetwork->network.
1284 InfrastructureMode
1285 !=
1286 padapter->mlmepriv.
1287 cur_network.network.
1288 InfrastructureMode)
1289 continue;
1290 }
1291
1292 r8712_set_802_11_infrastructure_mode(
1293 padapter,
1294 pnetwork->network.InfrastructureMode);
1295 break;
1296 }
1297 }
1298 r8712_set_802_11_authentication_mode(padapter, authmode);
1299 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1300 }
1301 return -EINPROGRESS;
1302 }
1303
1304 static int r8711_wx_get_essid(struct net_device *dev,
1305 struct iw_request_info *a,
1306 union iwreq_data *wrqu, char *extra)
1307 {
1308 struct _adapter *padapter = netdev_priv(dev);
1309 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1310 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1311 u32 len, ret = 0;
1312
1313 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
1314 len = pcur_bss->Ssid.SsidLength;
1315 wrqu->essid.length = len;
1316 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1317 wrqu->essid.flags = 1;
1318 } else {
1319 ret = -ENOLINK;
1320 }
1321 return ret;
1322 }
1323
1324 static int r8711_wx_set_rate(struct net_device *dev,
1325 struct iw_request_info *a,
1326 union iwreq_data *wrqu, char *extra)
1327 {
1328 struct _adapter *padapter = netdev_priv(dev);
1329 u32 target_rate = wrqu->bitrate.value;
1330 u32 fixed = wrqu->bitrate.fixed;
1331 u32 ratevalue = 0;
1332 u8 datarates[NumRates];
1333 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1334 int i, ret = 0;
1335
1336 if (target_rate == -1) {
1337 ratevalue = 11;
1338 goto set_rate;
1339 }
1340 target_rate = target_rate / 100000;
1341 switch (target_rate) {
1342 case 10:
1343 ratevalue = 0;
1344 break;
1345 case 20:
1346 ratevalue = 1;
1347 break;
1348 case 55:
1349 ratevalue = 2;
1350 break;
1351 case 60:
1352 ratevalue = 3;
1353 break;
1354 case 90:
1355 ratevalue = 4;
1356 break;
1357 case 110:
1358 ratevalue = 5;
1359 break;
1360 case 120:
1361 ratevalue = 6;
1362 break;
1363 case 180:
1364 ratevalue = 7;
1365 break;
1366 case 240:
1367 ratevalue = 8;
1368 break;
1369 case 360:
1370 ratevalue = 9;
1371 break;
1372 case 480:
1373 ratevalue = 10;
1374 break;
1375 case 540:
1376 ratevalue = 11;
1377 break;
1378 default:
1379 ratevalue = 11;
1380 break;
1381 }
1382 set_rate:
1383 for (i = 0; i < NumRates; i++) {
1384 if (ratevalue == mpdatarate[i]) {
1385 datarates[i] = mpdatarate[i];
1386 if (fixed == 0)
1387 break;
1388 } else {
1389 datarates[i] = 0xff;
1390 }
1391 }
1392 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1393 ret = -ENOMEM;
1394 return ret;
1395 }
1396
1397 static int r8711_wx_get_rate(struct net_device *dev,
1398 struct iw_request_info *info,
1399 union iwreq_data *wrqu, char *extra)
1400 {
1401 struct _adapter *padapter = netdev_priv(dev);
1402 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1403 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1404 struct ieee80211_ht_cap *pht_capie;
1405 unsigned char rf_type = padapter->registrypriv.rf_config;
1406 int i;
1407 u8 *p;
1408 u16 rate, max_rate = 0, ht_cap = false;
1409 u32 ht_ielen = 0;
1410 u8 bw_40MHz = 0, short_GI = 0;
1411 u16 mcs_rate = 0;
1412
1413 i = 0;
1414 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
1415 p = r8712_get_ie(&pcur_bss->IEs[12],
1416 _HT_CAPABILITY_IE_, &ht_ielen,
1417 pcur_bss->IELength - 12);
1418 if (p && ht_ielen > 0) {
1419 ht_cap = true;
1420 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1421 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
1422 bw_40MHz = (pht_capie->cap_info &
1423 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1424 short_GI = (pht_capie->cap_info &
1425 (IEEE80211_HT_CAP_SGI_20 |
1426 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1427 }
1428 while ((pcur_bss->rates[i] != 0) &&
1429 (pcur_bss->rates[i] != 0xFF)) {
1430 rate = pcur_bss->rates[i] & 0x7F;
1431 if (rate > max_rate)
1432 max_rate = rate;
1433 wrqu->bitrate.fixed = 0; /* no auto select */
1434 wrqu->bitrate.value = rate * 500000;
1435 i++;
1436 }
1437 if (ht_cap) {
1438 if (mcs_rate & 0x8000 /* MCS15 */
1439 &&
1440 rf_type == RTL8712_RF_2T2R)
1441 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1442 270) : ((short_GI) ? 144 : 130);
1443 else /* default MCS7 */
1444 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1445 135) : ((short_GI) ? 72 : 65);
1446 max_rate *= 2; /* Mbps/2 */
1447 }
1448 wrqu->bitrate.value = max_rate * 500000;
1449 } else {
1450 return -ENOLINK;
1451 }
1452 return 0;
1453 }
1454
1455 static int r8711_wx_get_rts(struct net_device *dev,
1456 struct iw_request_info *info,
1457 union iwreq_data *wrqu, char *extra)
1458 {
1459 struct _adapter *padapter = netdev_priv(dev);
1460
1461 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1462 wrqu->rts.fixed = 0; /* no auto select */
1463 return 0;
1464 }
1465
1466 static int r8711_wx_set_frag(struct net_device *dev,
1467 struct iw_request_info *info,
1468 union iwreq_data *wrqu, char *extra)
1469 {
1470 struct _adapter *padapter = netdev_priv(dev);
1471
1472 if (wrqu->frag.disabled) {
1473 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1474 } else {
1475 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1476 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1477 return -EINVAL;
1478 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1479 }
1480 return 0;
1481 }
1482
1483 static int r8711_wx_get_frag(struct net_device *dev,
1484 struct iw_request_info *info,
1485 union iwreq_data *wrqu, char *extra)
1486 {
1487 struct _adapter *padapter = netdev_priv(dev);
1488
1489 wrqu->frag.value = padapter->xmitpriv.frag_len;
1490 wrqu->frag.fixed = 0; /* no auto select */
1491 return 0;
1492 }
1493
1494 static int r8711_wx_get_retry(struct net_device *dev,
1495 struct iw_request_info *info,
1496 union iwreq_data *wrqu, char *extra)
1497 {
1498 wrqu->retry.value = 7;
1499 wrqu->retry.fixed = 0; /* no auto select */
1500 wrqu->retry.disabled = 1;
1501 return 0;
1502 }
1503
1504 static int r8711_wx_set_enc(struct net_device *dev,
1505 struct iw_request_info *info,
1506 union iwreq_data *wrqu, char *keybuf)
1507 {
1508 u32 key;
1509 u32 keyindex_provided;
1510 struct NDIS_802_11_WEP wep;
1511 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1512 struct iw_point *erq = &(wrqu->encoding);
1513 struct _adapter *padapter = netdev_priv(dev);
1514
1515 key = erq->flags & IW_ENCODE_INDEX;
1516 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1517 if (erq->flags & IW_ENCODE_DISABLED) {
1518 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1519 padapter->securitypriv.ndisencryptstatus =
1520 Ndis802_11EncryptionDisabled;
1521 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1522 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1523 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1524 authmode = Ndis802_11AuthModeOpen;
1525 padapter->securitypriv.ndisauthtype = authmode;
1526 return 0;
1527 }
1528 if (key) {
1529 if (key > WEP_KEYS)
1530 return -EINVAL;
1531 key--;
1532 keyindex_provided = 1;
1533 } else {
1534 keyindex_provided = 0;
1535 key = padapter->securitypriv.PrivacyKeyIndex;
1536 }
1537 /* set authentication mode */
1538 if (erq->flags & IW_ENCODE_OPEN) {
1539 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1540 padapter->securitypriv.ndisencryptstatus =
1541 Ndis802_11Encryption1Enabled;
1542 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1543 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1544 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1545 authmode = Ndis802_11AuthModeOpen;
1546 padapter->securitypriv.ndisauthtype = authmode;
1547 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1548 netdev_info(dev,
1549 "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
1550 padapter->securitypriv.ndisencryptstatus =
1551 Ndis802_11Encryption1Enabled;
1552 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1553 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1554 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1555 authmode = Ndis802_11AuthModeShared;
1556 padapter->securitypriv.ndisauthtype = authmode;
1557 } else {
1558 padapter->securitypriv.ndisencryptstatus =
1559 Ndis802_11Encryption1Enabled;
1560 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1561 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1562 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1563 authmode = Ndis802_11AuthModeOpen;
1564 padapter->securitypriv.ndisauthtype = authmode;
1565 }
1566 wep.KeyIndex = key;
1567 if (erq->length > 0) {
1568 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1569 wep.Length = wep.KeyLength +
1570 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1571 } else {
1572 wep.KeyLength = 0;
1573 if (keyindex_provided == 1) { /* set key_id only, no given
1574 * KeyMaterial(erq->length==0).
1575 */
1576 padapter->securitypriv.PrivacyKeyIndex = key;
1577 switch (padapter->securitypriv.DefKeylen[key]) {
1578 case 5:
1579 padapter->securitypriv.PrivacyAlgrthm =
1580 _WEP40_;
1581 break;
1582 case 13:
1583 padapter->securitypriv.PrivacyAlgrthm =
1584 _WEP104_;
1585 break;
1586 default:
1587 padapter->securitypriv.PrivacyAlgrthm =
1588 _NO_PRIVACY_;
1589 break;
1590 }
1591 return 0;
1592 }
1593 }
1594 wep.KeyIndex |= 0x80000000; /* transmit key */
1595 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1596 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1597 return -EOPNOTSUPP;
1598 return 0;
1599 }
1600
1601 static int r8711_wx_get_enc(struct net_device *dev,
1602 struct iw_request_info *info,
1603 union iwreq_data *wrqu, char *keybuf)
1604 {
1605 uint key, ret = 0;
1606 struct _adapter *padapter = netdev_priv(dev);
1607 struct iw_point *erq = &(wrqu->encoding);
1608 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1609
1610 if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
1611 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1612 erq->length = 0;
1613 erq->flags |= IW_ENCODE_DISABLED;
1614 return 0;
1615 }
1616 }
1617 key = erq->flags & IW_ENCODE_INDEX;
1618 if (key) {
1619 if (key > WEP_KEYS)
1620 return -EINVAL;
1621 key--;
1622 } else {
1623 key = padapter->securitypriv.PrivacyKeyIndex;
1624 }
1625 erq->flags = key + 1;
1626 switch (padapter->securitypriv.ndisencryptstatus) {
1627 case Ndis802_11EncryptionNotSupported:
1628 case Ndis802_11EncryptionDisabled:
1629 erq->length = 0;
1630 erq->flags |= IW_ENCODE_DISABLED;
1631 break;
1632 case Ndis802_11Encryption1Enabled:
1633 erq->length = padapter->securitypriv.DefKeylen[key];
1634 if (erq->length) {
1635 memcpy(keybuf, padapter->securitypriv.DefKey[
1636 key].skey, padapter->securitypriv.
1637 DefKeylen[key]);
1638 erq->flags |= IW_ENCODE_ENABLED;
1639 if (padapter->securitypriv.ndisauthtype ==
1640 Ndis802_11AuthModeOpen)
1641 erq->flags |= IW_ENCODE_OPEN;
1642 else if (padapter->securitypriv.ndisauthtype ==
1643 Ndis802_11AuthModeShared)
1644 erq->flags |= IW_ENCODE_RESTRICTED;
1645 } else {
1646 erq->length = 0;
1647 erq->flags |= IW_ENCODE_DISABLED;
1648 }
1649 break;
1650 case Ndis802_11Encryption2Enabled:
1651 case Ndis802_11Encryption3Enabled:
1652 erq->length = 16;
1653 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1654 IW_ENCODE_NOKEY);
1655 break;
1656 default:
1657 erq->length = 0;
1658 erq->flags |= IW_ENCODE_DISABLED;
1659 break;
1660 }
1661 return ret;
1662 }
1663
1664 static int r8711_wx_get_power(struct net_device *dev,
1665 struct iw_request_info *info,
1666 union iwreq_data *wrqu, char *extra)
1667 {
1668 wrqu->power.value = 0;
1669 wrqu->power.fixed = 0; /* no auto select */
1670 wrqu->power.disabled = 1;
1671 return 0;
1672 }
1673
1674 static int r871x_wx_set_gen_ie(struct net_device *dev,
1675 struct iw_request_info *info,
1676 union iwreq_data *wrqu, char *extra)
1677 {
1678 struct _adapter *padapter = netdev_priv(dev);
1679
1680 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1681 }
1682
1683 static int r871x_wx_set_auth(struct net_device *dev,
1684 struct iw_request_info *info,
1685 union iwreq_data *wrqu, char *extra)
1686 {
1687 struct _adapter *padapter = netdev_priv(dev);
1688 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1689 int paramid;
1690 int paramval;
1691 int ret = 0;
1692
1693 paramid = param->flags & IW_AUTH_INDEX;
1694 paramval = param->value;
1695 switch (paramid) {
1696 case IW_AUTH_WPA_VERSION:
1697 break;
1698 case IW_AUTH_CIPHER_PAIRWISE:
1699 break;
1700 case IW_AUTH_CIPHER_GROUP:
1701 break;
1702 case IW_AUTH_KEY_MGMT:
1703 /*
1704 * ??? does not use these parameters
1705 */
1706 break;
1707 case IW_AUTH_TKIP_COUNTERMEASURES:
1708 if (paramval) {
1709 /* wpa_supplicant is enabling tkip countermeasure. */
1710 padapter->securitypriv.btkip_countermeasure = true;
1711 } else {
1712 /* wpa_supplicant is disabling tkip countermeasure. */
1713 padapter->securitypriv.btkip_countermeasure = false;
1714 }
1715 break;
1716 case IW_AUTH_DROP_UNENCRYPTED:
1717 /* HACK:
1718 *
1719 * wpa_supplicant calls set_wpa_enabled when the driver
1720 * is loaded and unloaded, regardless of if WPA is being
1721 * used. No other calls are made which can be used to
1722 * determine if encryption will be used or not prior to
1723 * association being expected. If encryption is not being
1724 * used, drop_unencrypted is set to false, else true -- we
1725 * can use this to determine if the CAP_PRIVACY_ON bit should
1726 * be set.
1727 */
1728 if (padapter->securitypriv.ndisencryptstatus ==
1729 Ndis802_11Encryption1Enabled) {
1730 /* it means init value, or using wep,
1731 * ndisencryptstatus =
1732 * Ndis802_11Encryption1Enabled,
1733 * then it needn't reset it;
1734 */
1735 break;
1736 }
1737
1738 if (paramval) {
1739 padapter->securitypriv.ndisencryptstatus =
1740 Ndis802_11EncryptionDisabled;
1741 padapter->securitypriv.PrivacyAlgrthm =
1742 _NO_PRIVACY_;
1743 padapter->securitypriv.XGrpPrivacy =
1744 _NO_PRIVACY_;
1745 padapter->securitypriv.AuthAlgrthm = 0;
1746 padapter->securitypriv.ndisauthtype =
1747 Ndis802_11AuthModeOpen;
1748 }
1749 break;
1750 case IW_AUTH_80211_AUTH_ALG:
1751 ret = wpa_set_auth_algs(dev, (u32)paramval);
1752 break;
1753 case IW_AUTH_WPA_ENABLED:
1754 break;
1755 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1756 break;
1757 case IW_AUTH_PRIVACY_INVOKED:
1758 break;
1759 default:
1760 return -EOPNOTSUPP;
1761 }
1762
1763 return ret;
1764 }
1765
1766 static int r871x_wx_set_enc_ext(struct net_device *dev,
1767 struct iw_request_info *info,
1768 union iwreq_data *wrqu, char *extra)
1769 {
1770 struct iw_point *pencoding = &wrqu->encoding;
1771 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1772 struct ieee_param *param = NULL;
1773 char *alg_name;
1774 u32 param_len;
1775 int ret = 0;
1776
1777 switch (pext->alg) {
1778 case IW_ENCODE_ALG_NONE:
1779 alg_name = "none";
1780 break;
1781 case IW_ENCODE_ALG_WEP:
1782 alg_name = "WEP";
1783 break;
1784 case IW_ENCODE_ALG_TKIP:
1785 alg_name = "TKIP";
1786 break;
1787 case IW_ENCODE_ALG_CCMP:
1788 alg_name = "CCMP";
1789 break;
1790 default:
1791 return -EINVAL;
1792 }
1793
1794 param_len = sizeof(struct ieee_param) + pext->key_len;
1795 param = kzalloc(param_len, GFP_ATOMIC);
1796 if (param == NULL)
1797 return -ENOMEM;
1798 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1799 eth_broadcast_addr(param->sta_addr);
1800 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1801 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1802 param->u.crypt.set_tx = 0;
1803 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1804 param->u.crypt.set_tx = 1;
1805 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1806 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1807 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1808 if (pext->key_len) {
1809 param->u.crypt.key_len = pext->key_len;
1810 memcpy(param + 1, pext + 1, pext->key_len);
1811 }
1812 ret = wpa_set_encryption(dev, param, param_len);
1813 kfree(param);
1814 return ret;
1815 }
1816
1817 static int r871x_wx_get_nick(struct net_device *dev,
1818 struct iw_request_info *info,
1819 union iwreq_data *wrqu, char *extra)
1820 {
1821 if (extra) {
1822 wrqu->data.length = 8;
1823 wrqu->data.flags = 1;
1824 memcpy(extra, "rtl_wifi", 8);
1825 }
1826 return 0;
1827 }
1828
1829 static int r8711_wx_read32(struct net_device *dev,
1830 struct iw_request_info *info,
1831 union iwreq_data *wrqu, char *keybuf)
1832 {
1833 struct _adapter *padapter = netdev_priv(dev);
1834 u32 addr;
1835 u32 data32;
1836
1837 get_user(addr, (u32 __user *)wrqu->data.pointer);
1838 data32 = r8712_read32(padapter, addr);
1839 put_user(data32, (u32 __user *)wrqu->data.pointer);
1840 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1841 wrqu->data.flags = data32 & 0xffff;
1842 get_user(addr, (u32 __user *)wrqu->data.pointer);
1843 return 0;
1844 }
1845
1846 static int r8711_wx_write32(struct net_device *dev,
1847 struct iw_request_info *info,
1848 union iwreq_data *wrqu, char *keybuf)
1849 {
1850 struct _adapter *padapter = netdev_priv(dev);
1851 u32 addr;
1852 u32 data32;
1853
1854 get_user(addr, (u32 __user *)wrqu->data.pointer);
1855 data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
1856 r8712_write32(padapter, addr, data32);
1857 return 0;
1858 }
1859
1860 static int dummy(struct net_device *dev,
1861 struct iw_request_info *a,
1862 union iwreq_data *wrqu, char *b)
1863 {
1864 return -ENOSYS;
1865 }
1866
1867 static int r8711_drvext_hdl(struct net_device *dev,
1868 struct iw_request_info *info,
1869 union iwreq_data *wrqu, char *extra)
1870 {
1871 return 0;
1872 }
1873
1874 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1875 struct iw_request_info *info,
1876 union iwreq_data *wrqu, char *extra)
1877 {
1878 struct _adapter *padapter = netdev_priv(dev);
1879 struct iw_point *p = &wrqu->data;
1880 struct oid_par_priv oid_par;
1881 struct mp_ioctl_handler *phandler;
1882 struct mp_ioctl_param *poidparam;
1883 unsigned long BytesRead, BytesWritten, BytesNeeded;
1884 u8 *pparmbuf, bset;
1885 u16 len;
1886 uint status;
1887 int ret = 0;
1888
1889 if ((!p->length) || (!p->pointer))
1890 return -EINVAL;
1891
1892 bset = (u8)(p->flags & 0xFFFF);
1893 len = p->length;
1894 pparmbuf = memdup_user(p->pointer, len);
1895 if (IS_ERR(pparmbuf))
1896 return PTR_ERR(pparmbuf);
1897
1898 poidparam = (struct mp_ioctl_param *)pparmbuf;
1899 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1900 ret = -EINVAL;
1901 goto _r871x_mp_ioctl_hdl_exit;
1902 }
1903 phandler = mp_ioctl_hdl + poidparam->subcode;
1904 if ((phandler->paramsize != 0) &&
1905 (poidparam->len < phandler->paramsize)) {
1906 ret = -EINVAL;
1907 goto _r871x_mp_ioctl_hdl_exit;
1908 }
1909 if (phandler->oid == 0 && phandler->handler) {
1910 status = phandler->handler(&oid_par);
1911 } else if (phandler->handler) {
1912 oid_par.adapter_context = padapter;
1913 oid_par.oid = phandler->oid;
1914 oid_par.information_buf = poidparam->data;
1915 oid_par.information_buf_len = poidparam->len;
1916 oid_par.dbg = 0;
1917 BytesWritten = 0;
1918 BytesNeeded = 0;
1919 if (bset) {
1920 oid_par.bytes_rw = &BytesRead;
1921 oid_par.bytes_needed = &BytesNeeded;
1922 oid_par.type_of_oid = SET_OID;
1923 } else {
1924 oid_par.bytes_rw = &BytesWritten;
1925 oid_par.bytes_needed = &BytesNeeded;
1926 oid_par.type_of_oid = QUERY_OID;
1927 }
1928 status = phandler->handler(&oid_par);
1929 /* todo:check status, BytesNeeded, etc. */
1930 } else {
1931 netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
1932 __func__, poidparam->subcode, phandler->oid,
1933 phandler->handler);
1934 ret = -EFAULT;
1935 goto _r871x_mp_ioctl_hdl_exit;
1936 }
1937 if (bset == 0x00) { /* query info */
1938 if (copy_to_user(p->pointer, pparmbuf, len))
1939 ret = -EFAULT;
1940 }
1941 if (status) {
1942 ret = -EFAULT;
1943 goto _r871x_mp_ioctl_hdl_exit;
1944 }
1945 _r871x_mp_ioctl_hdl_exit:
1946 kfree(pparmbuf);
1947 return ret;
1948 }
1949
1950 static int r871x_get_ap_info(struct net_device *dev,
1951 struct iw_request_info *info,
1952 union iwreq_data *wrqu, char *extra)
1953 {
1954 struct _adapter *padapter = netdev_priv(dev);
1955 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1956 struct __queue *queue = &pmlmepriv->scanned_queue;
1957 struct iw_point *pdata = &wrqu->data;
1958 struct wlan_network *pnetwork = NULL;
1959 u32 cnt = 0, wpa_ielen;
1960 unsigned long irqL;
1961 struct list_head *plist, *phead;
1962 unsigned char *pbuf;
1963 u8 bssid[ETH_ALEN];
1964 char data[33];
1965
1966 if (padapter->bDriverStopped || (pdata == NULL))
1967 return -EINVAL;
1968 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1969 _FW_UNDER_LINKING)) {
1970 msleep(30);
1971 cnt++;
1972 if (cnt > 100)
1973 break;
1974 }
1975 pdata->flags = 0;
1976 if (pdata->length >= 32) {
1977 if (copy_from_user(data, pdata->pointer, 32))
1978 return -EINVAL;
1979 data[32] = 0;
1980 } else {
1981 return -EINVAL;
1982 }
1983 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
1984 phead = &queue->queue;
1985 plist = phead->next;
1986 while (1) {
1987 if (end_of_queue_search(phead, plist))
1988 break;
1989 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1990 if (!mac_pton(data, bssid)) {
1991 netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
1992 (u8 *)data);
1993 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
1994 irqL);
1995 return -EINVAL;
1996 }
1997 netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
1998 if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
1999 /* BSSID match, then check if supporting wpa/wpa2 */
2000 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2001 &wpa_ielen, pnetwork->network.IELength - 12);
2002 if (pbuf && (wpa_ielen > 0)) {
2003 pdata->flags = 1;
2004 break;
2005 }
2006 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2007 &wpa_ielen, pnetwork->network.IELength - 12);
2008 if (pbuf && (wpa_ielen > 0)) {
2009 pdata->flags = 2;
2010 break;
2011 }
2012 }
2013 plist = plist->next;
2014 }
2015 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2016 if (pdata->length >= 34) {
2017 if (copy_to_user((u8 __user *)pdata->pointer + 32,
2018 (u8 *)&pdata->flags, 1))
2019 return -EINVAL;
2020 }
2021 return 0;
2022 }
2023
2024 static int r871x_set_pid(struct net_device *dev,
2025 struct iw_request_info *info,
2026 union iwreq_data *wrqu, char *extra)
2027 {
2028 struct _adapter *padapter = netdev_priv(dev);
2029 struct iw_point *pdata = &wrqu->data;
2030
2031 if ((padapter->bDriverStopped) || (pdata == NULL))
2032 return -EINVAL;
2033 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2034 return -EINVAL;
2035 return 0;
2036 }
2037
2038 static int r871x_set_chplan(struct net_device *dev,
2039 struct iw_request_info *info,
2040 union iwreq_data *wrqu, char *extra)
2041 {
2042 int ret = 0;
2043 struct _adapter *padapter = netdev_priv(dev);
2044 struct iw_point *pdata = &wrqu->data;
2045 int ch_plan = -1;
2046
2047 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2048 ret = -EINVAL;
2049 goto exit;
2050 }
2051 ch_plan = (int)*extra;
2052 r8712_set_chplan_cmd(padapter, ch_plan);
2053
2054 exit:
2055
2056 return ret;
2057 }
2058
2059 static int r871x_wps_start(struct net_device *dev,
2060 struct iw_request_info *info,
2061 union iwreq_data *wrqu, char *extra)
2062 {
2063 struct _adapter *padapter = netdev_priv(dev);
2064 struct iw_point *pdata = &wrqu->data;
2065 u32 u32wps_start = 0;
2066
2067 if ((padapter->bDriverStopped) || (pdata == NULL))
2068 return -EINVAL;
2069 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2070 return -EFAULT;
2071 if (u32wps_start == 0)
2072 u32wps_start = *extra;
2073 if (u32wps_start == 1) /* WPS Start */
2074 padapter->ledpriv.LedControlHandler(padapter,
2075 LED_CTL_START_WPS);
2076 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2077 padapter->ledpriv.LedControlHandler(padapter,
2078 LED_CTL_STOP_WPS);
2079 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2080 padapter->ledpriv.LedControlHandler(padapter,
2081 LED_CTL_STOP_WPS_FAIL);
2082 return 0;
2083 }
2084
2085 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2086 {
2087 struct _adapter *padapter = netdev_priv(dev);
2088
2089 switch (name) {
2090 case IEEE_PARAM_WPA_ENABLED:
2091 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2092 switch ((value) & 0xff) {
2093 case 1: /* WPA */
2094 padapter->securitypriv.ndisauthtype =
2095 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2096 padapter->securitypriv.ndisencryptstatus =
2097 Ndis802_11Encryption2Enabled;
2098 break;
2099 case 2: /* WPA2 */
2100 padapter->securitypriv.ndisauthtype =
2101 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2102 padapter->securitypriv.ndisencryptstatus =
2103 Ndis802_11Encryption3Enabled;
2104 break;
2105 }
2106 break;
2107 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2108 break;
2109 case IEEE_PARAM_DROP_UNENCRYPTED:
2110 /* HACK:
2111 *
2112 * wpa_supplicant calls set_wpa_enabled when the driver
2113 * is loaded and unloaded, regardless of if WPA is being
2114 * used. No other calls are made which can be used to
2115 * determine if encryption will be used or not prior to
2116 * association being expected. If encryption is not being
2117 * used, drop_unencrypted is set to false, else true -- we
2118 * can use this to determine if the CAP_PRIVACY_ON bit should
2119 * be set.
2120 */
2121 break;
2122 case IEEE_PARAM_PRIVACY_INVOKED:
2123 break;
2124 case IEEE_PARAM_AUTH_ALGS:
2125 return wpa_set_auth_algs(dev, value);
2126 case IEEE_PARAM_IEEE_802_1X:
2127 break;
2128 case IEEE_PARAM_WPAX_SELECT:
2129 /* added for WPA2 mixed mode */
2130 break;
2131 default:
2132 return -EOPNOTSUPP;
2133 }
2134 return 0;
2135 }
2136
2137 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2138 {
2139 struct _adapter *padapter = netdev_priv(dev);
2140
2141 switch (command) {
2142 case IEEE_MLME_STA_DEAUTH:
2143 if (!r8712_set_802_11_disassociate(padapter))
2144 return -1;
2145 break;
2146 case IEEE_MLME_STA_DISASSOC:
2147 if (!r8712_set_802_11_disassociate(padapter))
2148 return -1;
2149 break;
2150 default:
2151 return -EOPNOTSUPP;
2152 }
2153 return 0;
2154 }
2155
2156 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2157 {
2158 struct ieee_param *param;
2159 int ret = 0;
2160 struct _adapter *padapter = netdev_priv(dev);
2161
2162 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2163 return -EINVAL;
2164 param = memdup_user(p->pointer, p->length);
2165 if (IS_ERR(param))
2166 return PTR_ERR(param);
2167 switch (param->cmd) {
2168 case IEEE_CMD_SET_WPA_PARAM:
2169 ret = wpa_set_param(dev, param->u.wpa_param.name,
2170 param->u.wpa_param.value);
2171 break;
2172 case IEEE_CMD_SET_WPA_IE:
2173 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2174 (u16)param->u.wpa_ie.len);
2175 break;
2176 case IEEE_CMD_SET_ENCRYPTION:
2177 ret = wpa_set_encryption(dev, param, p->length);
2178 break;
2179 case IEEE_CMD_MLME:
2180 ret = wpa_mlme(dev, param->u.mlme.command,
2181 param->u.mlme.reason_code);
2182 break;
2183 default:
2184 ret = -EOPNOTSUPP;
2185 break;
2186 }
2187 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2188 ret = -EFAULT;
2189 kfree(param);
2190 return ret;
2191 }
2192
2193 /* based on "driver_ipw" and for hostapd */
2194 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2195 {
2196 struct iwreq *wrq = (struct iwreq *)rq;
2197
2198 switch (cmd) {
2199 case RTL_IOCTL_WPA_SUPPLICANT:
2200 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2201 default:
2202 return -EOPNOTSUPP;
2203 }
2204 return 0;
2205 }
2206
2207 static iw_handler r8711_handlers[] = {
2208 NULL, /* SIOCSIWCOMMIT */
2209 r8711_wx_get_name, /* SIOCGIWNAME */
2210 dummy, /* SIOCSIWNWID */
2211 dummy, /* SIOCGIWNWID */
2212 r8711_wx_set_freq, /* SIOCSIWFREQ */
2213 r8711_wx_get_freq, /* SIOCGIWFREQ */
2214 r8711_wx_set_mode, /* SIOCSIWMODE */
2215 r8711_wx_get_mode, /* SIOCGIWMODE */
2216 dummy, /* SIOCSIWSENS */
2217 r8711_wx_get_sens, /* SIOCGIWSENS */
2218 NULL, /* SIOCSIWRANGE */
2219 r8711_wx_get_range, /* SIOCGIWRANGE */
2220 r871x_wx_set_priv, /* SIOCSIWPRIV */
2221 NULL, /* SIOCGIWPRIV */
2222 NULL, /* SIOCSIWSTATS */
2223 NULL, /* SIOCGIWSTATS */
2224 dummy, /* SIOCSIWSPY */
2225 dummy, /* SIOCGIWSPY */
2226 NULL, /* SIOCGIWTHRSPY */
2227 NULL, /* SIOCWIWTHRSPY */
2228 r8711_wx_set_wap, /* SIOCSIWAP */
2229 r8711_wx_get_wap, /* SIOCGIWAP */
2230 r871x_wx_set_mlme, /* request MLME operation;
2231 * uses struct iw_mlme
2232 */
2233 dummy, /* SIOCGIWAPLIST -- deprecated */
2234 r8711_wx_set_scan, /* SIOCSIWSCAN */
2235 r8711_wx_get_scan, /* SIOCGIWSCAN */
2236 r8711_wx_set_essid, /* SIOCSIWESSID */
2237 r8711_wx_get_essid, /* SIOCGIWESSID */
2238 dummy, /* SIOCSIWNICKN */
2239 r871x_wx_get_nick, /* SIOCGIWNICKN */
2240 NULL, /* -- hole -- */
2241 NULL, /* -- hole -- */
2242 r8711_wx_set_rate, /* SIOCSIWRATE */
2243 r8711_wx_get_rate, /* SIOCGIWRATE */
2244 dummy, /* SIOCSIWRTS */
2245 r8711_wx_get_rts, /* SIOCGIWRTS */
2246 r8711_wx_set_frag, /* SIOCSIWFRAG */
2247 r8711_wx_get_frag, /* SIOCGIWFRAG */
2248 dummy, /* SIOCSIWTXPOW */
2249 dummy, /* SIOCGIWTXPOW */
2250 dummy, /* SIOCSIWRETRY */
2251 r8711_wx_get_retry, /* SIOCGIWRETRY */
2252 r8711_wx_set_enc, /* SIOCSIWENCODE */
2253 r8711_wx_get_enc, /* SIOCGIWENCODE */
2254 dummy, /* SIOCSIWPOWER */
2255 r8711_wx_get_power, /* SIOCGIWPOWER */
2256 NULL, /*---hole---*/
2257 NULL, /*---hole---*/
2258 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2259 NULL, /* SIOCGIWGENIE */
2260 r871x_wx_set_auth, /* SIOCSIWAUTH */
2261 NULL, /* SIOCGIWAUTH */
2262 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2263 NULL, /* SIOCGIWENCODEEXT */
2264 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2265 NULL, /*---hole---*/
2266 };
2267
2268 static const struct iw_priv_args r8711_private_args[] = {
2269 {
2270 SIOCIWFIRSTPRIV + 0x0,
2271 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2272 },
2273 {
2274 SIOCIWFIRSTPRIV + 0x1,
2275 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2276 },
2277 {
2278 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2279 },
2280 {
2281 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2282 },
2283 {
2284 SIOCIWFIRSTPRIV + 0x4,
2285 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2286 },
2287 {
2288 SIOCIWFIRSTPRIV + 0x5,
2289 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2290 },
2291 {
2292 SIOCIWFIRSTPRIV + 0x6,
2293 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2294 },
2295 {
2296 SIOCIWFIRSTPRIV + 0x7,
2297 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2298 }
2299 };
2300
2301 static iw_handler r8711_private_handler[] = {
2302 r8711_wx_read32,
2303 r8711_wx_write32,
2304 r8711_drvext_hdl,
2305 r871x_mp_ioctl_hdl,
2306 r871x_get_ap_info, /*for MM DTV platform*/
2307 r871x_set_pid,
2308 r871x_wps_start,
2309 r871x_set_chplan
2310 };
2311
2312 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2313 {
2314 struct _adapter *padapter = netdev_priv(dev);
2315 struct iw_statistics *piwstats = &padapter->iwstats;
2316 int tmp_level = 0;
2317 int tmp_qual = 0;
2318 int tmp_noise = 0;
2319
2320 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2321 piwstats->qual.qual = 0;
2322 piwstats->qual.level = 0;
2323 piwstats->qual.noise = 0;
2324 } else {
2325 /* show percentage, we need transfer dbm to orignal value. */
2326 tmp_level = padapter->recvpriv.fw_rssi;
2327 tmp_qual = padapter->recvpriv.signal;
2328 tmp_noise = padapter->recvpriv.noise;
2329 piwstats->qual.level = tmp_level;
2330 piwstats->qual.qual = tmp_qual;
2331 piwstats->qual.noise = tmp_noise;
2332 }
2333 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2334 return &padapter->iwstats;
2335 }
2336
2337 struct iw_handler_def r871x_handlers_def = {
2338 .standard = r8711_handlers,
2339 .num_standard = ARRAY_SIZE(r8711_handlers),
2340 .private = r8711_private_handler,
2341 .private_args = (struct iw_priv_args *)r8711_private_args,
2342 .num_private = ARRAY_SIZE(r8711_private_handler),
2343 .num_private_args = sizeof(r8711_private_args) /
2344 sizeof(struct iw_priv_args),
2345 .get_wireless_stats = r871x_get_wireless_stats
2346 };
This page took 0.125218 seconds and 5 git commands to generate.