Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[sfrench/cifs-2.6.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, bw_40MHz = 0, short_GI = 0;
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                 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
201                            ? 1 : 0;
202                 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
203                             IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
204         }
205         /* Add the protocol name */
206         iwe.cmd = SIOCGIWNAME;
207         if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
208              SupportedRates)) == true) {
209                 if (ht_cap == true)
210                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
211                 else
212                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
213         } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
214                     SupportedRates)) == true) {
215                 if (ht_cap == true)
216                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
217                 else
218                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
219         } else {
220                 if (ht_cap == true)
221                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
222                 else
223                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
224         }
225         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
226         /* Add mode */
227         iwe.cmd = SIOCGIWMODE;
228         memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
229                 2);
230         cap = le16_to_cpu(cap);
231         if (cap & (WLAN_CAPABILITY_IBSS|WLAN_CAPABILITY_BSS)) {
232                 if (cap & WLAN_CAPABILITY_BSS)
233                         iwe.u.mode = (u32)IW_MODE_MASTER;
234                 else
235                         iwe.u.mode = (u32)IW_MODE_ADHOC;
236                 start = iwe_stream_add_event(info, start, stop, &iwe,
237                         IW_EV_UINT_LEN);
238         }
239         /* Add frequency/channel */
240         iwe.cmd = SIOCGIWFREQ;
241         {
242                 /*  check legal index */
243                 u8 dsconfig = pnetwork->network.Configuration.DSConfig;
244                 if (dsconfig >= 1 && dsconfig <= sizeof(
245                     ieee80211_wlan_frequencies) / sizeof(long))
246                         iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
247                                        pnetwork->network.Configuration.
248                                        DSConfig - 1] * 100000);
249                 else
250                         iwe.u.freq.m = 0;
251         }
252         iwe.u.freq.e = (s16)1;
253         iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
254         start = iwe_stream_add_event(info, start, stop, &iwe,
255                 IW_EV_FREQ_LEN);
256         /* Add encryption capability */
257         iwe.cmd = SIOCGIWENCODE;
258         if (cap & WLAN_CAPABILITY_PRIVACY)
259                 iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
260                                     IW_ENCODE_NOKEY);
261         else
262                 iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
263         iwe.u.data.length = (u16)0;
264         start = iwe_stream_add_point(info, start, stop, &iwe,
265                 pnetwork->network.Ssid.Ssid);
266         /*Add basic and extended rates */
267         current_val = start + iwe_stream_lcp_len(info);
268         iwe.cmd = SIOCGIWRATE;
269         iwe.u.bitrate.fixed = 0;
270         iwe.u.bitrate.disabled = 0;
271         iwe.u.bitrate.value = 0;
272         i = 0;
273         while (pnetwork->network.SupportedRates[i] != 0) {
274                 /* Bit rate given in 500 kb/s units */
275                 iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
276                                       0x7F) * 500000;
277                 current_val = iwe_stream_add_value(info, start, current_val,
278                               stop, &iwe, IW_EV_PARAM_LEN);
279         }
280         /* Check if we added any event */
281         if ((current_val - start) > iwe_stream_lcp_len(info))
282                 start = current_val;
283         /* parsing WPA/WPA2 IE */
284         {
285                 u8 buf[MAX_WPA_IE_LEN];
286                 u8 wpa_ie[255], rsn_ie[255];
287                 u16 wpa_len = 0, rsn_len = 0;
288                 int n;
289                 sint out_len = 0;
290                 out_len = r8712_get_sec_ie(pnetwork->network.IEs,
291                                            pnetwork->network.
292                                            IELength, rsn_ie, &rsn_len,
293                                            wpa_ie, &wpa_len);
294                 if (wpa_len > 0) {
295                         memset(buf, 0, MAX_WPA_IE_LEN);
296                         n = sprintf(buf, "wpa_ie=");
297                         for (i = 0; i < wpa_len; i++) {
298                                 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
299                                                         "%02x", wpa_ie[i]);
300                                 if (n >= MAX_WPA_IE_LEN)
301                                         break;
302                         }
303                         memset(&iwe, 0, sizeof(iwe));
304                         iwe.cmd = IWEVCUSTOM;
305                         iwe.u.data.length = (u16)strlen(buf);
306                         start = iwe_stream_add_point(info, start, stop,
307                                 &iwe, buf);
308                         memset(&iwe, 0, sizeof(iwe));
309                         iwe.cmd = IWEVGENIE;
310                         iwe.u.data.length = (u16)wpa_len;
311                         start = iwe_stream_add_point(info, start, stop,
312                                 &iwe, wpa_ie);
313                 }
314                 if (rsn_len > 0) {
315                         memset(buf, 0, MAX_WPA_IE_LEN);
316                         n = sprintf(buf, "rsn_ie=");
317                         for (i = 0; i < rsn_len; i++) {
318                                 n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
319                                                         "%02x", rsn_ie[i]);
320                                 if (n >= MAX_WPA_IE_LEN)
321                                         break;
322                         }
323                         memset(&iwe, 0, sizeof(iwe));
324                         iwe.cmd = IWEVCUSTOM;
325                         iwe.u.data.length = strlen(buf);
326                         start = iwe_stream_add_point(info, start, stop,
327                                 &iwe, buf);
328                         memset(&iwe, 0, sizeof(iwe));
329                         iwe.cmd = IWEVGENIE;
330                         iwe.u.data.length = rsn_len;
331                         start = iwe_stream_add_point(info, start, stop, &iwe,
332                                 rsn_ie);
333                 }
334         }
335
336         { /* parsing WPS IE */
337                 u8 wps_ie[512];
338                 uint wps_ielen;
339
340                 if (r8712_get_wps_ie(pnetwork->network.IEs,
341                     pnetwork->network.IELength,
342                     wps_ie, &wps_ielen) == true) {
343                         if (wps_ielen > 2) {
344                                 iwe.cmd = IWEVGENIE;
345                                 iwe.u.data.length = (u16)wps_ielen;
346                                 start = iwe_stream_add_point(info, start, stop,
347                                         &iwe, wps_ie);
348                         }
349                 }
350         }
351         /* Add quality statistics */
352         iwe.cmd = IWEVQUAL;
353         rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
354         /* we only update signal_level (signal strength) that is rssi. */
355         iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
356                                   IW_QUAL_NOISE_INVALID);
357         iwe.u.qual.level = rssi;  /* signal strength */
358         iwe.u.qual.qual = 0; /* signal quality */
359         iwe.u.qual.noise = 0; /* noise level */
360         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
361         /* how to translate rssi to ?% */
362         return start;
363 }
364
365 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
366 {
367         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
368         int ret = 0;
369
370         if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
371                 padapter->securitypriv.ndisencryptstatus =
372                                                  Ndis802_11Encryption1Enabled;
373                 padapter->securitypriv.ndisauthtype =
374                                                  Ndis802_11AuthModeAutoSwitch;
375                 padapter->securitypriv.AuthAlgrthm = 3;
376         } else if (value & AUTH_ALG_SHARED_KEY) {
377                 padapter->securitypriv.ndisencryptstatus =
378                                                  Ndis802_11Encryption1Enabled;
379                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
380                 padapter->securitypriv.AuthAlgrthm = 1;
381         } else if (value & AUTH_ALG_OPEN_SYSTEM) {
382                 if (padapter->securitypriv.ndisauthtype <
383                                                  Ndis802_11AuthModeWPAPSK) {
384                         padapter->securitypriv.ndisauthtype =
385                                                  Ndis802_11AuthModeOpen;
386                         padapter->securitypriv.AuthAlgrthm = 0;
387                 }
388         } else
389                 ret = -EINVAL;
390         return ret;
391 }
392
393 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
394                               u32 param_len)
395 {
396         int ret = 0;
397         u32 wep_key_idx, wep_key_len = 0;
398         struct NDIS_802_11_WEP   *pwep = NULL;
399         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
400         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
401         struct security_priv *psecuritypriv = &padapter->securitypriv;
402
403         param->u.crypt.err = 0;
404         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
405         if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
406                          param->u.crypt.key_len)
407                 return -EINVAL;
408         if (is_broadcast_ether_addr(param->sta_addr)) {
409                 if (param->u.crypt.idx >= WEP_KEYS) {
410                         /* for large key indices, set the default (0) */
411                         param->u.crypt.idx = 0;
412                 }
413         } else
414                 return -EINVAL;
415         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
416                 netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
417                 padapter->securitypriv.ndisencryptstatus =
418                              Ndis802_11Encryption1Enabled;
419                 padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
420                 padapter->securitypriv.XGrpPrivacy = _WEP40_;
421                 wep_key_idx = param->u.crypt.idx;
422                 wep_key_len = param->u.crypt.key_len;
423                 if (wep_key_idx >= WEP_KEYS)
424                         wep_key_idx = 0;
425                 if (wep_key_len > 0) {
426                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
427                         pwep = kmalloc((u32)(wep_key_len +
428                                        FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial)),
429                                        GFP_ATOMIC);
430                         if (pwep == NULL)
431                                 return -ENOMEM;
432                         memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
433                         pwep->KeyLength = wep_key_len;
434                         pwep->Length = wep_key_len +
435                                  FIELD_OFFSET(struct NDIS_802_11_WEP,
436                                  KeyMaterial);
437                         if (wep_key_len == 13) {
438                                 padapter->securitypriv.PrivacyAlgrthm =
439                                          _WEP104_;
440                                 padapter->securitypriv.XGrpPrivacy =
441                                          _WEP104_;
442                         }
443                 } else
444                         return -EINVAL;
445                 pwep->KeyIndex = wep_key_idx;
446                 pwep->KeyIndex |= 0x80000000;
447                 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
448                 if (param->u.crypt.set_tx) {
449                         if (r8712_set_802_11_add_wep(padapter, pwep) ==
450                             (u8)_FAIL)
451                                 ret = -EOPNOTSUPP;
452                 } else {
453                         /* don't update "psecuritypriv->PrivacyAlgrthm" and
454                          * "psecuritypriv->PrivacyKeyIndex=keyid", but can
455                          * r8712_set_key to fw/cam
456                          */
457                         if (wep_key_idx >= WEP_KEYS) {
458                                 ret = -EOPNOTSUPP;
459                                 goto exit;
460                         }
461                         memcpy(&(psecuritypriv->DefKey[wep_key_idx].
462                                 skey[0]), pwep->KeyMaterial,
463                                 pwep->KeyLength);
464                         psecuritypriv->DefKeylen[wep_key_idx] =
465                                 pwep->KeyLength;
466                         r8712_set_key(padapter, psecuritypriv, wep_key_idx);
467                 }
468                 goto exit;
469         }
470         if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
471                 struct sta_info *psta, *pbcmc_sta;
472                 struct sta_priv *pstapriv = &padapter->stapriv;
473
474                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
475                     WIFI_MP_STATE) == true) { /* sta mode */
476                         psta = r8712_get_stainfo(pstapriv,
477                                                  get_bssid(pmlmepriv));
478                         if (psta) {
479                                 psta->ieee8021x_blocked = false;
480                                 if ((padapter->securitypriv.ndisencryptstatus ==
481                                     Ndis802_11Encryption2Enabled) ||
482                                     (padapter->securitypriv.ndisencryptstatus ==
483                                     Ndis802_11Encryption3Enabled))
484                                         psta->XPrivacy = padapter->
485                                             securitypriv.PrivacyAlgrthm;
486                                 if (param->u.crypt.set_tx == 1)
487                                         handle_pairwise_key(psta, param,
488                                                             padapter);
489                                 else /* group key */
490                                         handle_group_key(param, padapter);
491                         }
492                         pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
493                         if (pbcmc_sta) {
494                                 pbcmc_sta->ieee8021x_blocked = false;
495                                 if ((padapter->securitypriv.ndisencryptstatus ==
496                                     Ndis802_11Encryption2Enabled) ||
497                                     (padapter->securitypriv.ndisencryptstatus ==
498                                     Ndis802_11Encryption3Enabled))
499                                         pbcmc_sta->XPrivacy =
500                                           padapter->securitypriv.
501                                           PrivacyAlgrthm;
502                         }
503                 }
504         }
505 exit:
506         kfree((u8 *)pwep);
507         return ret;
508 }
509
510 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
511                             unsigned short ielen)
512 {
513         u8 *buf = NULL, *pos = NULL;
514         int group_cipher = 0, pairwise_cipher = 0;
515         int ret = 0;
516
517         if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
518                 return -EINVAL;
519         if (ielen) {
520                 buf = kmemdup(pie, ielen, GFP_ATOMIC);
521                 if (buf == NULL)
522                         return -ENOMEM;
523                 pos = buf;
524                 if (ielen < RSN_HEADER_LEN) {
525                         ret  = -EINVAL;
526                         goto exit;
527                 }
528                 if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
529                     &pairwise_cipher) == _SUCCESS) {
530                         padapter->securitypriv.AuthAlgrthm = 2;
531                         padapter->securitypriv.ndisauthtype =
532                                   Ndis802_11AuthModeWPAPSK;
533                 }
534                 if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
535                     &pairwise_cipher) == _SUCCESS) {
536                         padapter->securitypriv.AuthAlgrthm = 2;
537                         padapter->securitypriv.ndisauthtype =
538                                   Ndis802_11AuthModeWPA2PSK;
539                 }
540                 switch (group_cipher) {
541                 case WPA_CIPHER_NONE:
542                         padapter->securitypriv.XGrpPrivacy =
543                                  _NO_PRIVACY_;
544                         padapter->securitypriv.ndisencryptstatus =
545                                  Ndis802_11EncryptionDisabled;
546                         break;
547                 case WPA_CIPHER_WEP40:
548                         padapter->securitypriv.XGrpPrivacy = _WEP40_;
549                         padapter->securitypriv.ndisencryptstatus =
550                                  Ndis802_11Encryption1Enabled;
551                         break;
552                 case WPA_CIPHER_TKIP:
553                         padapter->securitypriv.XGrpPrivacy = _TKIP_;
554                         padapter->securitypriv.ndisencryptstatus =
555                                  Ndis802_11Encryption2Enabled;
556                         break;
557                 case WPA_CIPHER_CCMP:
558                         padapter->securitypriv.XGrpPrivacy = _AES_;
559                         padapter->securitypriv.ndisencryptstatus =
560                                  Ndis802_11Encryption3Enabled;
561                         break;
562                 case WPA_CIPHER_WEP104:
563                         padapter->securitypriv.XGrpPrivacy = _WEP104_;
564                         padapter->securitypriv.ndisencryptstatus =
565                                  Ndis802_11Encryption1Enabled;
566                         break;
567                 }
568                 switch (pairwise_cipher) {
569                 case WPA_CIPHER_NONE:
570                         padapter->securitypriv.PrivacyAlgrthm =
571                                  _NO_PRIVACY_;
572                         padapter->securitypriv.ndisencryptstatus =
573                                  Ndis802_11EncryptionDisabled;
574                         break;
575                 case WPA_CIPHER_WEP40:
576                         padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
577                         padapter->securitypriv.ndisencryptstatus =
578                                  Ndis802_11Encryption1Enabled;
579                         break;
580                 case WPA_CIPHER_TKIP:
581                         padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
582                         padapter->securitypriv.ndisencryptstatus =
583                                  Ndis802_11Encryption2Enabled;
584                         break;
585                 case WPA_CIPHER_CCMP:
586                         padapter->securitypriv.PrivacyAlgrthm = _AES_;
587                         padapter->securitypriv.ndisencryptstatus =
588                                  Ndis802_11Encryption3Enabled;
589                         break;
590                 case WPA_CIPHER_WEP104:
591                         padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
592                         padapter->securitypriv.ndisencryptstatus =
593                                  Ndis802_11Encryption1Enabled;
594                         break;
595                 }
596                 padapter->securitypriv.wps_phase = false;
597                 {/* set wps_ie */
598                         u16 cnt = 0;
599                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
600
601                         while (cnt < ielen) {
602                                 eid = buf[cnt];
603
604                                 if ((eid == _VENDOR_SPECIFIC_IE_) &&
605                                     (!memcmp(&buf[cnt+2], wps_oui, 4))) {
606                                         netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
607                                         padapter->securitypriv.wps_ie_len =
608                                             ((buf[cnt+1] + 2) <
609                                             (MAX_WPA_IE_LEN << 2)) ?
610                                             (buf[cnt + 1] + 2) :
611                                             (MAX_WPA_IE_LEN << 2);
612                                         memcpy(padapter->securitypriv.wps_ie,
613                                             &buf[cnt],
614                                             padapter->securitypriv.wps_ie_len);
615                                         padapter->securitypriv.wps_phase =
616                                                                  true;
617                                         netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
618                                         cnt += buf[cnt+1]+2;
619                                         break;
620                                 } else
621                                         cnt += buf[cnt + 1] + 2;
622                         }
623                 }
624         }
625 exit:
626         kfree(buf);
627         return ret;
628 }
629
630 static int r8711_wx_get_name(struct net_device *dev,
631                              struct iw_request_info *info,
632                              union iwreq_data *wrqu, char *extra)
633 {
634         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
635         u32 ht_ielen = 0;
636         char *p;
637         u8 ht_cap = false;
638         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
639         struct ndis_wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
640         NDIS_802_11_RATES_EX *prates = NULL;
641
642         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
643             true) {
644                 /* parsing HT_CAP_IE */
645                 p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
646                                  &ht_ielen, pcur_bss->IELength - 12);
647                 if (p && ht_ielen > 0)
648                         ht_cap = true;
649                 prates = &pcur_bss->SupportedRates;
650                 if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
651                         if (ht_cap == true)
652                                 snprintf(wrqu->name, IFNAMSIZ,
653                                          "IEEE 802.11bn");
654                         else
655                                 snprintf(wrqu->name, IFNAMSIZ,
656                                          "IEEE 802.11b");
657                 } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
658                         if (ht_cap == true)
659                                 snprintf(wrqu->name, IFNAMSIZ,
660                                          "IEEE 802.11bgn");
661                         else
662                                 snprintf(wrqu->name, IFNAMSIZ,
663                                          "IEEE 802.11bg");
664                 } else {
665                         if (ht_cap == true)
666                                 snprintf(wrqu->name, IFNAMSIZ,
667                                          "IEEE 802.11gn");
668                         else
669                                 snprintf(wrqu->name, IFNAMSIZ,
670                                          "IEEE 802.11g");
671                 }
672         } else
673                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
674         return 0;
675 }
676
677 static const long frequency_list[] = {
678         2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
679         2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
680         5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
681         5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
682         5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
683         5825
684 };
685
686 static int r8711_wx_set_freq(struct net_device *dev,
687                              struct iw_request_info *info,
688                              union iwreq_data *wrqu, char *extra)
689 {
690         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
691         struct iw_freq *fwrq = &wrqu->freq;
692         int rc = 0;
693
694 /* If setting by frequency, convert to a channel */
695         if ((fwrq->e == 1) &&
696           (fwrq->m >= (int) 2.412e8) &&
697           (fwrq->m <= (int) 2.487e8)) {
698                 int f = fwrq->m / 100000;
699                 int c = 0;
700                 while ((c < 14) && (f != frequency_list[c]))
701                         c++;
702                 fwrq->e = 0;
703                 fwrq->m = c + 1;
704         }
705         /* Setting by channel number */
706         if ((fwrq->m > 14) || (fwrq->e > 0))
707                 rc = -EOPNOTSUPP;
708         else {
709                 int channel = fwrq->m;
710                 if ((channel < 1) || (channel > 14))
711                         rc = -EINVAL;
712                 else {
713                         /* Yes ! We can set it !!! */
714                         padapter->registrypriv.channel = channel;
715                 }
716         }
717         return rc;
718 }
719
720 static int r8711_wx_get_freq(struct net_device *dev,
721                              struct iw_request_info *info,
722                              union iwreq_data *wrqu, char *extra)
723 {
724         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
725         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
726         struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
727
728         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
729                 wrqu->freq.m = ieee80211_wlan_frequencies[
730                                pcur_bss->Configuration.DSConfig-1] * 100000;
731                 wrqu->freq.e = 1;
732                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
733         } else {
734                 return -ENOLINK;
735         }
736         return 0;
737 }
738
739 static int r8711_wx_set_mode(struct net_device *dev,
740                              struct iw_request_info *a,
741                              union iwreq_data *wrqu, char *b)
742 {
743         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
744         enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
745
746         switch (wrqu->mode) {
747         case IW_MODE_AUTO:
748                 networkType = Ndis802_11AutoUnknown;
749                 break;
750         case IW_MODE_ADHOC:
751                 networkType = Ndis802_11IBSS;
752                 break;
753         case IW_MODE_MASTER:
754                 networkType = Ndis802_11APMode;
755                 break;
756         case IW_MODE_INFRA:
757                 networkType = Ndis802_11Infrastructure;
758                 break;
759         default:
760                 return -EINVAL;
761         }
762         if (Ndis802_11APMode == networkType)
763                 r8712_setopmode_cmd(padapter, networkType);
764         else
765                 r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
766
767         r8712_set_802_11_infrastructure_mode(padapter, networkType);
768         return 0;
769 }
770
771 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
772                              union iwreq_data *wrqu, char *b)
773 {
774         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
775         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
776
777         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
778                 wrqu->mode = IW_MODE_INFRA;
779         else if (check_fwstate(pmlmepriv,
780                  WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) == true)
781                 wrqu->mode = IW_MODE_ADHOC;
782         else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
783                 wrqu->mode = IW_MODE_MASTER;
784         else
785                 wrqu->mode = IW_MODE_AUTO;
786         return 0;
787 }
788
789 static int r871x_wx_set_pmkid(struct net_device *dev,
790                              struct iw_request_info *a,
791                              union iwreq_data *wrqu, char *extra)
792 {
793         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
794         struct security_priv *psecuritypriv = &padapter->securitypriv;
795         struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
796         u8 strZeroMacAddress[ETH_ALEN] = {0x00};
797         u8 strIssueBssid[ETH_ALEN] = {0x00};
798         u8 j, blInserted = false;
799         int intReturn = false;
800
801 /*
802         There are the BSSID information in the bssid.sa_data array.
803         If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
804         all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
805         wpa_supplicant wants to add a PMKID/BSSID to driver.
806         If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
807         remove a PMKID/BSSID from driver.
808 */
809         if (pPMK == NULL)
810                 return -EINVAL;
811         memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
812         switch (pPMK->cmd) {
813         case IW_PMKSA_ADD:
814                 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
815                         return intReturn;
816                 else
817                         intReturn = true;
818                 blInserted = false;
819                 /* overwrite PMKID */
820                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
821                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
822                             strIssueBssid, ETH_ALEN)) {
823                                 /* BSSID is matched, the same AP => rewrite
824                                  * with new PMKID. */
825                                 netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
826                                             __func__);
827                                 memcpy(psecuritypriv->PMKIDList[j].PMKID,
828                                         pPMK->pmkid, IW_PMKID_LEN);
829                                 psecuritypriv->PMKIDList[j].bUsed = true;
830                                 psecuritypriv->PMKIDIndex = j + 1;
831                                 blInserted = true;
832                                 break;
833                         }
834                 }
835                 if (!blInserted) {
836                         /* Find a new entry */
837                         netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
838                                     __func__, psecuritypriv->PMKIDIndex);
839                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->
840                                 PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
841                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->
842                                 PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
843                         psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
844                                 bUsed = true;
845                         psecuritypriv->PMKIDIndex++;
846                         if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
847                                 psecuritypriv->PMKIDIndex = 0;
848                 }
849                 break;
850         case IW_PMKSA_REMOVE:
851                 intReturn = true;
852                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
853                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
854                             strIssueBssid, ETH_ALEN)) {
855                                 /* BSSID is matched, the same AP => Remove
856                                  * this PMKID information and reset it. */
857                                 memset(psecuritypriv->PMKIDList[j].Bssid,
858                                         0x00, ETH_ALEN);
859                                 psecuritypriv->PMKIDList[j].bUsed = false;
860                                 break;
861                         }
862                 }
863                 break;
864         case IW_PMKSA_FLUSH:
865                 memset(psecuritypriv->PMKIDList, 0,
866                         sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
867                 psecuritypriv->PMKIDIndex = 0;
868                 intReturn = true;
869                 break;
870         default:
871                 netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
872                 intReturn = false;
873                 break;
874         }
875         return intReturn;
876 }
877
878 static int r8711_wx_get_sens(struct net_device *dev,
879                              struct iw_request_info *info,
880                              union iwreq_data *wrqu, char *extra)
881 {
882         wrqu->sens.value = 0;
883         wrqu->sens.fixed = 0;   /* no auto select */
884         wrqu->sens.disabled = 1;
885         return 0;
886 }
887
888 static int r8711_wx_get_range(struct net_device *dev,
889                                 struct iw_request_info *info,
890                                 union iwreq_data *wrqu, char *extra)
891 {
892         struct iw_range *range = (struct iw_range *)extra;
893         u16 val;
894         int i;
895
896         wrqu->data.length = sizeof(*range);
897         memset(range, 0, sizeof(*range));
898         /* Let's try to keep this struct in the same order as in
899          * linux/include/wireless.h
900          */
901
902         /* TODO: See what values we can set, and remove the ones we can't
903          * set, or fill them with some default data.
904          */
905         /* ~5 Mb/s real (802.11b) */
906         range->throughput = 5 * 1000 * 1000;
907         /* TODO: 8711 sensitivity ? */
908         /* signal level threshold range */
909         /* percent values between 0 and 100. */
910         range->max_qual.qual = 100;
911         range->max_qual.level = 100;
912         range->max_qual.noise = 100;
913         range->max_qual.updated = 7; /* Updated all three */
914         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
915         /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
916         range->avg_qual.level = 20 + -98;
917         range->avg_qual.noise = 0;
918         range->avg_qual.updated = 7; /* Updated all three */
919         range->num_bitrates = RATE_COUNT;
920         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
921                 range->bitrate[i] = rtl8180_rates[i];
922         range->min_frag = MIN_FRAG_THRESHOLD;
923         range->max_frag = MAX_FRAG_THRESHOLD;
924         range->pm_capa = 0;
925         range->we_version_compiled = WIRELESS_EXT;
926         range->we_version_source = 16;
927         range->num_channels = 14;
928         for (i = 0, val = 0; i < 14; i++) {
929                 /* Include only legal frequencies for some countries */
930                 range->freq[val].i = i + 1;
931                 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
932                 range->freq[val].e = 1;
933                 val++;
934                 if (val == IW_MAX_FREQUENCIES)
935                         break;
936         }
937         range->num_frequency = val;
938         range->enc_capa = IW_ENC_CAPA_WPA |
939                           IW_ENC_CAPA_WPA2 |
940                           IW_ENC_CAPA_CIPHER_TKIP |
941                           IW_ENC_CAPA_CIPHER_CCMP;
942         return 0;
943 }
944
945 static int r8711_wx_get_rate(struct net_device *dev,
946                              struct iw_request_info *info,
947                              union iwreq_data *wrqu, char *extra);
948
949 static int r871x_wx_set_priv(struct net_device *dev,
950                                 struct iw_request_info *info,
951                                 union iwreq_data *awrq,
952                                 char *extra)
953 {
954         int ret = 0, len = 0;
955         char *ext;
956         struct _adapter *padapter = netdev_priv(dev);
957         struct iw_point *dwrq = (struct iw_point *)awrq;
958
959         len = dwrq->length;
960         ext = memdup_user(dwrq->pointer, len);
961         if (IS_ERR(ext))
962                 return PTR_ERR(ext);
963
964         if (0 == strcasecmp(ext, "RSSI")) {
965                 /*Return received signal strength indicator in -db for */
966                 /* current AP */
967                 /*<ssid> Rssi xx */
968                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
969                 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
970                 /*static u8 xxxx; */
971                 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
972                         sprintf(ext, "%s rssi %d",
973                                 pcur_network->network.Ssid.Ssid,
974                                 /*(xxxx=xxxx+10) */
975                                 ((padapter->recvpriv.fw_rssi)>>1)-95
976                                 /*pcur_network->network.Rssi */
977                                 );
978                 } else {
979                         sprintf(ext, "OK");
980                 }
981         } else if (0 == strcasecmp(ext, "LINKSPEED")) {
982                 /*Return link speed in MBPS */
983                 /*LinkSpeed xx */
984                 union iwreq_data wrqd;
985                 int ret_inner;
986                 int mbps;
987
988                 ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
989                 if (0 != ret_inner)
990                         mbps = 0;
991                 else
992                         mbps = wrqd.bitrate.value / 1000000;
993                 sprintf(ext, "LINKSPEED %d", mbps);
994         } else if (0 == strcasecmp(ext, "MACADDR")) {
995                 /*Return mac address of the station */
996                 /* Macaddr = xx:xx:xx:xx:xx:xx */
997                 sprintf(ext, "MACADDR = %pM", dev->dev_addr);
998         } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
999                 /*Set scan type to active */
1000                 /*OK if successful */
1001                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1002                 pmlmepriv->passive_mode = 1;
1003                 sprintf(ext, "OK");
1004         } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1005                 /*Set scan type to passive */
1006                 /*OK if successful */
1007                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1008                 pmlmepriv->passive_mode = 0;
1009                 sprintf(ext, "OK");
1010         } else if (0 == strncmp(ext, "DCE-E", 5)) {
1011                 /*Set scan type to passive */
1012                 /*OK if successful */
1013                 r8712_disconnectCtrlEx_cmd(padapter
1014                         , 1 /*u32 enableDrvCtrl */
1015                         , 5 /*u32 tryPktCnt */
1016                         , 100 /*u32 tryPktInterval */
1017                         , 5000 /*u32 firstStageTO */
1018                 );
1019                 sprintf(ext, "OK");
1020         } else if (0 == strncmp(ext, "DCE-D", 5)) {
1021                 /*Set scan type to passive */
1022                 /*OK if successfu */
1023                 r8712_disconnectCtrlEx_cmd(padapter
1024                         , 0 /*u32 enableDrvCtrl */
1025                         , 5 /*u32 tryPktCnt */
1026                         , 100 /*u32 tryPktInterval */
1027                         , 5000 /*u32 firstStageTO */
1028                 );
1029                 sprintf(ext, "OK");
1030         } else {
1031                 netdev_info(dev, "r8712u: %s: unknown Command %s.\n",
1032                             __func__, ext);
1033                 goto FREE_EXT;
1034         }
1035         if (copy_to_user(dwrq->pointer, ext,
1036                                 min(dwrq->length, (__u16)(strlen(ext)+1))))
1037                 ret = -EFAULT;
1038
1039 FREE_EXT:
1040         kfree(ext);
1041         return ret;
1042 }
1043
1044 /* set bssid flow
1045  * s1. set_802_11_infrastructure_mode()
1046  * s2. set_802_11_authentication_mode()
1047  * s3. set_802_11_encryption_mode()
1048  * s4. set_802_11_bssid()
1049  *
1050  * This function intends to handle the Set AP command, which specifies the
1051  * MAC# of a preferred Access Point.
1052  * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1053  *
1054  * For this operation to succeed, there is no need for the interface to be up.
1055  *
1056  */
1057 static int r8711_wx_set_wap(struct net_device *dev,
1058                          struct iw_request_info *info,
1059                          union iwreq_data *awrq,
1060                          char *extra)
1061 {
1062         int ret = -EINPROGRESS;
1063         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1064         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1065         struct  __queue *queue = &pmlmepriv->scanned_queue;
1066         struct sockaddr *temp = (struct sockaddr *)awrq;
1067         unsigned long irqL;
1068         struct list_head *phead;
1069         u8 *dst_bssid;
1070         struct wlan_network *pnetwork = NULL;
1071         enum NDIS_802_11_AUTHENTICATION_MODE    authmode;
1072
1073         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1074                 return -EBUSY;
1075         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1076                 return ret;
1077         if (temp->sa_family != ARPHRD_ETHER)
1078                 return -EINVAL;
1079         authmode = padapter->securitypriv.ndisauthtype;
1080         spin_lock_irqsave(&queue->lock, irqL);
1081         phead = &queue->queue;
1082         pmlmepriv->pscanned = phead->next;
1083         while (1) {
1084                 if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1085                         break;
1086                 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1087                            struct wlan_network, list);
1088                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1089                 dst_bssid = pnetwork->network.MacAddress;
1090                 if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1091                         r8712_set_802_11_infrastructure_mode(padapter,
1092                             pnetwork->network.InfrastructureMode);
1093                         break;
1094                 }
1095         }
1096         spin_unlock_irqrestore(&queue->lock, irqL);
1097         if (!ret) {
1098                 if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1099                         ret = -ENOMEM;
1100                 else {
1101                         if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1102                                 ret = -1;
1103                 }
1104         }
1105         return ret;
1106 }
1107
1108 static int r8711_wx_get_wap(struct net_device *dev,
1109                                 struct iw_request_info *info,
1110                                 union iwreq_data *wrqu, char *extra)
1111 {
1112         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1113         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1114         struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1115
1116         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1117         if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
1118                                      WIFI_AP_STATE))
1119                 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1120         else
1121                 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1122         return 0;
1123 }
1124
1125 static int r871x_wx_set_mlme(struct net_device *dev,
1126                              struct iw_request_info *info,
1127                              union iwreq_data *wrqu, char *extra)
1128 {
1129         int ret = 0;
1130         u16 reason;
1131         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1132         struct iw_mlme *mlme = (struct iw_mlme *) extra;
1133
1134         if (mlme == NULL)
1135                 return -1;
1136         reason = cpu_to_le16(mlme->reason_code);
1137         switch (mlme->cmd) {
1138         case IW_MLME_DEAUTH:
1139                 if (!r8712_set_802_11_disassociate(padapter))
1140                         ret = -1;
1141                 break;
1142         case IW_MLME_DISASSOC:
1143                 if (!r8712_set_802_11_disassociate(padapter))
1144                         ret = -1;
1145                 break;
1146         default:
1147                 return -EOPNOTSUPP;
1148         }
1149         return ret;
1150 }
1151
1152 /**
1153  *
1154  * This function intends to handle the Set Scan command.
1155  * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
1156  *
1157  * For this operation to succeed, the interface is brought Up beforehand.
1158  *
1159  */
1160 static int r8711_wx_set_scan(struct net_device *dev,
1161                         struct iw_request_info *a,
1162                         union iwreq_data *wrqu, char *extra)
1163 {
1164         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1165         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1166         u8 status = true;
1167
1168         if (padapter->bDriverStopped == true) {
1169                 netdev_info(dev, "In %s: bDriverStopped=%d\n",
1170                             __func__, padapter->bDriverStopped);
1171                 return -1;
1172         }
1173         if (padapter->bup == false)
1174                 return -ENETDOWN;
1175         if (padapter->hw_init_completed == false)
1176                 return -1;
1177         if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1178             (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1179                 return 0;
1180         if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1181                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1182                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1183                         struct ndis_802_11_ssid ssid;
1184                         unsigned long irqL;
1185                         u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
1186                         memset((unsigned char *)&ssid, 0,
1187                                  sizeof(struct ndis_802_11_ssid));
1188                         memcpy(ssid.Ssid, req->essid, len);
1189                         ssid.SsidLength = len;
1190                         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1191                         if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1192                              _FW_UNDER_LINKING)) ||
1193                             (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1194                                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1195                                         status = false;
1196                         } else
1197                                 status = r8712_sitesurvey_cmd(padapter, &ssid);
1198                         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1199                 }
1200         } else
1201                 status = r8712_set_802_11_bssid_list_scan(padapter);
1202         if (status == false)
1203                 return -1;
1204         return 0;
1205 }
1206
1207 static int r8711_wx_get_scan(struct net_device *dev,
1208                                 struct iw_request_info *a,
1209                                 union iwreq_data *wrqu, char *extra)
1210 {
1211         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1212         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1213         struct  __queue *queue = &pmlmepriv->scanned_queue;
1214         struct wlan_network *pnetwork = NULL;
1215         unsigned long irqL;
1216         struct list_head *plist, *phead;
1217         char *ev = extra;
1218         char *stop = ev + wrqu->data.length;
1219         u32 ret = 0, cnt = 0;
1220
1221         if (padapter->bDriverStopped)
1222                 return -EINVAL;
1223         while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1224                 msleep(30);
1225                 cnt++;
1226                 if (cnt > 100)
1227                         break;
1228         }
1229         spin_lock_irqsave(&queue->lock, irqL);
1230         phead = &queue->queue;
1231         plist = phead->next;
1232         while (1) {
1233                 if (end_of_queue_search(phead, plist) == true)
1234                         break;
1235                 if ((stop - ev) < SCAN_ITEM_SIZE) {
1236                         ret = -E2BIG;
1237                         break;
1238                 }
1239                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1240                 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1241                 plist = plist->next;
1242         }
1243         spin_unlock_irqrestore(&queue->lock, irqL);
1244         wrqu->data.length = ev - extra;
1245         wrqu->data.flags = 0;
1246         return ret;
1247 }
1248
1249 /* set ssid flow
1250  * s1. set_802_11_infrastructure_mode()
1251  * s2. set_802_11_authenticaion_mode()
1252  * s3. set_802_11_encryption_mode()
1253  * s4. set_802_11_ssid()
1254  *
1255  * This function intends to handle the Set ESSID command.
1256  * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1257  *
1258  * For this operation to succeed, there is no need for the interface to be Up.
1259  *
1260  */
1261 static int r8711_wx_set_essid(struct net_device *dev,
1262                                 struct iw_request_info *a,
1263                                 union iwreq_data *wrqu, char *extra)
1264 {
1265         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1266         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1267         struct  __queue *queue = &pmlmepriv->scanned_queue;
1268         struct wlan_network *pnetwork = NULL;
1269         enum NDIS_802_11_AUTHENTICATION_MODE    authmode;
1270         struct ndis_802_11_ssid ndis_ssid;
1271         u8 *dst_ssid, *src_ssid;
1272         struct list_head *phead;
1273         u32 len;
1274
1275         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1276                 return -EBUSY;
1277         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1278                 return 0;
1279         if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1280                 return -E2BIG;
1281         authmode = padapter->securitypriv.ndisauthtype;
1282         if (wrqu->essid.flags && wrqu->essid.length) {
1283                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1284                        wrqu->essid.length : IW_ESSID_MAX_SIZE;
1285                 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1286                 ndis_ssid.SsidLength = len;
1287                 memcpy(ndis_ssid.Ssid, extra, len);
1288                 src_ssid = ndis_ssid.Ssid;
1289                 phead = &queue->queue;
1290                 pmlmepriv->pscanned = phead->next;
1291                 while (1) {
1292                         if (end_of_queue_search(phead, pmlmepriv->pscanned))
1293                                 break;
1294                         pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1295                                    struct wlan_network, list);
1296                         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1297                         dst_ssid = pnetwork->network.Ssid.Ssid;
1298                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1299                             && (pnetwork->network.Ssid.SsidLength ==
1300                              ndis_ssid.SsidLength)) {
1301                                 if (check_fwstate(pmlmepriv,
1302                                                         WIFI_ADHOC_STATE)) {
1303                                         if (pnetwork->network.
1304                                                 InfrastructureMode
1305                                                 !=
1306                                                 padapter->mlmepriv.
1307                                                 cur_network.network.
1308                                                 InfrastructureMode)
1309                                                 continue;
1310                                 }
1311
1312                                 r8712_set_802_11_infrastructure_mode(
1313                                      padapter,
1314                                      pnetwork->network.InfrastructureMode);
1315                                 break;
1316                         }
1317                 }
1318                 r8712_set_802_11_authentication_mode(padapter, authmode);
1319                 r8712_set_802_11_ssid(padapter, &ndis_ssid);
1320         }
1321         return -EINPROGRESS;
1322 }
1323
1324 static int r8711_wx_get_essid(struct net_device *dev,
1325                                 struct iw_request_info *a,
1326                                 union iwreq_data *wrqu, char *extra)
1327 {
1328         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1329         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1330         struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1331         u32 len, ret = 0;
1332
1333         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1334                 len = pcur_bss->Ssid.SsidLength;
1335                 wrqu->essid.length = len;
1336                 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1337                 wrqu->essid.flags = 1;
1338         } else {
1339                 ret = -ENOLINK;
1340         }
1341         return ret;
1342 }
1343
1344 static int r8711_wx_set_rate(struct net_device *dev,
1345                                 struct iw_request_info *a,
1346                                 union iwreq_data *wrqu, char *extra)
1347 {
1348         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1349         u32 target_rate = wrqu->bitrate.value;
1350         u32 fixed = wrqu->bitrate.fixed;
1351         u32 ratevalue = 0;
1352         u8 datarates[NumRates];
1353         u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1354         int i, ret = 0;
1355
1356         if (target_rate == -1) {
1357                 ratevalue = 11;
1358                 goto set_rate;
1359         }
1360         target_rate = target_rate / 100000;
1361         switch (target_rate) {
1362         case 10:
1363                 ratevalue = 0;
1364                 break;
1365         case 20:
1366                 ratevalue = 1;
1367                 break;
1368         case 55:
1369                 ratevalue = 2;
1370                 break;
1371         case 60:
1372                 ratevalue = 3;
1373                 break;
1374         case 90:
1375                 ratevalue = 4;
1376                 break;
1377         case 110:
1378                 ratevalue = 5;
1379                 break;
1380         case 120:
1381                 ratevalue = 6;
1382                 break;
1383         case 180:
1384                 ratevalue = 7;
1385                 break;
1386         case 240:
1387                 ratevalue = 8;
1388                 break;
1389         case 360:
1390                 ratevalue = 9;
1391                 break;
1392         case 480:
1393                 ratevalue = 10;
1394                 break;
1395         case 540:
1396                 ratevalue = 11;
1397                 break;
1398         default:
1399                 ratevalue = 11;
1400                 break;
1401         }
1402 set_rate:
1403         for (i = 0; i < NumRates; i++) {
1404                 if (ratevalue == mpdatarate[i]) {
1405                         datarates[i] = mpdatarate[i];
1406                         if (fixed == 0)
1407                                 break;
1408                 } else
1409                         datarates[i] = 0xff;
1410         }
1411         if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1412                 ret = -ENOMEM;
1413         return ret;
1414 }
1415
1416 static int r8711_wx_get_rate(struct net_device *dev,
1417                              struct iw_request_info *info,
1418                              union iwreq_data *wrqu, char *extra)
1419 {
1420         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1421         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1422         struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1423         struct ieee80211_ht_cap *pht_capie;
1424         unsigned char rf_type = padapter->registrypriv.rf_config;
1425         int i;
1426         u8 *p;
1427         u16 rate, max_rate = 0, ht_cap = false;
1428         u32 ht_ielen = 0;
1429         u8 bw_40MHz = 0, short_GI = 0;
1430         u16 mcs_rate = 0;
1431
1432         i = 0;
1433         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1434                 p = r8712_get_ie(&pcur_bss->IEs[12],
1435                                  _HT_CAPABILITY_IE_, &ht_ielen,
1436                     pcur_bss->IELength - 12);
1437                 if (p && ht_ielen > 0) {
1438                         ht_cap = true;
1439                         pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1440                         memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1441                         bw_40MHz = (pht_capie->cap_info &
1442                                     IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1443                         short_GI = (pht_capie->cap_info &
1444                                     (IEEE80211_HT_CAP_SGI_20 |
1445                                     IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1446                 }
1447                 while ((pcur_bss->SupportedRates[i] != 0) &&
1448                         (pcur_bss->SupportedRates[i] != 0xFF)) {
1449                         rate = pcur_bss->SupportedRates[i] & 0x7F;
1450                         if (rate > max_rate)
1451                                 max_rate = rate;
1452                         wrqu->bitrate.fixed = 0;        /* no auto select */
1453                         wrqu->bitrate.value = rate*500000;
1454                         i++;
1455                 }
1456                 if (ht_cap == true) {
1457                         if (mcs_rate & 0x8000 /* MCS15 */
1458                                 &&
1459                                 RTL8712_RF_2T2R == rf_type)
1460                                 max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1461                                             270) : ((short_GI) ? 144 : 130);
1462                         else /* default MCS7 */
1463                                 max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1464                                             135) : ((short_GI) ? 72 : 65);
1465                         max_rate *= 2; /* Mbps/2 */
1466                 }
1467                 wrqu->bitrate.value = max_rate * 500000;
1468         } else
1469                 return -ENOLINK;
1470         return 0;
1471 }
1472
1473 static int r8711_wx_get_rts(struct net_device *dev,
1474                                 struct iw_request_info *info,
1475                                 union iwreq_data *wrqu, char *extra)
1476 {
1477         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1478
1479         wrqu->rts.value = padapter->registrypriv.rts_thresh;
1480         wrqu->rts.fixed = 0;    /* no auto select */
1481         return 0;
1482 }
1483
1484 static int r8711_wx_set_frag(struct net_device *dev,
1485                                 struct iw_request_info *info,
1486                                 union iwreq_data *wrqu, char *extra)
1487 {
1488         struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1489
1490         if (wrqu->frag.disabled)
1491                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1492         else {
1493                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1494                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
1495                         return -EINVAL;
1496                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1497         }
1498         return 0;
1499 }
1500
1501 static int r8711_wx_get_frag(struct net_device *dev,
1502                                 struct iw_request_info *info,
1503                                 union iwreq_data *wrqu, char *extra)
1504 {
1505         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1506
1507         wrqu->frag.value = padapter->xmitpriv.frag_len;
1508         wrqu->frag.fixed = 0;   /* no auto select */
1509         return 0;
1510 }
1511
1512 static int r8711_wx_get_retry(struct net_device *dev,
1513                                 struct iw_request_info *info,
1514                                 union iwreq_data *wrqu, char *extra)
1515 {
1516         wrqu->retry.value = 7;
1517         wrqu->retry.fixed = 0;  /* no auto select */
1518         wrqu->retry.disabled = 1;
1519         return 0;
1520 }
1521
1522 static int r8711_wx_set_enc(struct net_device *dev,
1523                                 struct iw_request_info *info,
1524                                 union iwreq_data *wrqu, char *keybuf)
1525 {
1526         u32 key;
1527         u32 keyindex_provided;
1528         struct NDIS_802_11_WEP   wep;
1529         enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1530         struct iw_point *erq = &(wrqu->encoding);
1531         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1532
1533         key = erq->flags & IW_ENCODE_INDEX;
1534         memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1535         if (erq->flags & IW_ENCODE_DISABLED) {
1536                 netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
1537                 padapter->securitypriv.ndisencryptstatus =
1538                                  Ndis802_11EncryptionDisabled;
1539                 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1540                 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1541                 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1542                 authmode = Ndis802_11AuthModeOpen;
1543                 padapter->securitypriv.ndisauthtype = authmode;
1544                 return 0;
1545         }
1546         if (key) {
1547                 if (key > WEP_KEYS)
1548                         return -EINVAL;
1549                 key--;
1550                 keyindex_provided = 1;
1551         } else {
1552                 keyindex_provided = 0;
1553                 key = padapter->securitypriv.PrivacyKeyIndex;
1554         }
1555         /* set authentication mode */
1556         if (erq->flags & IW_ENCODE_OPEN) {
1557                 netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
1558                 padapter->securitypriv.ndisencryptstatus =
1559                                  Ndis802_11Encryption1Enabled;
1560                 padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1561                 padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1562                 padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1563                 authmode = Ndis802_11AuthModeOpen;
1564                 padapter->securitypriv.ndisauthtype = authmode;
1565         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1566                 netdev_info(dev, "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                 break;
2148         case IEEE_PARAM_IEEE_802_1X:
2149                 break;
2150         case IEEE_PARAM_WPAX_SELECT:
2151                 /* added for WPA2 mixed mode */
2152                 break;
2153         default:
2154                 return -EOPNOTSUPP;
2155         }
2156         return 0;
2157 }
2158
2159 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2160 {
2161         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2162
2163         switch (command) {
2164         case IEEE_MLME_STA_DEAUTH:
2165                 if (!r8712_set_802_11_disassociate(padapter))
2166                         return -1;
2167                 break;
2168         case IEEE_MLME_STA_DISASSOC:
2169                 if (!r8712_set_802_11_disassociate(padapter))
2170                         return -1;
2171                 break;
2172         default:
2173                 return -EOPNOTSUPP;
2174         }
2175         return 0;
2176 }
2177
2178 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2179 {
2180         struct ieee_param *param;
2181         int ret = 0;
2182         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2183
2184         if (p->length < sizeof(struct ieee_param) || !p->pointer)
2185                 return -EINVAL;
2186         param = memdup_user(p->pointer, p->length);
2187         if (IS_ERR(param))
2188                 return PTR_ERR(param);
2189         switch (param->cmd) {
2190         case IEEE_CMD_SET_WPA_PARAM:
2191                 ret = wpa_set_param(dev, param->u.wpa_param.name,
2192                       param->u.wpa_param.value);
2193                 break;
2194         case IEEE_CMD_SET_WPA_IE:
2195                 ret =  r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2196                        (u16)param->u.wpa_ie.len);
2197                 break;
2198         case IEEE_CMD_SET_ENCRYPTION:
2199                 ret = wpa_set_encryption(dev, param, p->length);
2200                 break;
2201         case IEEE_CMD_MLME:
2202                 ret = wpa_mlme(dev, param->u.mlme.command,
2203                       param->u.mlme.reason_code);
2204                 break;
2205         default:
2206                 ret = -EOPNOTSUPP;
2207                 break;
2208         }
2209         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2210                 ret = -EFAULT;
2211         kfree((u8 *)param);
2212         return ret;
2213 }
2214
2215 /* based on "driver_ipw" and for hostapd */
2216 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2217 {
2218         struct iwreq *wrq = (struct iwreq *)rq;
2219
2220         switch (cmd) {
2221         case RTL_IOCTL_WPA_SUPPLICANT:
2222                 return wpa_supplicant_ioctl(dev, &wrq->u.data);
2223         default:
2224                 return -EOPNOTSUPP;
2225         }
2226         return 0;
2227 }
2228
2229 static iw_handler r8711_handlers[] = {
2230         NULL,                           /* SIOCSIWCOMMIT */
2231         r8711_wx_get_name,              /* SIOCGIWNAME */
2232         dummy,                          /* SIOCSIWNWID */
2233         dummy,                          /* SIOCGIWNWID */
2234         r8711_wx_set_freq,              /* SIOCSIWFREQ */
2235         r8711_wx_get_freq,              /* SIOCGIWFREQ */
2236         r8711_wx_set_mode,              /* SIOCSIWMODE */
2237         r8711_wx_get_mode,              /* SIOCGIWMODE */
2238         dummy,                          /* SIOCSIWSENS */
2239         r8711_wx_get_sens,              /* SIOCGIWSENS */
2240         NULL,                           /* SIOCSIWRANGE */
2241         r8711_wx_get_range,             /* SIOCGIWRANGE */
2242         r871x_wx_set_priv,              /* SIOCSIWPRIV */
2243         NULL,                           /* SIOCGIWPRIV */
2244         NULL,                           /* SIOCSIWSTATS */
2245         NULL,                           /* SIOCGIWSTATS */
2246         dummy,                          /* SIOCSIWSPY */
2247         dummy,                          /* SIOCGIWSPY */
2248         NULL,                           /* SIOCGIWTHRSPY */
2249         NULL,                           /* SIOCWIWTHRSPY */
2250         r8711_wx_set_wap,               /* SIOCSIWAP */
2251         r8711_wx_get_wap,               /* SIOCGIWAP */
2252         r871x_wx_set_mlme,              /* request MLME operation;
2253                                          *  uses struct iw_mlme */
2254         dummy,                          /* SIOCGIWAPLIST -- deprecated */
2255         r8711_wx_set_scan,              /* SIOCSIWSCAN */
2256         r8711_wx_get_scan,              /* SIOCGIWSCAN */
2257         r8711_wx_set_essid,             /* SIOCSIWESSID */
2258         r8711_wx_get_essid,             /* SIOCGIWESSID */
2259         dummy,                          /* SIOCSIWNICKN */
2260         r871x_wx_get_nick,              /* SIOCGIWNICKN */
2261         NULL,                           /* -- hole -- */
2262         NULL,                           /* -- hole -- */
2263         r8711_wx_set_rate,              /* SIOCSIWRATE */
2264         r8711_wx_get_rate,              /* SIOCGIWRATE */
2265         dummy,                          /* SIOCSIWRTS */
2266         r8711_wx_get_rts,               /* SIOCGIWRTS */
2267         r8711_wx_set_frag,              /* SIOCSIWFRAG */
2268         r8711_wx_get_frag,              /* SIOCGIWFRAG */
2269         dummy,                          /* SIOCSIWTXPOW */
2270         dummy,                          /* SIOCGIWTXPOW */
2271         dummy,                          /* SIOCSIWRETRY */
2272         r8711_wx_get_retry,             /* SIOCGIWRETRY */
2273         r8711_wx_set_enc,               /* SIOCSIWENCODE */
2274         r8711_wx_get_enc,               /* SIOCGIWENCODE */
2275         dummy,                          /* SIOCSIWPOWER */
2276         r8711_wx_get_power,             /* SIOCGIWPOWER */
2277         NULL,                           /*---hole---*/
2278         NULL,                           /*---hole---*/
2279         r871x_wx_set_gen_ie,            /* SIOCSIWGENIE */
2280         NULL,                           /* SIOCGIWGENIE */
2281         r871x_wx_set_auth,              /* SIOCSIWAUTH */
2282         NULL,                           /* SIOCGIWAUTH */
2283         r871x_wx_set_enc_ext,           /* SIOCSIWENCODEEXT */
2284         NULL,                           /* SIOCGIWENCODEEXT */
2285         r871x_wx_set_pmkid,             /* SIOCSIWPMKSA */
2286         NULL,                           /*---hole---*/
2287 };
2288
2289 static const struct iw_priv_args r8711_private_args[] = {
2290         {
2291                 SIOCIWFIRSTPRIV + 0x0,
2292                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2293         },
2294         {
2295                 SIOCIWFIRSTPRIV + 0x1,
2296                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2297         },
2298         {
2299                 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2300         },
2301         {
2302                 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2303         },
2304         {
2305                 SIOCIWFIRSTPRIV + 0x4,
2306                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2307         },
2308         {
2309                 SIOCIWFIRSTPRIV + 0x5,
2310                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2311         },
2312         {
2313                 SIOCIWFIRSTPRIV + 0x6,
2314                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2315         },
2316         {
2317                 SIOCIWFIRSTPRIV + 0x7,
2318                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2319         }
2320 };
2321
2322 static iw_handler r8711_private_handler[] = {
2323         r8711_wx_read32,
2324         r8711_wx_write32,
2325         r8711_drvext_hdl,
2326         r871x_mp_ioctl_hdl,
2327         r871x_get_ap_info, /*for MM DTV platform*/
2328         r871x_set_pid,
2329         r871x_wps_start,
2330         r871x_set_chplan
2331 };
2332
2333 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2334 {
2335         struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2336         struct iw_statistics *piwstats = &padapter->iwstats;
2337         int tmp_level = 0;
2338         int tmp_qual = 0;
2339         int tmp_noise = 0;
2340
2341         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2342                 piwstats->qual.qual = 0;
2343                 piwstats->qual.level = 0;
2344                 piwstats->qual.noise = 0;
2345         } else {
2346                 /* show percentage, we need transfer dbm to orignal value. */
2347                 tmp_level = padapter->recvpriv.fw_rssi;
2348                 tmp_qual = padapter->recvpriv.signal;
2349                 tmp_noise = padapter->recvpriv.noise;
2350                 piwstats->qual.level = tmp_level;
2351                 piwstats->qual.qual = tmp_qual;
2352                 piwstats->qual.noise = tmp_noise;
2353         }
2354         piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2355         return &padapter->iwstats;
2356 }
2357
2358 struct iw_handler_def r871x_handlers_def = {
2359         .standard = r8711_handlers,
2360         .num_standard = ARRAY_SIZE(r8711_handlers),
2361         .private = r8711_private_handler,
2362         .private_args = (struct iw_priv_args *)r8711_private_args,
2363         .num_private = ARRAY_SIZE(r8711_private_handler),
2364         .num_private_args = sizeof(r8711_private_args) /
2365                             sizeof(struct iw_priv_args),
2366         .get_wireless_stats = r871x_get_wireless_stats
2367 };