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