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