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