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