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