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