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