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