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