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