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