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