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