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