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