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