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