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