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