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