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