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