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