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