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