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