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