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