staging: r8712u: Tracking kmemleak false positives.
[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 51
c6dc001f 52#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
2865d42c
LF
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
c6dc001f
AB
956static int r8711_wx_get_rate(struct net_device *dev,
957 struct iw_request_info *info,
958 union iwreq_data *wrqu, char *extra);
959
2865d42c
LF
960static int r871x_wx_set_priv(struct net_device *dev,
961 struct iw_request_info *info,
962 union iwreq_data *awrq,
963 char *extra)
964{
965 int ret = 0, len = 0;
966 char *ext;
c6dc001f 967 struct _adapter *padapter = netdev_priv(dev);
2865d42c
LF
968 struct iw_point *dwrq = (struct iw_point *)awrq;
969
970 len = dwrq->length;
971 ext = _malloc(len);
4495c15f 972 if (!ext)
2865d42c
LF
973 return -ENOMEM;
974 if (copy_from_user(ext, dwrq->pointer, len)) {
975 kfree(ext);
976 return -EFAULT;
977 }
c6dc001f
AB
978
979 if (0 == strcasecmp(ext, "RSSI")) {
980 /*Return received signal strength indicator in -db for */
981 /* current AP */
982 /*<ssid> Rssi xx */
983 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
984 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
985 /*static u8 xxxx; */
986 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
987 sprintf(ext, "%s rssi %d",
988 pcur_network->network.Ssid.Ssid,
989 /*(xxxx=xxxx+10) */
990 ((padapter->recvpriv.fw_rssi)>>1)-95
991 /*pcur_network->network.Rssi */
992 );
993 } else {
994 sprintf(ext, "OK");
995 }
996 } else if (0 == strcasecmp(ext, "LINKSPEED")) {
997 /*Return link speed in MBPS */
998 /*LinkSpeed xx */
999 union iwreq_data wrqd;
1000 int ret_inner;
1001 int mbps;
1002
1003 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
1004 if (0 != ret_inner)
1005 mbps = 0;
1006 else
1007 mbps = wrqd.bitrate.value / 1000000;
1008 sprintf(ext, "LINKSPEED %d", mbps);
1009 } else if (0 == strcasecmp(ext, "MACADDR")) {
1010 /*Return mac address of the station */
1011 /*Macaddr = xx.xx.xx.xx.xx.xx */
1012 sprintf(ext,
1013 "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
1014 *(dev->dev_addr), *(dev->dev_addr+1),
1015 *(dev->dev_addr+2), *(dev->dev_addr+3),
1016 *(dev->dev_addr+4), *(dev->dev_addr+5));
1017 } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
1018 /*Set scan type to active */
1019 /*OK if successful */
1020 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1021 pmlmepriv->passive_mode = 1;
1022 sprintf(ext, "OK");
1023 } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1024 /*Set scan type to passive */
1025 /*OK if successful */
1026 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1027 pmlmepriv->passive_mode = 0;
1028 sprintf(ext, "OK");
1029 } else if (0 == strncmp(ext, "DCE-E", 5)) {
1030 /*Set scan type to passive */
1031 /*OK if successful */
1032 r8712_disconnectCtrlEx_cmd(padapter
1033 , 1 /*u32 enableDrvCtrl */
1034 , 5 /*u32 tryPktCnt */
1035 , 100 /*u32 tryPktInterval */
1036 , 5000 /*u32 firstStageTO */
1037 );
1038 sprintf(ext, "OK");
1039 } else if (0 == strncmp(ext, "DCE-D", 5)) {
1040 /*Set scan type to passive */
1041 /*OK if successfu */
1042 r8712_disconnectCtrlEx_cmd(padapter
1043 , 0 /*u32 enableDrvCtrl */
1044 , 5 /*u32 tryPktCnt */
1045 , 100 /*u32 tryPktInterval */
1046 , 5000 /*u32 firstStageTO */
1047 );
1048 sprintf(ext, "OK");
1049 } else {
1050 printk(KERN_INFO "r8712u: r871x_wx_set_priv: unknown Command"
1051 " %s.\n", ext);
1052 goto FREE_EXT;
1053 }
1054 if (copy_to_user(dwrq->pointer, ext,
1055 min(dwrq->length, (__u16)(strlen(ext)+1))))
1056 ret = -EFAULT;
1057
1058FREE_EXT:
2865d42c
LF
1059 kfree(ext);
1060 return ret;
1061}
1062
1063/* set bssid flow
1064 * s1. set_802_11_infrastructure_mode()
1065 * s2. set_802_11_authentication_mode()
1066 * s3. set_802_11_encryption_mode()
1067 * s4. set_802_11_bssid()
d1661dfd
AB
1068 *
1069 * This function intends to handle the Set AP command, which specifies the
1070 * MAC# of a preferred Access Point.
1071 * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1072 *
1073 * For this operation to succeed, there is no need for the interface to be Up.
1074 *
2865d42c
LF
1075 */
1076static int r8711_wx_set_wap(struct net_device *dev,
1077 struct iw_request_info *info,
1078 union iwreq_data *awrq,
1079 char *extra)
1080{
1081 int ret = -EINPROGRESS;
7c1f4203 1082 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1083 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1084 struct __queue *queue = &pmlmepriv->scanned_queue;
1085 struct sockaddr *temp = (struct sockaddr *)awrq;
1086 unsigned long irqL;
1087 struct list_head *phead;
1088 u8 *dst_bssid;
1089 struct wlan_network *pnetwork = NULL;
1090 enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1091
2865d42c
LF
1092 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1093 return -1;
1094 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1095 return ret;
1096 if (temp->sa_family != ARPHRD_ETHER)
1097 return -EINVAL;
1098 authmode = padapter->securitypriv.ndisauthtype;
1099 spin_lock_irqsave(&queue->lock, irqL);
1100 phead = get_list_head(queue);
1101 pmlmepriv->pscanned = get_next(phead);
1102 while (1) {
1103 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1104 break;
1105 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1106 struct wlan_network, list);
1107 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1108 dst_bssid = pnetwork->network.MacAddress;
1109 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1110 if (r8712_set_802_11_infrastructure_mode(padapter,
1111 pnetwork->network.InfrastructureMode) == false)
1112 ret = -1;
1113 break;
1114 }
1115 }
1116 spin_unlock_irqrestore(&queue->lock, irqL);
1117 if (!ret) {
1118 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1119 ret = -1;
1120 else {
1121 if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1122 ret = -1;
1123 }
1124 }
1125 return ret;
1126}
1127
1128static int r8711_wx_get_wap(struct net_device *dev,
1129 struct iw_request_info *info,
1130 union iwreq_data *wrqu, char *extra)
1131{
7c1f4203 1132 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1133 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1134 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1135
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);
1141 }
1142 return 0;
1143}
1144
1145static int r871x_wx_set_mlme(struct net_device *dev,
1146 struct iw_request_info *info,
1147 union iwreq_data *wrqu, char *extra)
1148{
1149 int ret = 0;
1150 u16 reason;
7c1f4203 1151 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1152 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1153
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;
1168 }
1169 return ret;
1170}
1171
d1661dfd
AB
1172/**
1173 *
1174 * This function intends to handle the Set Scan command.
1175 * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1176 *
1177 * For this operation to succeed, the interface is brought Up beforehand.
1178 *
1179 */
2865d42c
LF
1180static int r8711_wx_set_scan(struct net_device *dev,
1181 struct iw_request_info *a,
1182 union iwreq_data *wrqu, char *extra)
1183{
7c1f4203 1184 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1185 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1186 u8 status = true;
1187
1188 if (padapter->bDriverStopped == true) {
1189 printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
1190 "bDriverStopped=%d\n", padapter->bDriverStopped);
1191 return -1;
1192 }
1193 if (padapter->bup == false)
1194 return -1;
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);
1220 }
1221 } else
1222 status = r8712_set_802_11_bssid_list_scan(padapter);
1223 if (status == false)
1224 return -1;
1225 return 0;
1226}
1227
1228static int r8711_wx_get_scan(struct net_device *dev,
1229 struct iw_request_info *a,
1230 union iwreq_data *wrqu, char *extra)
1231{
7c1f4203 1232 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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;
1241
1242 if (padapter->bDriverStopped)
1243 return -EINVAL;
1244 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1245 msleep(30);
1246 cnt++;
c6dc001f 1247 if (cnt > 100)
2865d42c
LF
1248 break;
1249 }
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;
1259 }
1260 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1261 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1262 plist = get_next(plist);
1263 }
1264 spin_unlock_irqrestore(&queue->lock, irqL);
1265 wrqu->data.length = ev - extra;
1266 wrqu->data.flags = 0;
1267 return ret;
1268}
1269
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()
d1661dfd
AB
1275 *
1276 * This function intends to handle the Set ESSID command.
1277 * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1278 *
1279 * For this operation to succeed, there is no need for the interface to be Up.
1280 *
2865d42c
LF
1281 */
1282static int r8711_wx_set_essid(struct net_device *dev,
1283 struct iw_request_info *a,
1284 union iwreq_data *wrqu, char *extra)
1285{
7c1f4203 1286 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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;
1295
2865d42c
LF
1296 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1297 return -1;
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)) {
c6dc001f
AB
1322 if (check_fwstate(pmlmepriv,
1323 WIFI_ADHOC_STATE)) {
1324 if (pnetwork->network.
1325 InfrastructureMode
1326 !=
1327 padapter->mlmepriv.
1328 cur_network.network.
1329 InfrastructureMode)
1330 continue;
1331 }
1332
2865d42c
LF
1333 if (!r8712_set_802_11_infrastructure_mode(
1334 padapter,
1335 pnetwork->network.InfrastructureMode))
1336 return -1;
1337 break;
1338 }
1339 }
1340 r8712_set_802_11_authentication_mode(padapter, authmode);
1341 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1342 }
1343 return -EINPROGRESS;
1344}
1345
1346static int r8711_wx_get_essid(struct net_device *dev,
1347 struct iw_request_info *a,
1348 union iwreq_data *wrqu, char *extra)
1349{
7c1f4203 1350 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1351 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1352 struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1353 u32 len, ret = 0;
1354
1355 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1356 len = pcur_bss->Ssid.SsidLength;
1357 wrqu->essid.length = len;
1358 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1359 wrqu->essid.flags = 1;
1360 } else
1361 ret = -1;
1362 return ret;
1363}
1364
1365static int r8711_wx_set_rate(struct net_device *dev,
1366 struct iw_request_info *a,
1367 union iwreq_data *wrqu, char *extra)
1368{
7c1f4203 1369 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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;
1376
1377 if (target_rate == -1) {
1378 ratevalue = 11;
1379 goto set_rate;
1380 }
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;
1422 }
1423set_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;
1431 }
1432 if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1433 ret = -1;
1434 return ret;
1435}
1436
1437static int r8711_wx_get_rate(struct net_device *dev,
1438 struct iw_request_info *info,
1439 union iwreq_data *wrqu, char *extra)
1440{
7c1f4203 1441 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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;
c6dc001f 1445 unsigned char rf_type = padapter->registrypriv.rf_config;
2865d42c
LF
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;
1452
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;
1467 }
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++;
1476 }
1477 if (ht_cap == true) {
c6dc001f
AB
1478 if (mcs_rate & 0x8000 /* MCS15 */
1479 &&
1480 RTL8712_RF_2T2R == rf_type)
2865d42c
LF
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;
1407a9e1
LF
1491 } else {
1492 wrqu->bitrate.value = max_rate * 500000;
2865d42c
LF
1493 }
1494 } else
1495 return -1;
1496 return 0;
1497}
1498
1499static int r8711_wx_get_rts(struct net_device *dev,
1500 struct iw_request_info *info,
1501 union iwreq_data *wrqu, char *extra)
1502{
7c1f4203 1503 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1504
1505 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1506 wrqu->rts.fixed = 0; /* no auto select */
1507 return 0;
1508}
1509
1510static int r8711_wx_set_frag(struct net_device *dev,
1511 struct iw_request_info *info,
1512 union iwreq_data *wrqu, char *extra)
1513{
7c1f4203 1514 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1515
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;
1523 }
1524 return 0;
1525}
1526
1527static int r8711_wx_get_frag(struct net_device *dev,
1528 struct iw_request_info *info,
1529 union iwreq_data *wrqu, char *extra)
1530{
7c1f4203 1531 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1532
1533 wrqu->frag.value = padapter->xmitpriv.frag_len;
1534 wrqu->frag.fixed = 0; /* no auto select */
1535 return 0;
1536}
1537
1538static int r8711_wx_get_retry(struct net_device *dev,
1539 struct iw_request_info *info,
1540 union iwreq_data *wrqu, char *extra)
1541{
1542 wrqu->retry.value = 7;
1543 wrqu->retry.fixed = 0; /* no auto select */
1544 wrqu->retry.disabled = 1;
1545 return 0;
1546}
1547
1548static int r8711_wx_set_enc(struct net_device *dev,
1549 struct iw_request_info *info,
1550 union iwreq_data *wrqu, char *keybuf)
1551{
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);
7c1f4203 1557 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1558
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;
1572 }
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;
1581 }
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;
1611 }
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;
1635 }
1636 return 0;
1637 }
1638 }
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;
1644}
1645
1646static int r8711_wx_get_enc(struct net_device *dev,
1647 struct iw_request_info *info,
1648 union iwreq_data *wrqu, char *keybuf)
1649{
1650 uint key, ret = 0;
7c1f4203 1651 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1652 struct iw_point *erq = &(wrqu->encoding);
1653 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1654
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;
1660 }
1661 }
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;
1669 }
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;
1693 }
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;
1705 }
1706 return ret;
1707}
1708
1709static int r8711_wx_get_power(struct net_device *dev,
1710 struct iw_request_info *info,
1711 union iwreq_data *wrqu, char *extra)
1712{
1713 wrqu->power.value = 0;
1714 wrqu->power.fixed = 0; /* no auto select */
1715 wrqu->power.disabled = 1;
1716 return 0;
1717}
1718
1719static int r871x_wx_set_gen_ie(struct net_device *dev,
1720 struct iw_request_info *info,
1721 union iwreq_data *wrqu, char *extra)
1722{
7c1f4203 1723 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1724
1725 return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1726}
1727
1728static int r871x_wx_set_auth(struct net_device *dev,
1729 struct iw_request_info *info,
1730 union iwreq_data *wrqu, char *extra)
1731{
7c1f4203 1732 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
1733 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1734 int paramid;
1735 int paramval;
1736 int ret = 0;
1737
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:
1748 /*
1749 * ??? does not use these parameters
1750 */
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;
1759 }
1760 break;
1761 case IW_AUTH_DROP_UNENCRYPTED:
1762 /* HACK:
1763 *
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.
1772 */
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;
1779 */
1780 break;
1781 }
1782
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;
1793 }
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;
1806 }
1807
1808 return ret;
1809}
1810
1811static int r871x_wx_set_enc_ext(struct net_device *dev,
1812 struct iw_request_info *info,
1813 union iwreq_data *wrqu, char *extra)
1814{
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;
1821
1822 param_len = sizeof(struct ieee_param) + pext->key_len;
1823 param = (struct ieee_param *)_malloc(param_len);
1824 if (param == NULL)
1825 return -1;
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 -1;
1844 }
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);
1856 }
1857 ret = wpa_set_encryption(dev, param, param_len);
40083865 1858 kfree(param);
2865d42c
LF
1859 return ret;
1860}
1861
1862static int r871x_wx_get_nick(struct net_device *dev,
1863 struct iw_request_info *info,
1864 union iwreq_data *wrqu, char *extra)
1865{
1866 if (extra) {
1867 wrqu->data.length = 8;
1868 wrqu->data.flags = 1;
1869 memcpy(extra, "rtl_wifi", 8);
1870 }
1871 return 0;
1872}
1873
1874static int r8711_wx_read32(struct net_device *dev,
1875 struct iw_request_info *info,
1876 union iwreq_data *wrqu, char *keybuf)
1877{
7c1f4203 1878 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1879 u32 addr;
1880 u32 data32;
1881
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;
1889}
1890
1891static int r8711_wx_write32(struct net_device *dev,
1892 struct iw_request_info *info,
1893 union iwreq_data *wrqu, char *keybuf)
1894{
7c1f4203 1895 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
1896 u32 addr;
1897 u32 data32;
1898
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;
1903}
1904
1905static int dummy(struct net_device *dev,
1906 struct iw_request_info *a,
1907 union iwreq_data *wrqu, char *b)
1908{
1909 return -1;
1910}
1911
1912static int r8711_drvext_hdl(struct net_device *dev,
1913 struct iw_request_info *info,
1914 union iwreq_data *wrqu, char *extra)
1915{
1916 return 0;
1917}
1918
1919static int r871x_mp_ioctl_hdl(struct net_device *dev,
1920 struct iw_request_info *info,
1921 union iwreq_data *wrqu, char *extra)
1922{
7c1f4203 1923 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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;
1933
1934 if ((!p->length) || (!p->pointer)) {
1935 ret = -EINVAL;
1936 goto _r871x_mp_ioctl_hdl_exit;
1937 }
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;
1945 }
1946 if (copy_from_user(pparmbuf, p->pointer, len)) {
1947 ret = -EFAULT;
1948 goto _r871x_mp_ioctl_hdl_exit;
1949 }
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;
1954 }
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;
1960 }
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;
1979 }
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;
1988 }
1989 if (bset == 0x00) { /* query info */
1990 if (copy_to_user(p->pointer, pparmbuf, len))
1991 ret = -EFAULT;
1992 }
1993 if (status) {
1994 ret = -EFAULT;
1995 goto _r871x_mp_ioctl_hdl_exit;
1996 }
1997_r871x_mp_ioctl_hdl_exit:
b7977fa2 1998 kfree(pparmbuf);
2865d42c
LF
1999 return ret;
2000}
2001
2002static int r871x_get_ap_info(struct net_device *dev,
2003 struct iw_request_info *info,
2004 union iwreq_data *wrqu, char *extra)
2005{
7c1f4203 2006 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
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];
2017
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;
2025 }
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;
2045 }
a5ed57a3 2046 printk(KERN_INFO "r8712u: BSSID:%pM\n", bssid);
2865d42c
LF
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;
2054 }
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;
2060 }
2061 }
2062 plist = get_next(plist);
2063 }
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;
2069 }
2070 return 0;
2071}
2072
2073static int r871x_set_pid(struct net_device *dev,
2074 struct iw_request_info *info,
2075 union iwreq_data *wrqu, char *extra)
2076{
7c1f4203 2077 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2078 struct iw_point *pdata = &wrqu->data;
2079
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;
2085}
2086
c6dc001f
AB
2087static int r871x_set_chplan(struct net_device *dev,
2088 struct iw_request_info *info,
2089 union iwreq_data *wrqu, char *extra)
2090{
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;
2095
2096 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2097 ret = -EINVAL;
2098 goto exit;
2099 }
2100 ch_plan = (int)*extra;
2101 r8712_set_chplan_cmd(padapter, ch_plan);
2102
2103exit:
2104
2105 return ret;
2106}
2107
2865d42c
LF
2108static int r871x_wps_start(struct net_device *dev,
2109 struct iw_request_info *info,
2110 union iwreq_data *wrqu, char *extra)
2111{
7c1f4203 2112 struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2865d42c
LF
2113 struct iw_point *pdata = &wrqu->data;
2114 u32 u32wps_start = 0;
2865d42c 2115
cd922740
XW
2116 if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2117 return -EFAULT;
2865d42c
LF
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;
2132}
2133
2134static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2135{
7c1f4203 2136 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2137
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;
2154 }
2155 break;
2156 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2157 break;
2158 case IEEE_PARAM_DROP_UNENCRYPTED:
2159 /* HACK:
2160 *
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.
2169 */
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;
2183 }
2184 return 0;
2185}
2186
2187static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2188{
7c1f4203 2189 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2190
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;
2202 }
2203 return 0;
2204}
2205
2206static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2207{
2208 struct ieee_param *param;
2209 int ret = 0;
7c1f4203 2210 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2211
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;
5ae71713 2217 if (copy_from_user(param, p->pointer, p->length)) {
2865d42c
LF
2218 kfree((u8 *)param);
2219 return -EFAULT;
5ae71713 2220 }
2865d42c
LF
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;
2240 }
2241 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2242 ret = -EFAULT;
2243 kfree((u8 *)param);
2244 return ret;
2245}
2246
2247/* based on "driver_ipw" and for hostapd */
2248int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2249{
2250 struct iwreq *wrq = (struct iwreq *)rq;
2251
2252 switch (cmd) {
2253 case RTL_IOCTL_WPA_SUPPLICANT:
2254 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2255 default:
2256 return -EOPNOTSUPP;
2257 }
2258 return 0;
2259}
2260
2261static 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---*/
2319};
2320
2321static const struct iw_priv_args r8711_private_args[] = {
2322 {
2323 SIOCIWFIRSTPRIV + 0x0,
2324 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2325 },
2326 {
2327 SIOCIWFIRSTPRIV + 0x1,
2328 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2329 },
2330 {
2331 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2332 },
2333 {
2334 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2335 },
2336 {
2337 SIOCIWFIRSTPRIV + 0x4,
2338 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2339 },
2340 {
2341 SIOCIWFIRSTPRIV + 0x5,
2342 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2343 },
2344 {
2345 SIOCIWFIRSTPRIV + 0x6,
2346 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
c6dc001f
AB
2347 },
2348 {
2349 SIOCIWFIRSTPRIV + 0x7,
2350 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2865d42c
LF
2351 }
2352};
2353
2354static 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,
c6dc001f
AB
2361 r871x_wps_start,
2362 r871x_set_chplan
2865d42c
LF
2363};
2364
2365static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2366{
7c1f4203 2367 struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2865d42c
LF
2368 struct iw_statistics *piwstats = &padapter->iwstats;
2369 int tmp_level = 0;
2370 int tmp_qual = 0;
2371 int tmp_noise = 0;
2372
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;
c6dc001f
AB
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.
2388 */
2389 piwstats->qual.qual = tmp_level;
2865d42c
LF
2390 piwstats->qual.noise = tmp_noise;
2391 }
2392 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2393 return &padapter->iwstats;
2394}
2395
2396struct 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),
c6dc001f 2404 .get_wireless_stats = r871x_get_wireless_stats
2865d42c 2405};
This page took 0.240784 seconds and 5 git commands to generate.