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