staging: r8712u: Merging Realtek's latest (v2.6.6). New decl's and defines.
[deliverable/linux.git] / drivers / staging / rtl8712 / rtl871x_ioctl_linux.c
CommitLineData
2865d42c
LF
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_
e3dc896b 30#define _RTL871X_MP_IOCTL_C_
2865d42c
LF
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"
359140aa
AB
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>
2865d42c
LF
51
52#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
53
54#define SCAN_ITEM_SIZE 768
55#define MAX_CUSTOM_LEN 64
56#define RATE_COUNT 4
57
58
59static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
60 6000000, 9000000, 12000000, 18000000,
61 24000000, 36000000, 48000000, 54000000};
62
63static 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
70static const char * const iw_operation_mode[] = {
71 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
72 "Monitor"
73};
74
2865d42c
LF
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)
80 */
81static int hwaddr_aton_i(const char *txt, u8 *addr)
82{
83 int i;
84
85 for (i = 0; i < 6; i++) {
86 int a, b;
87
91facdbe 88 a = hex_to_bin(*txt++);
2865d42c
LF
89 if (a < 0)
90 return -1;
91facdbe 91 b = hex_to_bin(*txt++);
2865d42c
LF
92 if (b < 0)
93 return -1;
94 *addr++ = (a << 4) | b;
95 if (i < 5 && *txt++ != ':')
96 return -1;
97 }
98 return 0;
99}
100
101void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
102{
103 union iwreq_data wrqu;
104 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
105
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);
110}
111
112void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
113{
114 union iwreq_data wrqu;
115
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);
119}
120
121static inline void handle_pairwise_key(struct sta_info *psta,
122 struct ieee_param *param,
123 struct _adapter *padapter)
124{
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);
135 }
136 r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
137}
138
139static inline void handle_group_key(struct ieee_param *param,
140 struct _adapter *padapter)
141{
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);
160 }
161 }
162}
163
164static inline char *translate_scan(struct _adapter *padapter,
165 struct iw_request_info *info,
166 struct wlan_network *pnetwork,
167 char *start, char *stop)
168{
169 struct iw_event iwe;
170 struct ieee80211_ht_cap *pht_capie;
171 char *current_val;
2865d42c
LF
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;
176
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;
183 }
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;
207 }
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");
227 }
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),
232 2);
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);
241 }
242 /* Add frequency/channel */
243 iwe.cmd = SIOCGIWFREQ;
244 {
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;
254 }
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);
282 }
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 */
287 {
c13b6f24
AB
288 u8 buf[MAX_WPA_IE_LEN];
289 u8 wpa_ie[255], rsn_ie[255];
2865d42c 290 u16 wpa_len = 0, rsn_len = 0;
d936435f 291 int n;
2865d42c
LF
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) {
2865d42c 298 memset(buf, 0, MAX_WPA_IE_LEN);
d936435f
DC
299 n = sprintf(buf, "wpa_ie=");
300 for (i = 0; i < wpa_len; i++) {
2657c30e
JM
301 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
302 "%02x", wpa_ie[i]);
d936435f
DC
303 if (n >= MAX_WPA_IE_LEN)
304 break;
305 }
2865d42c
LF
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);
316 }
317 if (rsn_len > 0) {
2865d42c 318 memset(buf, 0, MAX_WPA_IE_LEN);
d936435f
DC
319 n = sprintf(buf, "rsn_ie=");
320 for (i = 0; i < rsn_len; i++) {
2657c30e
JM
321 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
322 "%02x", rsn_ie[i]);
d936435f
DC
323 if (n >= MAX_WPA_IE_LEN)
324 break;
325 }
2865d42c
LF
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);
336 }
337 }
338
339 { /* parsing WPS IE */
c13b6f24 340 u8 wps_ie[512];
2865d42c
LF
341 uint wps_ielen;
342
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);
351 }
352 }
353 }
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 ?% */
2865d42c
LF
365 return start;
366}
367
368static int wpa_set_auth_algs(struct net_device *dev, u32 value)
369{
7c1f4203 370 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
371 int ret = 0;
372
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;
390 }
391 } else
392 ret = -EINVAL;
393 return ret;
394}
395
396static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
397 u32 param_len)
398{
399 int ret = 0;
400 u32 wep_key_idx, wep_key_len = 0;
401 struct NDIS_802_11_WEP *pwep = NULL;
7c1f4203 402 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
403 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
404 struct security_priv *psecuritypriv = &padapter->securitypriv;
405
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;
417 }
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_;
449 }
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
463 */
464 if (wep_key_idx >= WEP_KEYS) {
465 ret = -EOPNOTSUPP;
466 goto exit;
467 }
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);
474 }
475 goto exit;
476 }
477 if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
478 struct sta_info *psta, *pbcmc_sta;
479 struct sta_priv *pstapriv = &padapter->stapriv;
480
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);
498 }
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;
509 }
510 }
511 }
512exit:
513 kfree((u8 *)pwep);
514 return ret;
515}
516
517static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
518 unsigned short ielen)
519{
520 u8 *buf = NULL, *pos = NULL;
521 int group_cipher = 0, pairwise_cipher = 0;
522 int ret = 0;
523
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 = -1;
534 goto exit;
535 }
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;
541 }
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;
547 }
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;
575 }
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;
603 }
604 padapter->securitypriv.wps_phase = false;
605 {/* set wps_ie */
606 u16 cnt = 0;
607 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
608
609 while (cnt < ielen) {
610 eid = buf[cnt];
611
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;
632 }
633 }
634 }
635exit:
636 kfree(buf);
637 return ret;
638}
639
640static int r8711_wx_get_name(struct net_device *dev,
641 struct iw_request_info *info,
642 union iwreq_data *wrqu, char *extra)
643{
7c1f4203 644 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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;
651
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");
681 }
682 } else
683 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
684 return 0;
685}
686
687static 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
694};
695
696static int r8711_wx_set_freq(struct net_device *dev,
697 struct iw_request_info *info,
698 union iwreq_data *wrqu, char *extra)
699{
7c1f4203 700 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
701 struct iw_freq *fwrq = &wrqu->freq;
702 int rc = 0;
703
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;
714 }
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;
725 }
726 }
727 return rc;
728}
729
730static int r8711_wx_get_freq(struct net_device *dev,
731 struct iw_request_info *info,
732 union iwreq_data *wrqu, char *extra)
733{
7c1f4203 734 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
735 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
736 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
737
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 -1;
745 return 0;
746}
747
748static int r8711_wx_set_mode(struct net_device *dev,
749 struct iw_request_info *a,
750 union iwreq_data *wrqu, char *b)
751{
7c1f4203 752 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
753 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
754
755 switch (wrqu->mode) {
756 case IW_MODE_AUTO:
757 networkType = Ndis802_11AutoUnknown;
758 break;
759 case IW_MODE_ADHOC:
760 networkType = Ndis802_11IBSS;
761 break;
762 case IW_MODE_MASTER:
763 networkType = Ndis802_11APMode;
764 break;
765 case IW_MODE_INFRA:
766 networkType = Ndis802_11Infrastructure;
767 break;
768 default:
769 return -EINVAL;
770 }
771 if (Ndis802_11APMode == networkType)
772 r8712_setopmode_cmd(padapter, networkType);
773 else
774 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
775 if (!r8712_set_802_11_infrastructure_mode(padapter, networkType))
776 return -1;
777 return 0;
778}
779
780static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
781 union iwreq_data *wrqu, char *b)
782{
7c1f4203 783 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
784 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
785
786 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
787 wrqu->mode = IW_MODE_INFRA;
788 else if (check_fwstate(pmlmepriv,
789 WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
790 wrqu->mode = IW_MODE_ADHOC;
791 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
792 wrqu->mode = IW_MODE_MASTER;
793 else
794 wrqu->mode = IW_MODE_AUTO;
795 return 0;
796}
797
798static int r871x_wx_set_pmkid(struct net_device *dev,
799 struct iw_request_info *a,
800 union iwreq_data *wrqu, char *extra)
801{
7c1f4203 802 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
803 struct security_priv *psecuritypriv = &padapter->securitypriv;
804 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
805 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
806 u8 strIssueBssid[ETH_ALEN] = {0x00};
807 u8 j, blInserted = false;
808 int intReturn = false;
809
810/*
811 There are the BSSID information in the bssid.sa_data array.
812 If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear
813 all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
814 wpa_supplicant wants to add a PMKID/BSSID to driver.
815 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
816 remove a PMKID/BSSID from driver.
817*/
818 if (pPMK == NULL)
819 return -EINVAL;
820 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
821 switch (pPMK->cmd) {
822 case IW_PMKSA_ADD:
823 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
824 return intReturn;
825 else
826 intReturn = true;
827 blInserted = false;
828 /* overwrite PMKID */
829 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
830 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
831 strIssueBssid, ETH_ALEN)) {
832 /* BSSID is matched, the same AP => rewrite
833 * with new PMKID. */
834 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid:"
835 " BSSID exists in the PMKList.\n");
836 memcpy(psecuritypriv->PMKIDList[j].PMKID,
837 pPMK->pmkid, IW_PMKID_LEN);
838 psecuritypriv->PMKIDList[j].bUsed = true;
839 psecuritypriv->PMKIDIndex = j + 1;
840 blInserted = true;
841 break;
842 }
843 }
844 if (!blInserted) {
845 /* Find a new entry */
846 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: Use the"
847 " new entry index = %d for this PMKID.\n",
848 psecuritypriv->PMKIDIndex);
849 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
850 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
851 memcpy(psecuritypriv->PMKIDList[psecuritypriv->
852 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
853 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
854 bUsed = true;
855 psecuritypriv->PMKIDIndex++ ;
856 if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
857 psecuritypriv->PMKIDIndex = 0;
858 }
859 break;
860 case IW_PMKSA_REMOVE:
861 intReturn = true;
862 for (j = 0; j < NUM_PMKID_CACHE; j++) {
863 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
864 strIssueBssid, ETH_ALEN)) {
865 /* BSSID is matched, the same AP => Remove
866 * this PMKID information and reset it. */
867 memset(psecuritypriv->PMKIDList[j].Bssid,
868 0x00, ETH_ALEN);
869 psecuritypriv->PMKIDList[j].bUsed = false;
870 break;
871 }
872 }
873 break;
874 case IW_PMKSA_FLUSH:
875 memset(psecuritypriv->PMKIDList, 0,
876 sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
877 psecuritypriv->PMKIDIndex = 0;
878 intReturn = true;
879 break;
880 default:
881 printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: "
882 "unknown Command\n");
883 intReturn = false;
884 break;
885 }
886 return intReturn;
887}
888
889static int r8711_wx_get_sens(struct net_device *dev,
890 struct iw_request_info *info,
891 union iwreq_data *wrqu, char *extra)
892{
893 wrqu->sens.value = 0;
894 wrqu->sens.fixed = 0; /* no auto select */
895 wrqu->sens.disabled = 1;
896 return 0;
897}
898
899static int r8711_wx_get_range(struct net_device *dev,
900 struct iw_request_info *info,
901 union iwreq_data *wrqu, char *extra)
902{
903 struct iw_range *range = (struct iw_range *)extra;
904 u16 val;
905 int i;
906
907 wrqu->data.length = sizeof(*range);
908 memset(range, 0, sizeof(*range));
909 /* Let's try to keep this struct in the same order as in
910 * linux/include/wireless.h
911 */
912
913 /* TODO: See what values we can set, and remove the ones we can't
914 * set, or fill them with some default data.
915 */
916 /* ~5 Mb/s real (802.11b) */
917 range->throughput = 5 * 1000 * 1000;
918 /* TODO: 8711 sensitivity ? */
919 /* signal level threshold range */
920 /* percent values between 0 and 100. */
921 range->max_qual.qual = 100;
922 range->max_qual.level = 100;
923 range->max_qual.noise = 100;
924 range->max_qual.updated = 7; /* Updated all three */
925 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
926 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
927 range->avg_qual.level = 20 + -98;
928 range->avg_qual.noise = 0;
929 range->avg_qual.updated = 7; /* Updated all three */
930 range->num_bitrates = RATE_COUNT;
931 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
932 range->bitrate[i] = rtl8180_rates[i];
933 range->min_frag = MIN_FRAG_THRESHOLD;
934 range->max_frag = MAX_FRAG_THRESHOLD;
935 range->pm_capa = 0;
936 range->we_version_compiled = WIRELESS_EXT;
937 range->we_version_source = 16;
938 range->num_channels = 14;
939 for (i = 0, val = 0; i < 14; i++) {
940 /* Include only legal frequencies for some countries */
941 range->freq[val].i = i + 1;
942 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
943 range->freq[val].e = 1;
944 val++;
945 if (val == IW_MAX_FREQUENCIES)
946 break;
947 }
948 range->num_frequency = val;
949 range->enc_capa = IW_ENC_CAPA_WPA |
950 IW_ENC_CAPA_WPA2 |
951 IW_ENC_CAPA_CIPHER_TKIP |
952 IW_ENC_CAPA_CIPHER_CCMP;
953 return 0;
954}
955
956static int r871x_wx_set_priv(struct net_device *dev,
957 struct iw_request_info *info,
958 union iwreq_data *awrq,
959 char *extra)
960{
961 int ret = 0, len = 0;
962 char *ext;
963 struct iw_point *dwrq = (struct iw_point *)awrq;
964
965 len = dwrq->length;
966 ext = _malloc(len);
4495c15f 967 if (!ext)
2865d42c
LF
968 return -ENOMEM;
969 if (copy_from_user(ext, dwrq->pointer, len)) {
970 kfree(ext);
971 return -EFAULT;
972 }
973 kfree(ext);
974 return ret;
975}
976
977/* set bssid flow
978 * s1. set_802_11_infrastructure_mode()
979 * s2. set_802_11_authentication_mode()
980 * s3. set_802_11_encryption_mode()
981 * s4. set_802_11_bssid()
d1661dfd
AB
982 *
983 * This function intends to handle the Set AP command, which specifies the
984 * MAC# of a preferred Access Point.
985 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
986 *
987 * For this operation to succeed, there is no need for the interface to be Up.
988 *
2865d42c
LF
989 */
990static int r8711_wx_set_wap(struct net_device *dev,
991 struct iw_request_info *info,
992 union iwreq_data *awrq,
993 char *extra)
994{
995 int ret = -EINPROGRESS;
7c1f4203 996 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
997 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
998 struct __queue *queue = &pmlmepriv->scanned_queue;
999 struct sockaddr *temp = (struct sockaddr *)awrq;
1000 unsigned long irqL;
1001 struct list_head *phead;
1002 u8 *dst_bssid;
1003 struct wlan_network *pnetwork = NULL;
1004 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1005
2865d42c
LF
1006 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1007 return -1;
1008 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1009 return ret;
1010 if (temp->sa_family != ARPHRD_ETHER)
1011 return -EINVAL;
1012 authmode = padapter->securitypriv.ndisauthtype;
1013 spin_lock_irqsave(&queue->lock, irqL);
1014 phead = get_list_head(queue);
1015 pmlmepriv->pscanned = get_next(phead);
1016 while (1) {
1017 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1018 break;
1019 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1020 struct wlan_network, list);
1021 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1022 dst_bssid = pnetwork->network.MacAddress;
1023 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1024 if (r8712_set_802_11_infrastructure_mode(padapter,
1025 pnetwork->network.InfrastructureMode) == false)
1026 ret = -1;
1027 break;
1028 }
1029 }
1030 spin_unlock_irqrestore(&queue->lock, irqL);
1031 if (!ret) {
1032 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1033 ret = -1;
1034 else {
1035 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1036 ret = -1;
1037 }
1038 }
1039 return ret;
1040}
1041
1042static int r8711_wx_get_wap(struct net_device *dev,
1043 struct iw_request_info *info,
1044 union iwreq_data *wrqu, char *extra)
1045{
7c1f4203 1046 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1047 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1048 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1049
1050 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1051 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1052 if (check_fwstate(pmlmepriv, _FW_LINKED |
1053 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
1054 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1055 }
1056 return 0;
1057}
1058
1059static int r871x_wx_set_mlme(struct net_device *dev,
1060 struct iw_request_info *info,
1061 union iwreq_data *wrqu, char *extra)
1062{
1063 int ret = 0;
1064 u16 reason;
7c1f4203 1065 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1066 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1067
1068 if (mlme == NULL)
1069 return -1;
1070 reason = cpu_to_le16(mlme->reason_code);
1071 switch (mlme->cmd) {
1072 case IW_MLME_DEAUTH:
1073 if (!r8712_set_802_11_disassociate(padapter))
1074 ret = -1;
1075 break;
1076 case IW_MLME_DISASSOC:
1077 if (!r8712_set_802_11_disassociate(padapter))
1078 ret = -1;
1079 break;
1080 default:
1081 return -EOPNOTSUPP;
1082 }
1083 return ret;
1084}
1085
d1661dfd
AB
1086/**
1087 *
1088 * This function intends to handle the Set Scan command.
1089 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1090 *
1091 * For this operation to succeed, the interface is brought Up beforehand.
1092 *
1093 */
2865d42c
LF
1094static int r8711_wx_set_scan(struct net_device *dev,
1095 struct iw_request_info *a,
1096 union iwreq_data *wrqu, char *extra)
1097{
7c1f4203 1098 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1099 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1100 u8 status = true;
1101
1102 if (padapter->bDriverStopped == true) {
1103 printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
1104 "bDriverStopped=%d\n", padapter->bDriverStopped);
1105 return -1;
1106 }
1107 if (padapter->bup == false)
1108 return -1;
1109 if (padapter->hw_init_completed == false)
1110 return -1;
1111 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1112 (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1113 return 0;
1114 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1115 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1116 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1117 struct ndis_802_11_ssid ssid;
1118 unsigned long irqL;
1119 u32 len = (u32) min((u8)req->essid_len,
1120 (u8)IW_ESSID_MAX_SIZE);
1121 memset((unsigned char *)&ssid, 0,
1122 sizeof(struct ndis_802_11_ssid));
1123 memcpy(ssid.Ssid, req->essid, len);
1124 ssid.SsidLength = len;
1125 spin_lock_irqsave(&pmlmepriv->lock, irqL);
1126 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1127 _FW_UNDER_LINKING)) ||
1128 (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1129 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1130 status = false;
1131 } else
1132 status = r8712_sitesurvey_cmd(padapter, &ssid);
1133 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1134 }
1135 } else
1136 status = r8712_set_802_11_bssid_list_scan(padapter);
1137 if (status == false)
1138 return -1;
1139 return 0;
1140}
1141
1142static int r8711_wx_get_scan(struct net_device *dev,
1143 struct iw_request_info *a,
1144 union iwreq_data *wrqu, char *extra)
1145{
7c1f4203 1146 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1147 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1148 struct __queue *queue = &pmlmepriv->scanned_queue;
1149 struct wlan_network *pnetwork = NULL;
1150 unsigned long irqL;
1151 struct list_head *plist, *phead;
1152 char *ev = extra;
1153 char *stop = ev + wrqu->data.length;
1154 u32 ret = 0, cnt = 0;
1155
1156 if (padapter->bDriverStopped)
1157 return -EINVAL;
1158 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1159 msleep(30);
1160 cnt++;
1161 if (cnt > 1000)
1162 break;
1163 }
1164 spin_lock_irqsave(&queue->lock, irqL);
1165 phead = get_list_head(queue);
1166 plist = get_next(phead);
1167 while (1) {
1168 if (end_of_queue_search(phead, plist) == true)
1169 break;
1170 if ((stop - ev) < SCAN_ITEM_SIZE) {
1171 ret = -E2BIG;
1172 break;
1173 }
1174 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1175 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1176 plist = get_next(plist);
1177 }
1178 spin_unlock_irqrestore(&queue->lock, irqL);
1179 wrqu->data.length = ev - extra;
1180 wrqu->data.flags = 0;
1181 return ret;
1182}
1183
1184/* set ssid flow
1185 * s1. set_802_11_infrastructure_mode()
1186 * s2. set_802_11_authenticaion_mode()
1187 * s3. set_802_11_encryption_mode()
1188 * s4. set_802_11_ssid()
d1661dfd
AB
1189 *
1190 * This function intends to handle the Set ESSID command.
1191 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1192 *
1193 * For this operation to succeed, there is no need for the interface to be Up.
1194 *
2865d42c
LF
1195 */
1196static int r8711_wx_set_essid(struct net_device *dev,
1197 struct iw_request_info *a,
1198 union iwreq_data *wrqu, char *extra)
1199{
7c1f4203 1200 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1201 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1202 struct __queue *queue = &pmlmepriv->scanned_queue;
1203 struct wlan_network *pnetwork = NULL;
1204 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1205 struct ndis_802_11_ssid ndis_ssid;
1206 u8 *dst_ssid, *src_ssid;
1207 struct list_head *phead;
1208 u32 len;
1209
2865d42c
LF
1210 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1211 return -1;
1212 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1213 return 0;
1214 if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1215 return -E2BIG;
1216 authmode = padapter->securitypriv.ndisauthtype;
1217 if (wrqu->essid.flags && wrqu->essid.length) {
1218 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1219 wrqu->essid.length : IW_ESSID_MAX_SIZE;
1220 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1221 ndis_ssid.SsidLength = len;
1222 memcpy(ndis_ssid.Ssid, extra, len);
1223 src_ssid = ndis_ssid.Ssid;
1224 phead = get_list_head(queue);
1225 pmlmepriv->pscanned = get_next(phead);
1226 while (1) {
1227 if (end_of_queue_search(phead, pmlmepriv->pscanned))
1228 break;
1229 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1230 struct wlan_network, list);
1231 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1232 dst_ssid = pnetwork->network.Ssid.Ssid;
1233 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1234 && (pnetwork->network.Ssid.SsidLength ==
1235 ndis_ssid.SsidLength)) {
1236 if (!r8712_set_802_11_infrastructure_mode(
1237 padapter,
1238 pnetwork->network.InfrastructureMode))
1239 return -1;
1240 break;
1241 }
1242 }
1243 r8712_set_802_11_authentication_mode(padapter, authmode);
1244 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1245 }
1246 return -EINPROGRESS;
1247}
1248
1249static int r8711_wx_get_essid(struct net_device *dev,
1250 struct iw_request_info *a,
1251 union iwreq_data *wrqu, char *extra)
1252{
7c1f4203 1253 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1254 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1255 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1256 u32 len, ret = 0;
1257
1258 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1259 len = pcur_bss->Ssid.SsidLength;
1260 wrqu->essid.length = len;
1261 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1262 wrqu->essid.flags = 1;
1263 } else
1264 ret = -1;
1265 return ret;
1266}
1267
1268static int r8711_wx_set_rate(struct net_device *dev,
1269 struct iw_request_info *a,
1270 union iwreq_data *wrqu, char *extra)
1271{
7c1f4203 1272 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1273 u32 target_rate = wrqu->bitrate.value;
1274 u32 fixed = wrqu->bitrate.fixed;
1275 u32 ratevalue = 0;
1276 u8 datarates[NumRates];
1277 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1278 int i, ret = 0;
1279
1280 if (target_rate == -1) {
1281 ratevalue = 11;
1282 goto set_rate;
1283 }
1284 target_rate = target_rate / 100000;
1285 switch (target_rate) {
1286 case 10:
1287 ratevalue = 0;
1288 break;
1289 case 20:
1290 ratevalue = 1;
1291 break;
1292 case 55:
1293 ratevalue = 2;
1294 break;
1295 case 60:
1296 ratevalue = 3;
1297 break;
1298 case 90:
1299 ratevalue = 4;
1300 break;
1301 case 110:
1302 ratevalue = 5;
1303 break;
1304 case 120:
1305 ratevalue = 6;
1306 break;
1307 case 180:
1308 ratevalue = 7;
1309 break;
1310 case 240:
1311 ratevalue = 8;
1312 break;
1313 case 360:
1314 ratevalue = 9;
1315 break;
1316 case 480:
1317 ratevalue = 10;
1318 break;
1319 case 540:
1320 ratevalue = 11;
1321 break;
1322 default:
1323 ratevalue = 11;
1324 break;
1325 }
1326set_rate:
1327 for (i = 0; i < NumRates; i++) {
1328 if (ratevalue == mpdatarate[i]) {
1329 datarates[i] = mpdatarate[i];
1330 if (fixed == 0)
1331 break;
1332 } else
1333 datarates[i] = 0xff;
1334 }
1335 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1336 ret = -1;
1337 return ret;
1338}
1339
1340static int r8711_wx_get_rate(struct net_device *dev,
1341 struct iw_request_info *info,
1342 union iwreq_data *wrqu, char *extra)
1343{
7c1f4203 1344 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1345 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1346 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1347 struct ieee80211_ht_cap *pht_capie;
1348 int i;
1349 u8 *p;
1350 u16 rate, max_rate = 0, ht_cap = false;
1351 u32 ht_ielen = 0;
1352 u8 bw_40MHz = 0, short_GI = 0;
1353 u16 mcs_rate = 0;
1354
1355 i = 0;
1356 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1357 p = r8712_get_ie(&pcur_bss->IEs[12],
1358 _HT_CAPABILITY_IE_, &ht_ielen,
1359 pcur_bss->IELength - 12);
1360 if (p && ht_ielen > 0) {
1361 ht_cap = true;
1362 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1363 memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1364 bw_40MHz = (pht_capie->cap_info &
1365 IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1366 short_GI = (pht_capie->cap_info &
1367 (IEEE80211_HT_CAP_SGI_20 |
1368 IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1369 }
1370 while ((pcur_bss->SupportedRates[i] != 0) &&
1371 (pcur_bss->SupportedRates[i] != 0xFF)) {
1372 rate = pcur_bss->SupportedRates[i] & 0x7F;
1373 if (rate > max_rate)
1374 max_rate = rate;
1375 wrqu->bitrate.fixed = 0; /* no auto select */
1376 wrqu->bitrate.value = rate*500000;
1377 i++;
1378 }
1379 if (ht_cap == true) {
1380 if (mcs_rate & 0x8000) /* MCS15 */
1381 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1382 270) : ((short_GI) ? 144 : 130);
1383 else if (mcs_rate & 0x0080) /* MCS7 */
1384 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1385 135) : ((short_GI) ? 72 : 65);
1386 else /* default MCS7 */
1387 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1388 135) : ((short_GI) ? 72 : 65);
1389 max_rate *= 2; /* Mbps/2 */
1390 wrqu->bitrate.value = max_rate * 500000;
1407a9e1
LF
1391 } else {
1392 wrqu->bitrate.value = max_rate * 500000;
2865d42c
LF
1393 }
1394 } else
1395 return -1;
1396 return 0;
1397}
1398
1399static int r8711_wx_get_rts(struct net_device *dev,
1400 struct iw_request_info *info,
1401 union iwreq_data *wrqu, char *extra)
1402{
7c1f4203 1403 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1404
1405 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1406 wrqu->rts.fixed = 0; /* no auto select */
1407 return 0;
1408}
1409
1410static int r8711_wx_set_frag(struct net_device *dev,
1411 struct iw_request_info *info,
1412 union iwreq_data *wrqu, char *extra)
1413{
7c1f4203 1414 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1415
1416 if (wrqu->frag.disabled)
1417 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1418 else {
1419 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1420 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1421 return -EINVAL;
1422 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1423 }
1424 return 0;
1425}
1426
1427static int r8711_wx_get_frag(struct net_device *dev,
1428 struct iw_request_info *info,
1429 union iwreq_data *wrqu, char *extra)
1430{
7c1f4203 1431 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1432
1433 wrqu->frag.value = padapter->xmitpriv.frag_len;
1434 wrqu->frag.fixed = 0; /* no auto select */
1435 return 0;
1436}
1437
1438static int r8711_wx_get_retry(struct net_device *dev,
1439 struct iw_request_info *info,
1440 union iwreq_data *wrqu, char *extra)
1441{
1442 wrqu->retry.value = 7;
1443 wrqu->retry.fixed = 0; /* no auto select */
1444 wrqu->retry.disabled = 1;
1445 return 0;
1446}
1447
1448static int r8711_wx_set_enc(struct net_device *dev,
1449 struct iw_request_info *info,
1450 union iwreq_data *wrqu, char *keybuf)
1451{
1452 u32 key;
1453 u32 keyindex_provided;
1454 struct NDIS_802_11_WEP wep;
1455 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1456 struct iw_point *erq = &(wrqu->encoding);
7c1f4203 1457 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1458
1459 key = erq->flags & IW_ENCODE_INDEX;
1460 memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1461 if (erq->flags & IW_ENCODE_DISABLED) {
1462 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1463 "EncryptionDisabled\n");
1464 padapter->securitypriv.ndisencryptstatus =
1465 Ndis802_11EncryptionDisabled;
1466 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1467 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1468 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1469 authmode = Ndis802_11AuthModeOpen;
1470 padapter->securitypriv.ndisauthtype = authmode;
1471 return 0;
1472 }
1473 if (key) {
1474 if (key > WEP_KEYS)
1475 return -EINVAL;
1476 key--;
1477 keyindex_provided = 1;
1478 } else {
1479 keyindex_provided = 0;
1480 key = padapter->securitypriv.PrivacyKeyIndex;
1481 }
1482 /* set authentication mode */
1483 if (erq->flags & IW_ENCODE_OPEN) {
1484 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1485 "IW_ENCODE_OPEN\n");
1486 padapter->securitypriv.ndisencryptstatus =
1487 Ndis802_11Encryption1Enabled;
1488 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1489 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1490 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1491 authmode = Ndis802_11AuthModeOpen;
1492 padapter->securitypriv.ndisauthtype = authmode;
1493 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1494 printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1495 "IW_ENCODE_RESTRICTED\n");
1496 padapter->securitypriv.ndisencryptstatus =
1497 Ndis802_11Encryption1Enabled;
1498 padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1499 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1500 padapter->securitypriv.XGrpPrivacy = _WEP40_;
1501 authmode = Ndis802_11AuthModeShared;
1502 padapter->securitypriv.ndisauthtype = authmode;
1503 } else {
1504 padapter->securitypriv.ndisencryptstatus =
1505 Ndis802_11Encryption1Enabled;
1506 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1507 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1508 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1509 authmode = Ndis802_11AuthModeOpen;
1510 padapter->securitypriv.ndisauthtype = authmode;
1511 }
1512 wep.KeyIndex = key;
1513 if (erq->length > 0) {
1514 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1515 wep.Length = wep.KeyLength +
1516 FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1517 } else {
1518 wep.KeyLength = 0 ;
1519 if (keyindex_provided == 1) { /* set key_id only, no given
1520 * KeyMaterial(erq->length==0).*/
1521 padapter->securitypriv.PrivacyKeyIndex = key;
1522 switch (padapter->securitypriv.DefKeylen[key]) {
1523 case 5:
1524 padapter->securitypriv.PrivacyAlgrthm =
1525 _WEP40_;
1526 break;
1527 case 13:
1528 padapter->securitypriv.PrivacyAlgrthm =
1529 _WEP104_;
1530 break;
1531 default:
1532 padapter->securitypriv.PrivacyAlgrthm =
1533 _NO_PRIVACY_;
1534 break;
1535 }
1536 return 0;
1537 }
1538 }
1539 wep.KeyIndex |= 0x80000000; /* transmit key */
1540 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1541 if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1542 return -EOPNOTSUPP;
1543 return 0;
1544}
1545
1546static int r8711_wx_get_enc(struct net_device *dev,
1547 struct iw_request_info *info,
1548 union iwreq_data *wrqu, char *keybuf)
1549{
1550 uint key, ret = 0;
7c1f4203 1551 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1552 struct iw_point *erq = &(wrqu->encoding);
1553 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1554
1555 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1556 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1557 erq->length = 0;
1558 erq->flags |= IW_ENCODE_DISABLED;
1559 return 0;
1560 }
1561 }
1562 key = erq->flags & IW_ENCODE_INDEX;
1563 if (key) {
1564 if (key > WEP_KEYS)
1565 return -EINVAL;
1566 key--;
1567 } else {
1568 key = padapter->securitypriv.PrivacyKeyIndex;
1569 }
1570 erq->flags = key + 1;
1571 switch (padapter->securitypriv.ndisencryptstatus) {
1572 case Ndis802_11EncryptionNotSupported:
1573 case Ndis802_11EncryptionDisabled:
1574 erq->length = 0;
1575 erq->flags |= IW_ENCODE_DISABLED;
1576 break;
1577 case Ndis802_11Encryption1Enabled:
1578 erq->length = padapter->securitypriv.DefKeylen[key];
1579 if (erq->length) {
1580 memcpy(keybuf, padapter->securitypriv.DefKey[
1581 key].skey, padapter->securitypriv.
1582 DefKeylen[key]);
1583 erq->flags |= IW_ENCODE_ENABLED;
1584 if (padapter->securitypriv.ndisauthtype ==
1585 Ndis802_11AuthModeOpen)
1586 erq->flags |= IW_ENCODE_OPEN;
1587 else if (padapter->securitypriv.ndisauthtype ==
1588 Ndis802_11AuthModeShared)
1589 erq->flags |= IW_ENCODE_RESTRICTED;
1590 } else {
1591 erq->length = 0;
1592 erq->flags |= IW_ENCODE_DISABLED;
1593 }
1594 break;
1595 case Ndis802_11Encryption2Enabled:
1596 case Ndis802_11Encryption3Enabled:
1597 erq->length = 16;
1598 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
1599 IW_ENCODE_NOKEY);
1600 break;
1601 default:
1602 erq->length = 0;
1603 erq->flags |= IW_ENCODE_DISABLED;
1604 break;
1605 }
1606 return ret;
1607}
1608
1609static int r8711_wx_get_power(struct net_device *dev,
1610 struct iw_request_info *info,
1611 union iwreq_data *wrqu, char *extra)
1612{
1613 wrqu->power.value = 0;
1614 wrqu->power.fixed = 0; /* no auto select */
1615 wrqu->power.disabled = 1;
1616 return 0;
1617}
1618
1619static int r871x_wx_set_gen_ie(struct net_device *dev,
1620 struct iw_request_info *info,
1621 union iwreq_data *wrqu, char *extra)
1622{
7c1f4203 1623 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1624
1625 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1626}
1627
1628static int r871x_wx_set_auth(struct net_device *dev,
1629 struct iw_request_info *info,
1630 union iwreq_data *wrqu, char *extra)
1631{
7c1f4203 1632 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1633 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1634 int paramid;
1635 int paramval;
1636 int ret = 0;
1637
1638 paramid = param->flags & IW_AUTH_INDEX;
1639 paramval = param->value;
1640 switch (paramid) {
1641 case IW_AUTH_WPA_VERSION:
1642 break;
1643 case IW_AUTH_CIPHER_PAIRWISE:
1644 break;
1645 case IW_AUTH_CIPHER_GROUP:
1646 break;
1647 case IW_AUTH_KEY_MGMT:
1648 /*
1649 * ??? does not use these parameters
1650 */
1651 break;
1652 case IW_AUTH_TKIP_COUNTERMEASURES:
1653 if (paramval) {
1654 /* wpa_supplicant is enabling tkip countermeasure. */
1655 padapter->securitypriv.btkip_countermeasure = true;
1656 } else {
1657 /* wpa_supplicant is disabling tkip countermeasure. */
1658 padapter->securitypriv.btkip_countermeasure = false;
1659 }
1660 break;
1661 case IW_AUTH_DROP_UNENCRYPTED:
1662 /* HACK:
1663 *
1664 * wpa_supplicant calls set_wpa_enabled when the driver
1665 * is loaded and unloaded, regardless of if WPA is being
1666 * used. No other calls are made which can be used to
1667 * determine if encryption will be used or not prior to
1668 * association being expected. If encryption is not being
1669 * used, drop_unencrypted is set to false, else true -- we
1670 * can use this to determine if the CAP_PRIVACY_ON bit should
1671 * be set.
1672 */
1673 if (padapter->securitypriv.ndisencryptstatus ==
1674 Ndis802_11Encryption1Enabled) {
1675 /* it means init value, or using wep,
1676 * ndisencryptstatus =
1677 * Ndis802_11Encryption1Enabled,
1678 * then it needn't reset it;
1679 */
1680 break;
1681 }
1682
1683 if (paramval) {
1684 padapter->securitypriv.ndisencryptstatus =
1685 Ndis802_11EncryptionDisabled;
1686 padapter->securitypriv.PrivacyAlgrthm =
1687 _NO_PRIVACY_;
1688 padapter->securitypriv.XGrpPrivacy =
1689 _NO_PRIVACY_;
1690 padapter->securitypriv.AuthAlgrthm = 0;
1691 padapter->securitypriv.ndisauthtype =
1692 Ndis802_11AuthModeOpen;
1693 }
1694 break;
1695 case IW_AUTH_80211_AUTH_ALG:
1696 ret = wpa_set_auth_algs(dev, (u32)paramval);
1697 break;
1698 case IW_AUTH_WPA_ENABLED:
1699 break;
1700 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1701 break;
1702 case IW_AUTH_PRIVACY_INVOKED:
1703 break;
1704 default:
1705 return -EOPNOTSUPP;
1706 }
1707
1708 return ret;
1709}
1710
1711static int r871x_wx_set_enc_ext(struct net_device *dev,
1712 struct iw_request_info *info,
1713 union iwreq_data *wrqu, char *extra)
1714{
1715 struct iw_point *pencoding = &wrqu->encoding;
1716 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1717 struct ieee_param *param = NULL;
1718 char *alg_name;
1719 u32 param_len;
1720 int ret = 0;
1721
1722 param_len = sizeof(struct ieee_param) + pext->key_len;
1723 param = (struct ieee_param *)_malloc(param_len);
1724 if (param == NULL)
1725 return -1;
1726 memset(param, 0, param_len);
1727 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1728 memset(param->sta_addr, 0xff, ETH_ALEN);
1729 switch (pext->alg) {
1730 case IW_ENCODE_ALG_NONE:
1731 alg_name = "none";
1732 break;
1733 case IW_ENCODE_ALG_WEP:
1734 alg_name = "WEP";
1735 break;
1736 case IW_ENCODE_ALG_TKIP:
1737 alg_name = "TKIP";
1738 break;
1739 case IW_ENCODE_ALG_CCMP:
1740 alg_name = "CCMP";
1741 break;
1742 default:
1743 return -1;
1744 }
1745 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1746 if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1747 param->u.crypt.set_tx = 0;
1748 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1749 param->u.crypt.set_tx = 1;
1750 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1751 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1752 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1753 if (pext->key_len) {
1754 param->u.crypt.key_len = pext->key_len;
1755 memcpy(param + 1, pext + 1, pext->key_len);
1756 }
1757 ret = wpa_set_encryption(dev, param, param_len);
40083865 1758 kfree(param);
2865d42c
LF
1759 return ret;
1760}
1761
1762static int r871x_wx_get_nick(struct net_device *dev,
1763 struct iw_request_info *info,
1764 union iwreq_data *wrqu, char *extra)
1765{
1766 if (extra) {
1767 wrqu->data.length = 8;
1768 wrqu->data.flags = 1;
1769 memcpy(extra, "rtl_wifi", 8);
1770 }
1771 return 0;
1772}
1773
1774static int r8711_wx_read32(struct net_device *dev,
1775 struct iw_request_info *info,
1776 union iwreq_data *wrqu, char *keybuf)
1777{
7c1f4203 1778 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1779 u32 addr;
1780 u32 data32;
1781
1782 get_user(addr, (u32 __user *)wrqu->data.pointer);
1783 data32 = r8712_read32(padapter, addr);
1784 put_user(data32, (u32 __user *)wrqu->data.pointer);
1785 wrqu->data.length = (data32 & 0xffff0000) >> 16;
1786 wrqu->data.flags = data32 & 0xffff;
1787 get_user(addr, (u32 __user *)wrqu->data.pointer);
1788 return 0;
1789}
1790
1791static int r8711_wx_write32(struct net_device *dev,
1792 struct iw_request_info *info,
1793 union iwreq_data *wrqu, char *keybuf)
1794{
7c1f4203 1795 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1796 u32 addr;
1797 u32 data32;
1798
1799 get_user(addr, (u32 __user *)wrqu->data.pointer);
1800 data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
1801 r8712_write32(padapter, addr, data32);
1802 return 0;
1803}
1804
1805static int dummy(struct net_device *dev,
1806 struct iw_request_info *a,
1807 union iwreq_data *wrqu, char *b)
1808{
1809 return -1;
1810}
1811
1812static int r8711_drvext_hdl(struct net_device *dev,
1813 struct iw_request_info *info,
1814 union iwreq_data *wrqu, char *extra)
1815{
1816 return 0;
1817}
1818
1819static int r871x_mp_ioctl_hdl(struct net_device *dev,
1820 struct iw_request_info *info,
1821 union iwreq_data *wrqu, char *extra)
1822{
7c1f4203 1823 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1824 struct iw_point *p = &wrqu->data;
1825 struct oid_par_priv oid_par;
1826 struct mp_ioctl_handler *phandler;
1827 struct mp_ioctl_param *poidparam;
1828 unsigned long BytesRead, BytesWritten, BytesNeeded;
1829 u8 *pparmbuf = NULL, bset;
1830 u16 len;
1831 uint status;
1832 int ret = 0;
1833
1834 if ((!p->length) || (!p->pointer)) {
1835 ret = -EINVAL;
1836 goto _r871x_mp_ioctl_hdl_exit;
1837 }
1838 bset = (u8)(p->flags & 0xFFFF);
1839 len = p->length;
1840 pparmbuf = NULL;
1841 pparmbuf = (u8 *)_malloc(len);
1842 if (pparmbuf == NULL) {
1843 ret = -ENOMEM;
1844 goto _r871x_mp_ioctl_hdl_exit;
1845 }
1846 if (copy_from_user(pparmbuf, p->pointer, len)) {
1847 ret = -EFAULT;
1848 goto _r871x_mp_ioctl_hdl_exit;
1849 }
1850 poidparam = (struct mp_ioctl_param *)pparmbuf;
1851 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1852 ret = -EINVAL;
1853 goto _r871x_mp_ioctl_hdl_exit;
1854 }
1855 phandler = mp_ioctl_hdl + poidparam->subcode;
1856 if ((phandler->paramsize != 0) &&
1857 (poidparam->len < phandler->paramsize)) {
1858 ret = -EINVAL;
1859 goto _r871x_mp_ioctl_hdl_exit;
1860 }
1861 if (phandler->oid == 0 && phandler->handler)
1862 status = phandler->handler(&oid_par);
1863 else if (phandler->handler) {
1864 oid_par.adapter_context = padapter;
1865 oid_par.oid = phandler->oid;
1866 oid_par.information_buf = poidparam->data;
1867 oid_par.information_buf_len = poidparam->len;
1868 oid_par.dbg = 0;
1869 BytesWritten = 0;
1870 BytesNeeded = 0;
1871 if (bset) {
1872 oid_par.bytes_rw = &BytesRead;
1873 oid_par.bytes_needed = &BytesNeeded;
1874 oid_par.type_of_oid = SET_OID;
1875 } else {
1876 oid_par.bytes_rw = &BytesWritten;
1877 oid_par.bytes_needed = &BytesNeeded;
1878 oid_par.type_of_oid = QUERY_OID;
1879 }
1880 status = phandler->handler(&oid_par);
1881 /* todo:check status, BytesNeeded, etc. */
1882 } else {
1883 printk(KERN_INFO "r8712u: r871x_mp_ioctl_hdl(): err!,"
1884 " subcode=%d, oid=%d, handler=%p\n",
1885 poidparam->subcode, phandler->oid, phandler->handler);
1886 ret = -EFAULT;
1887 goto _r871x_mp_ioctl_hdl_exit;
1888 }
1889 if (bset == 0x00) { /* query info */
1890 if (copy_to_user(p->pointer, pparmbuf, len))
1891 ret = -EFAULT;
1892 }
1893 if (status) {
1894 ret = -EFAULT;
1895 goto _r871x_mp_ioctl_hdl_exit;
1896 }
1897_r871x_mp_ioctl_hdl_exit:
b7977fa2 1898 kfree(pparmbuf);
2865d42c
LF
1899 return ret;
1900}
1901
1902static int r871x_get_ap_info(struct net_device *dev,
1903 struct iw_request_info *info,
1904 union iwreq_data *wrqu, char *extra)
1905{
7c1f4203 1906 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1907 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1908 struct __queue *queue = &pmlmepriv->scanned_queue;
1909 struct iw_point *pdata = &wrqu->data;
1910 struct wlan_network *pnetwork = NULL;
1911 u32 cnt = 0, wpa_ielen;
1912 unsigned long irqL;
1913 struct list_head *plist, *phead;
1914 unsigned char *pbuf;
1915 u8 bssid[ETH_ALEN];
1916 char data[32];
1917
1918 if (padapter->bDriverStopped || (pdata == NULL))
1919 return -EINVAL;
1920 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1921 msleep(30);
1922 cnt++;
1923 if (cnt > 100)
1924 break;
1925 }
1926 pdata->flags = 0;
1927 if (pdata->length >= 32) {
1928 if (copy_from_user(data, pdata->pointer, 32))
1929 return -EINVAL;
1930 } else
1931 return -EINVAL;
1932 spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
1933 phead = get_list_head(queue);
1934 plist = get_next(phead);
1935 while (1) {
1936 if (end_of_queue_search(phead, plist) == true)
1937 break;
1938 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1939 if (hwaddr_aton_i(data, bssid)) {
1940 printk(KERN_INFO "r8712u: Invalid BSSID '%s'.\n",
1941 (u8 *)data);
1942 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
1943 irqL);
1944 return -EINVAL;
1945 }
a5ed57a3 1946 printk(KERN_INFO "r8712u: BSSID:%pM\n", bssid);
2865d42c
LF
1947 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
1948 /* BSSID match, then check if supporting wpa/wpa2 */
1949 pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
1950 &wpa_ielen, pnetwork->network.IELength-12);
1951 if (pbuf && (wpa_ielen > 0)) {
1952 pdata->flags = 1;
1953 break;
1954 }
1955 pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
1956 &wpa_ielen, pnetwork->network.IELength-12);
1957 if (pbuf && (wpa_ielen > 0)) {
1958 pdata->flags = 2;
1959 break;
1960 }
1961 }
1962 plist = get_next(plist);
1963 }
1964 spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
1965 if (pdata->length >= 34) {
1966 if (copy_to_user((u8 __user *)pdata->pointer + 32,
1967 (u8 *)&pdata->flags, 1))
1968 return -EINVAL;
1969 }
1970 return 0;
1971}
1972
1973static int r871x_set_pid(struct net_device *dev,
1974 struct iw_request_info *info,
1975 union iwreq_data *wrqu, char *extra)
1976{
7c1f4203 1977 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1978 struct iw_point *pdata = &wrqu->data;
1979
1980 if ((padapter->bDriverStopped) || (pdata == NULL))
1981 return -EINVAL;
1982 if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
1983 return -EINVAL;
1984 return 0;
1985}
1986
1987static int r871x_wps_start(struct net_device *dev,
1988 struct iw_request_info *info,
1989 union iwreq_data *wrqu, char *extra)
1990{
7c1f4203 1991 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1992 struct iw_point *pdata = &wrqu->data;
1993 u32 u32wps_start = 0;
2865d42c 1994
cd922740
XW
1995 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
1996 return -EFAULT;
2865d42c
LF
1997 if ((padapter->bDriverStopped) || (pdata == NULL))
1998 return -EINVAL;
1999 if (u32wps_start == 0)
2000 u32wps_start = *extra;
2001 if (u32wps_start == 1) /* WPS Start */
2002 padapter->ledpriv.LedControlHandler(padapter,
2003 LED_CTL_START_WPS);
2004 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2005 padapter->ledpriv.LedControlHandler(padapter,
2006 LED_CTL_STOP_WPS);
2007 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2008 padapter->ledpriv.LedControlHandler(padapter,
2009 LED_CTL_STOP_WPS_FAIL);
2010 return 0;
2011}
2012
2013static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2014{
7c1f4203 2015 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2016
2017 switch (name) {
2018 case IEEE_PARAM_WPA_ENABLED:
2019 padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2020 switch ((value)&0xff) {
2021 case 1: /* WPA */
2022 padapter->securitypriv.ndisauthtype =
2023 Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2024 padapter->securitypriv.ndisencryptstatus =
2025 Ndis802_11Encryption2Enabled;
2026 break;
2027 case 2: /* WPA2 */
2028 padapter->securitypriv.ndisauthtype =
2029 Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2030 padapter->securitypriv.ndisencryptstatus =
2031 Ndis802_11Encryption3Enabled;
2032 break;
2033 }
2034 break;
2035 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2036 break;
2037 case IEEE_PARAM_DROP_UNENCRYPTED:
2038 /* HACK:
2039 *
2040 * wpa_supplicant calls set_wpa_enabled when the driver
2041 * is loaded and unloaded, regardless of if WPA is being
2042 * used. No other calls are made which can be used to
2043 * determine if encryption will be used or not prior to
2044 * association being expected. If encryption is not being
2045 * used, drop_unencrypted is set to false, else true -- we
2046 * can use this to determine if the CAP_PRIVACY_ON bit should
2047 * be set.
2048 */
2049 break;
2050 case IEEE_PARAM_PRIVACY_INVOKED:
2051 break;
2052 case IEEE_PARAM_AUTH_ALGS:
2053 return wpa_set_auth_algs(dev, value);
2054 break;
2055 case IEEE_PARAM_IEEE_802_1X:
2056 break;
2057 case IEEE_PARAM_WPAX_SELECT:
2058 /* added for WPA2 mixed mode */
2059 break;
2060 default:
2061 return -EOPNOTSUPP;
2062 }
2063 return 0;
2064}
2065
2066static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2067{
7c1f4203 2068 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2069
2070 switch (command) {
2071 case IEEE_MLME_STA_DEAUTH:
2072 if (!r8712_set_802_11_disassociate(padapter))
2073 return -1;
2074 break;
2075 case IEEE_MLME_STA_DISASSOC:
2076 if (!r8712_set_802_11_disassociate(padapter))
2077 return -1;
2078 break;
2079 default:
2080 return -EOPNOTSUPP;
2081 }
2082 return 0;
2083}
2084
2085static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2086{
2087 struct ieee_param *param;
2088 int ret = 0;
7c1f4203 2089 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2090
2091 if (p->length < sizeof(struct ieee_param) || !p->pointer)
2092 return -EINVAL;
2093 param = (struct ieee_param *)_malloc(p->length);
2094 if (param == NULL)
2095 return -ENOMEM;
5ae71713 2096 if (copy_from_user(param, p->pointer, p->length)) {
2865d42c
LF
2097 kfree((u8 *)param);
2098 return -EFAULT;
5ae71713 2099 }
2865d42c
LF
2100 switch (param->cmd) {
2101 case IEEE_CMD_SET_WPA_PARAM:
2102 ret = wpa_set_param(dev, param->u.wpa_param.name,
2103 param->u.wpa_param.value);
2104 break;
2105 case IEEE_CMD_SET_WPA_IE:
2106 ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2107 (u16)param->u.wpa_ie.len);
2108 break;
2109 case IEEE_CMD_SET_ENCRYPTION:
2110 ret = wpa_set_encryption(dev, param, p->length);
2111 break;
2112 case IEEE_CMD_MLME:
2113 ret = wpa_mlme(dev, param->u.mlme.command,
2114 param->u.mlme.reason_code);
2115 break;
2116 default:
2117 ret = -EOPNOTSUPP;
2118 break;
2119 }
2120 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2121 ret = -EFAULT;
2122 kfree((u8 *)param);
2123 return ret;
2124}
2125
2126/* based on "driver_ipw" and for hostapd */
2127int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2128{
2129 struct iwreq *wrq = (struct iwreq *)rq;
2130
2131 switch (cmd) {
2132 case RTL_IOCTL_WPA_SUPPLICANT:
2133 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2134 default:
2135 return -EOPNOTSUPP;
2136 }
2137 return 0;
2138}
2139
2140static iw_handler r8711_handlers[] = {
2141 NULL, /* SIOCSIWCOMMIT */
2142 r8711_wx_get_name, /* SIOCGIWNAME */
2143 dummy, /* SIOCSIWNWID */
2144 dummy, /* SIOCGIWNWID */
2145 r8711_wx_set_freq, /* SIOCSIWFREQ */
2146 r8711_wx_get_freq, /* SIOCGIWFREQ */
2147 r8711_wx_set_mode, /* SIOCSIWMODE */
2148 r8711_wx_get_mode, /* SIOCGIWMODE */
2149 dummy, /* SIOCSIWSENS */
2150 r8711_wx_get_sens, /* SIOCGIWSENS */
2151 NULL, /* SIOCSIWRANGE */
2152 r8711_wx_get_range, /* SIOCGIWRANGE */
2153 r871x_wx_set_priv, /* SIOCSIWPRIV */
2154 NULL, /* SIOCGIWPRIV */
2155 NULL, /* SIOCSIWSTATS */
2156 NULL, /* SIOCGIWSTATS */
2157 dummy, /* SIOCSIWSPY */
2158 dummy, /* SIOCGIWSPY */
2159 NULL, /* SIOCGIWTHRSPY */
2160 NULL, /* SIOCWIWTHRSPY */
2161 r8711_wx_set_wap, /* SIOCSIWAP */
2162 r8711_wx_get_wap, /* SIOCGIWAP */
2163 r871x_wx_set_mlme, /* request MLME operation;
2164 * uses struct iw_mlme */
2165 dummy, /* SIOCGIWAPLIST -- deprecated */
2166 r8711_wx_set_scan, /* SIOCSIWSCAN */
2167 r8711_wx_get_scan, /* SIOCGIWSCAN */
2168 r8711_wx_set_essid, /* SIOCSIWESSID */
2169 r8711_wx_get_essid, /* SIOCGIWESSID */
2170 dummy, /* SIOCSIWNICKN */
2171 r871x_wx_get_nick, /* SIOCGIWNICKN */
2172 NULL, /* -- hole -- */
2173 NULL, /* -- hole -- */
2174 r8711_wx_set_rate, /* SIOCSIWRATE */
2175 r8711_wx_get_rate, /* SIOCGIWRATE */
2176 dummy, /* SIOCSIWRTS */
2177 r8711_wx_get_rts, /* SIOCGIWRTS */
2178 r8711_wx_set_frag, /* SIOCSIWFRAG */
2179 r8711_wx_get_frag, /* SIOCGIWFRAG */
2180 dummy, /* SIOCSIWTXPOW */
2181 dummy, /* SIOCGIWTXPOW */
2182 dummy, /* SIOCSIWRETRY */
2183 r8711_wx_get_retry, /* SIOCGIWRETRY */
2184 r8711_wx_set_enc, /* SIOCSIWENCODE */
2185 r8711_wx_get_enc, /* SIOCGIWENCODE */
2186 dummy, /* SIOCSIWPOWER */
2187 r8711_wx_get_power, /* SIOCGIWPOWER */
2188 NULL, /*---hole---*/
2189 NULL, /*---hole---*/
2190 r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2191 NULL, /* SIOCGIWGENIE */
2192 r871x_wx_set_auth, /* SIOCSIWAUTH */
2193 NULL, /* SIOCGIWAUTH */
2194 r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2195 NULL, /* SIOCGIWENCODEEXT */
2196 r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2197 NULL, /*---hole---*/
2198};
2199
2200static const struct iw_priv_args r8711_private_args[] = {
2201 {
2202 SIOCIWFIRSTPRIV + 0x0,
2203 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2204 },
2205 {
2206 SIOCIWFIRSTPRIV + 0x1,
2207 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2208 },
2209 {
2210 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2211 },
2212 {
2213 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2214 },
2215 {
2216 SIOCIWFIRSTPRIV + 0x4,
2217 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2218 },
2219 {
2220 SIOCIWFIRSTPRIV + 0x5,
2221 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2222 },
2223 {
2224 SIOCIWFIRSTPRIV + 0x6,
2225 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2226 }
2227};
2228
2229static iw_handler r8711_private_handler[] = {
2230 r8711_wx_read32,
2231 r8711_wx_write32,
2232 r8711_drvext_hdl,
2233 r871x_mp_ioctl_hdl,
2234 r871x_get_ap_info, /*for MM DTV platform*/
2235 r871x_set_pid,
2236 r871x_wps_start,
2237};
2238
2239static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2240{
7c1f4203 2241 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2242 struct iw_statistics *piwstats = &padapter->iwstats;
2243 int tmp_level = 0;
2244 int tmp_qual = 0;
2245 int tmp_noise = 0;
2246
2247 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2248 piwstats->qual.qual = 0;
2249 piwstats->qual.level = 0;
2250 piwstats->qual.noise = 0;
2251 } else {
2252 /* show percentage, we need transfer dbm to orignal value. */
2253 tmp_level = padapter->recvpriv.fw_rssi;
2254 tmp_qual = padapter->recvpriv.signal;
2255 tmp_noise = padapter->recvpriv.noise;
2256 piwstats->qual.level = tmp_level;
2257 piwstats->qual.qual = tmp_qual;
2258 piwstats->qual.noise = tmp_noise;
2259 }
2260 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2261 return &padapter->iwstats;
2262}
2263
2264struct iw_handler_def r871x_handlers_def = {
2265 .standard = r8711_handlers,
2266 .num_standard = sizeof(r8711_handlers) / sizeof(iw_handler),
2267 .private = r8711_private_handler,
2268 .private_args = (struct iw_priv_args *)r8711_private_args,
2269 .num_private = sizeof(r8711_private_handler) / sizeof(iw_handler),
2270 .num_private_args = sizeof(r8711_private_args) /
2271 sizeof(struct iw_priv_args),
2272 .get_wireless_stats = r871x_get_wireless_stats,
2273};
This page took 0.251255 seconds and 5 git commands to generate.