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