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