Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8188eu / os_dep / ioctl_linux.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _IOCTL_LINUX_C_
21
22 #include <osdep_service.h>
23 #include <drv_types.h>
24 #include <wlan_bssdef.h>
25 #include <rtw_debug.h>
26 #include <wifi.h>
27 #include <rtw_mlme.h>
28 #include <rtw_mlme_ext.h>
29 #include <rtw_ioctl.h>
30 #include <rtw_ioctl_set.h>
31 #include <rtl8188e_hal.h>
32
33 #include <rtw_iol.h>
34 #include <linux/vmalloc.h>
35 #include <linux/etherdevice.h>
36
37 #include "osdep_intf.h"
38
39 #define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV + 30)
40
41 #define SCAN_ITEM_SIZE 768
42 #define MAX_CUSTOM_LEN 64
43 #define RATE_COUNT 4
44
45 /*  combo scan */
46 #define WEXT_CSCAN_AMOUNT 9
47 #define WEXT_CSCAN_BUF_LEN              360
48 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
49 #define WEXT_CSCAN_HEADER_SIZE          12
50 #define WEXT_CSCAN_SSID_SECTION         'S'
51 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
52 #define WEXT_CSCAN_NPROBE_SECTION       'N'
53 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
54 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
55 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
56 #define WEXT_CSCAN_TYPE_SECTION         'T'
57
58 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
59         6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
60         48000000, 54000000};
61
62 static const char * const iw_operation_mode[] = {
63         "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater",
64         "Secondary", "Monitor"
65 };
66
67 void indicate_wx_scan_complete_event(struct adapter *padapter)
68 {
69         union iwreq_data wrqu;
70
71         memset(&wrqu, 0, sizeof(union iwreq_data));
72         wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
73 }
74
75 void rtw_indicate_wx_assoc_event(struct adapter *padapter)
76 {
77         union iwreq_data wrqu;
78         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
79
80         memset(&wrqu, 0, sizeof(union iwreq_data));
81
82         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
83
84         memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
85
86         DBG_88E_LEVEL(_drv_always_, "assoc success\n");
87         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
88 }
89
90 void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
91 {
92         union iwreq_data wrqu;
93
94         memset(&wrqu, 0, sizeof(union iwreq_data));
95
96         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
97         eth_zero_addr(wrqu.ap_addr.sa_data);
98
99         DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
100         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
101 }
102
103 static char *translate_scan(struct adapter *padapter,
104                             struct iw_request_info *info,
105                             struct wlan_network *pnetwork,
106                             char *start, char *stop)
107 {
108         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
109         struct iw_event iwe;
110         u16 cap;
111         __le16 le_tmp;
112         u32 ht_ielen = 0;
113         char custom[MAX_CUSTOM_LEN];
114         char *p;
115         u16 max_rate = 0, rate, ht_cap = false;
116         u32 i = 0;
117         u8 bw_40MHz = 0, short_GI = 0;
118         u16 mcs_rate = 0;
119         u8 ss, sq;
120
121         /*  AP MAC address  */
122         iwe.cmd = SIOCGIWAP;
123         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
124
125         memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
126         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
127
128         /* Add the ESSID */
129         iwe.cmd = SIOCGIWESSID;
130         iwe.u.data.flags = 1;
131         iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
132         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
133
134         /* parsing HT_CAP_IE */
135         p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
136
137         if (p && ht_ielen > 0) {
138                 struct rtw_ieee80211_ht_cap *pht_capie;
139                 ht_cap = true;
140                 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
141                 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
142                 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
143                 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
144         }
145
146         /* Add the protocol name */
147         iwe.cmd = SIOCGIWNAME;
148         if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
149                 if (ht_cap)
150                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
151                 else
152                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
153         } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
154                 if (ht_cap)
155                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
156                 else
157                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
158         } else {
159                 if (pnetwork->network.Configuration.DSConfig > 14) {
160                         if (ht_cap)
161                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
162                         else
163                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
164                 } else {
165                         if (ht_cap)
166                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
167                         else
168                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
169                 }
170         }
171
172         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
173
174           /* Add mode */
175         iwe.cmd = SIOCGIWMODE;
176         memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
177
178         cap = le16_to_cpu(le_tmp);
179
180         if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
181                 if (cap & WLAN_CAPABILITY_BSS)
182                         iwe.u.mode = IW_MODE_MASTER;
183                 else
184                         iwe.u.mode = IW_MODE_ADHOC;
185
186                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
187         }
188
189         if (pnetwork->network.Configuration.DSConfig < 1)
190                 pnetwork->network.Configuration.DSConfig = 1;
191
192          /* Add frequency/channel */
193         iwe.cmd = SIOCGIWFREQ;
194         iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
195         iwe.u.freq.e = 1;
196         iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
197         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
198
199         /* Add encryption capability */
200         iwe.cmd = SIOCGIWENCODE;
201         if (cap & WLAN_CAPABILITY_PRIVACY)
202                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
203         else
204                 iwe.u.data.flags = IW_ENCODE_DISABLED;
205         iwe.u.data.length = 0;
206         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
207
208         /*Add basic and extended rates */
209         max_rate = 0;
210         p = custom;
211         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
212         while (pnetwork->network.SupportedRates[i] != 0) {
213                 rate = pnetwork->network.SupportedRates[i]&0x7F;
214                 if (rate > max_rate)
215                         max_rate = rate;
216                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
217                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
218                 i++;
219         }
220
221         if (ht_cap) {
222                 if (mcs_rate&0x8000)/* MCS15 */
223                         max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
224                 else if (mcs_rate&0x0080)/* MCS7 */
225                         ;
226                 else/* default MCS7 */
227                         max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
228
229                 max_rate = max_rate*2;/* Mbps/2; */
230         }
231
232         iwe.cmd = SIOCGIWRATE;
233         iwe.u.bitrate.fixed = 0;
234         iwe.u.bitrate.disabled = 0;
235         iwe.u.bitrate.value = max_rate * 500000;
236         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
237
238         /* parsing WPA/WPA2 IE */
239         {
240                 u8 buf[MAX_WPA_IE_LEN];
241                 u8 wpa_ie[255], rsn_ie[255];
242                 u16 wpa_len = 0, rsn_len = 0;
243                 u8 *p;
244
245                 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
246                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
247                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
248
249                 if (wpa_len > 0) {
250                         p = buf;
251                         memset(buf, 0, MAX_WPA_IE_LEN);
252                         p += sprintf(p, "wpa_ie=");
253                         for (i = 0; i < wpa_len; i++)
254                                 p += sprintf(p, "%02x", wpa_ie[i]);
255
256                         memset(&iwe, 0, sizeof(iwe));
257                         iwe.cmd = IWEVCUSTOM;
258                         iwe.u.data.length = strlen(buf);
259                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
260
261                         memset(&iwe, 0, sizeof(iwe));
262                         iwe.cmd = IWEVGENIE;
263                         iwe.u.data.length = wpa_len;
264                         start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
265                 }
266                 if (rsn_len > 0) {
267                         p = buf;
268                         memset(buf, 0, MAX_WPA_IE_LEN);
269                         p += sprintf(p, "rsn_ie=");
270                         for (i = 0; i < rsn_len; i++)
271                                 p += sprintf(p, "%02x", rsn_ie[i]);
272                         memset(&iwe, 0, sizeof(iwe));
273                         iwe.cmd = IWEVCUSTOM;
274                         iwe.u.data.length = strlen(buf);
275                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
276
277                         memset(&iwe, 0, sizeof(iwe));
278                         iwe.cmd = IWEVGENIE;
279                         iwe.u.data.length = rsn_len;
280                         start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
281                 }
282         }
283
284         {/* parsing WPS IE */
285                 uint cnt = 0, total_ielen;
286                 u8 *wpsie_ptr = NULL;
287                 uint wps_ielen = 0;
288
289                 u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
290                 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
291
292                 while (cnt < total_ielen) {
293                         if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
294                                 wpsie_ptr = &ie_ptr[cnt];
295                                 iwe.cmd = IWEVGENIE;
296                                 iwe.u.data.length = (u16)wps_ielen;
297                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
298                         }
299                         cnt += ie_ptr[cnt+1]+2; /* goto next */
300                 }
301         }
302
303         /* Add quality statistics */
304         iwe.cmd = IWEVQUAL;
305         iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
306
307         if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
308             is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
309                 ss = padapter->recvpriv.signal_strength;
310                 sq = padapter->recvpriv.signal_qual;
311         } else {
312                 ss = pnetwork->network.PhyInfo.SignalStrength;
313                 sq = pnetwork->network.PhyInfo.SignalQuality;
314         }
315
316         iwe.u.qual.level = (u8)ss;
317         iwe.u.qual.qual = (u8)sq;   /*  signal quality */
318         iwe.u.qual.noise = 0; /*  noise level */
319         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
320         return start;
321 }
322
323 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
324 {
325         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
326         int ret = 0;
327
328         if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
329                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
330                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
331                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
332                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
333         } else if (value & AUTH_ALG_SHARED_KEY) {
334                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n", value);
335                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
336
337                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
338                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
339         } else if (value & AUTH_ALG_OPEN_SYSTEM) {
340                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
341                 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
342                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
343                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
344                 }
345         } else if (value & AUTH_ALG_LEAP) {
346                 DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
347         } else {
348                 DBG_88E("wpa_set_auth_algs, error!\n");
349                 ret = -EINVAL;
350         }
351         return ret;
352 }
353
354 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
355 {
356         int ret = 0;
357         u32 wep_key_idx, wep_key_len, wep_total_len;
358         struct ndis_802_11_wep   *pwep = NULL;
359         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
360         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
361         struct security_priv *psecuritypriv = &padapter->securitypriv;
362
363         param->u.crypt.err = 0;
364         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
365
366         if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
367                 ret =  -EINVAL;
368                 goto exit;
369         }
370
371         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
372             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
373             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
374                 if (param->u.crypt.idx >= WEP_KEYS) {
375                         ret = -EINVAL;
376                         goto exit;
377                 }
378         } else {
379                 ret = -EINVAL;
380                 goto exit;
381         }
382
383         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
384                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
385                 DBG_88E("wpa_set_encryption, crypt.alg = WEP\n");
386
387                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
388                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
389                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
390
391                 wep_key_idx = param->u.crypt.idx;
392                 wep_key_len = param->u.crypt.key_len;
393
394                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
395                 DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
396
397                 if (wep_key_idx > WEP_KEYS)
398                         return -EINVAL;
399
400                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
401
402                 if (wep_key_len > 0) {
403                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
404                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
405                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
406                         if (pwep == NULL) {
407                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
408                                 goto exit;
409                         }
410                         memset(pwep, 0, wep_total_len);
411                         pwep->KeyLength = wep_key_len;
412                         pwep->Length = wep_total_len;
413                         if (wep_key_len == 13) {
414                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
415                                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
416                         }
417                 } else {
418                         ret = -EINVAL;
419                         goto exit;
420                 }
421                 pwep->KeyIndex = wep_key_idx;
422                 pwep->KeyIndex |= 0x80000000;
423                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
424                 if (param->u.crypt.set_tx) {
425                         DBG_88E("wep, set_tx = 1\n");
426                         if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
427                                 ret = -EOPNOTSUPP;
428                 } else {
429                         DBG_88E("wep, set_tx = 0\n");
430                         if (wep_key_idx >= WEP_KEYS) {
431                                 ret = -EOPNOTSUPP;
432                                 goto exit;
433                         }
434                       memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
435                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
436                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
437                 }
438                 goto exit;
439         }
440
441         if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
442                 struct sta_info *psta, *pbcmc_sta;
443                 struct sta_priv *pstapriv = &padapter->stapriv;
444
445                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */
446                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
447                         if (psta == NULL) {
448                                 ;
449                         } else {
450                                 if (strcmp(param->u.crypt.alg, "none") != 0)
451                                         psta->ieee8021x_blocked = false;
452
453                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
454                                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
455                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
456
457                                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
458                                         memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
459
460                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
461                                                 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
462                                                 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
463                                                 padapter->securitypriv.busetkipkey = false;
464                                         }
465
466                                         DBG_88E(" ~~~~set sta key:unicastkey\n");
467
468                                         rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
469                                 } else { /* group key */
470                                         memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
471                                         memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
472                                         memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
473                                         padapter->securitypriv.binstallGrpkey = true;
474                                         DBG_88E(" ~~~~set sta key:groupkey\n");
475
476                                         padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
477
478                                         rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
479                                 }
480                         }
481                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
482                         if (pbcmc_sta == NULL) {
483                                 ;
484                         } else {
485                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
486                                 if (strcmp(param->u.crypt.alg, "none") != 0)
487                                         pbcmc_sta->ieee8021x_blocked = false;
488
489                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
490                                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
491                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
492                         }
493                 }
494         }
495
496 exit:
497
498         kfree(pwep);
499         return ret;
500 }
501
502 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
503 {
504         u8 *buf = NULL;
505         int group_cipher = 0, pairwise_cipher = 0;
506         int ret = 0;
507
508         if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
509                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
510                 if (pie == NULL)
511                         return ret;
512                 else
513                         return -EINVAL;
514         }
515
516         if (ielen) {
517                 buf = kmemdup(pie, ielen, GFP_KERNEL);
518                 if (buf == NULL) {
519                         ret =  -ENOMEM;
520                         goto exit;
521                 }
522
523                 /* dump */
524                 {
525                         int i;
526                         DBG_88E("\n wpa_ie(length:%d):\n", ielen);
527                         for (i = 0; i < ielen; i += 8)
528                                 DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
529                 }
530
531                 if (ielen < RSN_HEADER_LEN) {
532                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
533                         ret  = -1;
534                         goto exit;
535                 }
536
537                 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
538                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
539                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
540                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
541                 }
542
543                 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
544                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
545                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
546                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
547                 }
548
549                 switch (group_cipher) {
550                 case WPA_CIPHER_NONE:
551                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
552                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
553                         break;
554                 case WPA_CIPHER_WEP40:
555                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
556                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
557                         break;
558                 case WPA_CIPHER_TKIP:
559                         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
560                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
561                         break;
562                 case WPA_CIPHER_CCMP:
563                         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
564                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
565                         break;
566                 case WPA_CIPHER_WEP104:
567                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
568                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
569                         break;
570                 }
571
572                 switch (pairwise_cipher) {
573                 case WPA_CIPHER_NONE:
574                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
575                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
576                         break;
577                 case WPA_CIPHER_WEP40:
578                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
579                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
580                         break;
581                 case WPA_CIPHER_TKIP:
582                         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
583                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
584                         break;
585                 case WPA_CIPHER_CCMP:
586                         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
587                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
588                         break;
589                 case WPA_CIPHER_WEP104:
590                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
591                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
592                         break;
593                 }
594
595                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
596                 {/* set wps_ie */
597                         u16 cnt = 0;
598                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
599
600                         while (cnt < ielen) {
601                                 eid = buf[cnt];
602                                 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
603                                         DBG_88E("SET WPS_IE\n");
604
605                                         padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2) : (MAX_WPA_IE_LEN<<2);
606
607                                         memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
608
609                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
610                                         cnt += buf[cnt+1]+2;
611                                         break;
612                                 } else {
613                                         cnt += buf[cnt+1]+2; /* goto next */
614                                 }
615                         }
616                 }
617         }
618
619         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
620                  ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
621                  pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
622 exit:
623         kfree(buf);
624         return ret;
625 }
626
627 typedef unsigned char   NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
628
629 static int rtw_wx_get_name(struct net_device *dev,
630                              struct iw_request_info *info,
631                              union iwreq_data *wrqu, char *extra)
632 {
633         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
634         u32 ht_ielen = 0;
635         char *p;
636         u8 ht_cap = false;
637         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
638         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
639         NDIS_802_11_RATES_EX *prates = NULL;
640
641         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
642
643         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
644                 /* parsing HT_CAP_IE */
645                 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
646                 if (p && ht_ielen > 0)
647                         ht_cap = true;
648
649                 prates = &pcur_bss->SupportedRates;
650
651                 if (rtw_is_cckratesonly_included((u8 *)prates) == true) {
652                         if (ht_cap)
653                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
654                         else
655                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
656                 } else if ((rtw_is_cckrates_included((u8 *)prates)) == true) {
657                         if (ht_cap)
658                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
659                         else
660                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
661                 } else {
662                         if (pcur_bss->Configuration.DSConfig > 14) {
663                                 if (ht_cap)
664                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
665                                 else
666                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
667                         } else {
668                                 if (ht_cap)
669                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
670                                 else
671                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
672                         }
673                 }
674         } else {
675                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
676         }
677         return 0;
678 }
679
680 static int rtw_wx_set_freq(struct net_device *dev,
681                              struct iw_request_info *info,
682                              union iwreq_data *wrqu, char *extra)
683 {
684         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
685         return 0;
686 }
687
688 static int rtw_wx_get_freq(struct net_device *dev,
689                              struct iw_request_info *info,
690                              union iwreq_data *wrqu, char *extra)
691 {
692         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
693         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
694         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
695
696         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
697                 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
698                 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
699                 wrqu->freq.e = 1;
700                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
701         } else {
702                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
703                 wrqu->freq.e = 1;
704                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
705         }
706
707         return 0;
708 }
709
710 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
711                              union iwreq_data *wrqu, char *b)
712 {
713         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
714         enum ndis_802_11_network_infra networkType;
715         int ret = 0;
716
717         if (_FAIL == rtw_pwr_wakeup(padapter)) {
718                 ret = -EPERM;
719                 goto exit;
720         }
721
722         if (!padapter->hw_init_completed) {
723                 ret = -EPERM;
724                 goto exit;
725         }
726
727         switch (wrqu->mode) {
728         case IW_MODE_AUTO:
729                 networkType = Ndis802_11AutoUnknown;
730                 DBG_88E("set_mode = IW_MODE_AUTO\n");
731                 break;
732         case IW_MODE_ADHOC:
733                 networkType = Ndis802_11IBSS;
734                 DBG_88E("set_mode = IW_MODE_ADHOC\n");
735                 break;
736         case IW_MODE_MASTER:
737                 networkType = Ndis802_11APMode;
738                 DBG_88E("set_mode = IW_MODE_MASTER\n");
739                 break;
740         case IW_MODE_INFRA:
741                 networkType = Ndis802_11Infrastructure;
742                 DBG_88E("set_mode = IW_MODE_INFRA\n");
743                 break;
744         default:
745                 ret = -EINVAL;
746                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
747                 goto exit;
748         }
749         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
750                 ret = -EPERM;
751                 goto exit;
752         }
753         rtw_setopmode_cmd(padapter, networkType);
754 exit:
755         return ret;
756 }
757
758 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
759                              union iwreq_data *wrqu, char *b)
760 {
761         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
762         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
763
764         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
765
766         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
767                 wrqu->mode = IW_MODE_INFRA;
768         else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
769                   (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
770                 wrqu->mode = IW_MODE_ADHOC;
771         else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
772                 wrqu->mode = IW_MODE_MASTER;
773         else
774                 wrqu->mode = IW_MODE_AUTO;
775
776         return 0;
777 }
778
779 static int rtw_wx_set_pmkid(struct net_device *dev,
780                             struct iw_request_info *a,
781                             union iwreq_data *wrqu, char *extra)
782 {
783         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
784         u8   j, blInserted = false;
785         int  ret = false;
786         struct security_priv *psecuritypriv = &padapter->securitypriv;
787         struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
788         u8     strZeroMacAddress[ETH_ALEN] = {0x00};
789         u8     strIssueBssid[ETH_ALEN] = {0x00};
790
791         memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
792         if (pPMK->cmd == IW_PMKSA_ADD) {
793                 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
794                 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
795                         return ret;
796                 else
797                         ret = true;
798                 blInserted = false;
799
800                 /* overwrite PMKID */
801                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
802                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
803                                 /*  BSSID is matched, the same AP => rewrite with new PMKID. */
804                                 DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
805                                 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
806                                 psecuritypriv->PMKIDList[j].bUsed = true;
807                                 psecuritypriv->PMKIDIndex = j+1;
808                                 blInserted = true;
809                                 break;
810                         }
811                 }
812
813                 if (!blInserted) {
814                         /*  Find a new entry */
815                         DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
816                                 psecuritypriv->PMKIDIndex);
817
818                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
819                         memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
820
821                         psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
822                         psecuritypriv->PMKIDIndex++;
823                         if (psecuritypriv->PMKIDIndex == 16)
824                                 psecuritypriv->PMKIDIndex = 0;
825                 }
826         } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
827                 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
828                 ret = true;
829                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
830                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
831                                 /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
832                                 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
833                                 psecuritypriv->PMKIDList[j].bUsed = false;
834                                 break;
835                         }
836                }
837         } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
838                 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
839                 memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
840                 psecuritypriv->PMKIDIndex = 0;
841                 ret = true;
842         }
843         return ret;
844 }
845
846 static int rtw_wx_get_sens(struct net_device *dev,
847                              struct iw_request_info *info,
848                              union iwreq_data *wrqu, char *extra)
849 {
850         wrqu->sens.value = 0;
851         wrqu->sens.fixed = 0;   /* no auto select */
852         wrqu->sens.disabled = 1;
853         return 0;
854 }
855
856 static int rtw_wx_get_range(struct net_device *dev,
857                                 struct iw_request_info *info,
858                                 union iwreq_data *wrqu, char *extra)
859 {
860         struct iw_range *range = (struct iw_range *)extra;
861         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
862         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
863
864         u16 val;
865         int i;
866
867         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
868
869         wrqu->data.length = sizeof(*range);
870         memset(range, 0, sizeof(*range));
871
872         /* Let's try to keep this struct in the same order as in
873          * linux/include/wireless.h
874          */
875
876         /* TODO: See what values we can set, and remove the ones we can't
877          * set, or fill them with some default data.
878          */
879
880         /* ~5 Mb/s real (802.11b) */
881         range->throughput = 5 * 1000 * 1000;
882
883         /* signal level threshold range */
884
885         /* percent values between 0 and 100. */
886         range->max_qual.qual = 100;
887         range->max_qual.level = 100;
888         range->max_qual.noise = 100;
889         range->max_qual.updated = 7; /* Updated all three */
890
891         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
892         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
893         range->avg_qual.level = 178; /* -78 dBm */
894         range->avg_qual.noise = 0;
895         range->avg_qual.updated = 7; /* Updated all three */
896
897         range->num_bitrates = RATE_COUNT;
898
899         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
900                 range->bitrate[i] = rtw_rates[i];
901
902         range->min_frag = MIN_FRAG_THRESHOLD;
903         range->max_frag = MAX_FRAG_THRESHOLD;
904
905         range->pm_capa = 0;
906
907         range->we_version_compiled = WIRELESS_EXT;
908         range->we_version_source = 16;
909
910         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
911                 /*  Include only legal frequencies for some countries */
912                 if (pmlmeext->channel_set[i].ChannelNum != 0) {
913                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
914                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
915                         range->freq[val].e = 1;
916                         val++;
917                 }
918
919                 if (val == IW_MAX_FREQUENCIES)
920                         break;
921         }
922
923         range->num_channels = val;
924         range->num_frequency = val;
925
926 /*  The following code will proivde the security capability to network manager. */
927 /*  If the driver doesn't provide this capability to network manager, */
928 /*  the WPA/WPA2 routers can't be chosen in the network manager. */
929
930 /*
931 #define IW_SCAN_CAPA_NONE               0x00
932 #define IW_SCAN_CAPA_ESSID              0x01
933 #define IW_SCAN_CAPA_BSSID              0x02
934 #define IW_SCAN_CAPA_CHANNEL            0x04
935 #define IW_SCAN_CAPA_MODE               0x08
936 #define IW_SCAN_CAPA_RATE               0x10
937 #define IW_SCAN_CAPA_TYPE               0x20
938 #define IW_SCAN_CAPA_TIME               0x40
939 */
940
941         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
942                           IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
943
944         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
945                            IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
946                            IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
947         return 0;
948 }
949
950 /* set bssid flow */
951 /* s1. rtw_set_802_11_infrastructure_mode() */
952 /* s2. rtw_set_802_11_authentication_mode() */
953 /* s3. set_802_11_encryption_mode() */
954 /* s4. rtw_set_802_11_bssid() */
955 static int rtw_wx_set_wap(struct net_device *dev,
956                          struct iw_request_info *info,
957                          union iwreq_data *awrq,
958                          char *extra)
959 {
960         uint ret = 0;
961         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
962         struct sockaddr *temp = (struct sockaddr *)awrq;
963         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
964         struct list_head *phead;
965         u8 *dst_bssid, *src_bssid;
966         struct __queue *queue   = &(pmlmepriv->scanned_queue);
967         struct  wlan_network    *pnetwork = NULL;
968         enum ndis_802_11_auth_mode      authmode;
969
970         if (_FAIL == rtw_pwr_wakeup(padapter)) {
971                 ret = -1;
972                 goto exit;
973         }
974
975         if (!padapter->bup) {
976                 ret = -1;
977                 goto exit;
978         }
979
980         if (temp->sa_family != ARPHRD_ETHER) {
981                 ret = -EINVAL;
982                 goto exit;
983         }
984
985         authmode = padapter->securitypriv.ndisauthtype;
986         spin_lock_bh(&queue->lock);
987         phead = get_list_head(queue);
988         pmlmepriv->pscanned = phead->next;
989
990         while (phead != pmlmepriv->pscanned) {
991                 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
992
993                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
994
995                 dst_bssid = pnetwork->network.MacAddress;
996
997                 src_bssid = temp->sa_data;
998
999                 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1000                         if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1001                                 ret = -1;
1002                                 spin_unlock_bh(&queue->lock);
1003                                 goto exit;
1004                         }
1005
1006                                 break;
1007                 }
1008         }
1009         spin_unlock_bh(&queue->lock);
1010
1011         rtw_set_802_11_authentication_mode(padapter, authmode);
1012         /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1013         if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1014                 ret = -1;
1015                 goto exit;
1016         }
1017
1018 exit:
1019
1020         return ret;
1021 }
1022
1023 static int rtw_wx_get_wap(struct net_device *dev,
1024                             struct iw_request_info *info,
1025                             union iwreq_data *wrqu, char *extra)
1026 {
1027         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1028         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1029         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1030
1031         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1032
1033         eth_zero_addr(wrqu->ap_addr.sa_data);
1034
1035         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
1036
1037         if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1038             ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
1039             ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
1040                 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1041         else
1042                 eth_zero_addr(wrqu->ap_addr.sa_data);
1043         return 0;
1044 }
1045
1046 static int rtw_wx_set_mlme(struct net_device *dev,
1047                              struct iw_request_info *info,
1048                              union iwreq_data *wrqu, char *extra)
1049 {
1050         int ret = 0;
1051         u16 reason;
1052         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1053         struct iw_mlme *mlme = (struct iw_mlme *)extra;
1054
1055         if (mlme == NULL)
1056                 return -1;
1057
1058         DBG_88E("%s\n", __func__);
1059
1060         reason = mlme->reason_code;
1061
1062         DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1063
1064         switch (mlme->cmd) {
1065         case IW_MLME_DEAUTH:
1066                 if (!rtw_set_802_11_disassociate(padapter))
1067                         ret = -1;
1068                 break;
1069         case IW_MLME_DISASSOC:
1070                 if (!rtw_set_802_11_disassociate(padapter))
1071                         ret = -1;
1072                 break;
1073         default:
1074                 return -EOPNOTSUPP;
1075         }
1076         return ret;
1077 }
1078
1079 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1080                              union iwreq_data *wrqu, char *extra)
1081 {
1082         u8 _status = false;
1083         int ret = 0;
1084         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1085         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1086         struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1087         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
1088
1089         if (padapter->registrypriv.mp_mode == 1) {
1090                 if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
1091                         ret = -1;
1092                         goto exit;
1093                 }
1094         }
1095         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1096                 ret = -1;
1097                 goto exit;
1098         }
1099
1100         if (padapter->bDriverStopped) {
1101                 DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
1102                 ret = -1;
1103                 goto exit;
1104         }
1105
1106         if (!padapter->bup) {
1107                 ret = -1;
1108                 goto exit;
1109         }
1110
1111         if (!padapter->hw_init_completed) {
1112                 ret = -1;
1113                 goto exit;
1114         }
1115
1116         /*  When Busy Traffic, driver do not site survey. So driver return success. */
1117         /*  wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1118         /*  modify by thomas 2011-02-22. */
1119         if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1120                 indicate_wx_scan_complete_event(padapter);
1121                 goto exit;
1122         }
1123
1124         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1125                 indicate_wx_scan_complete_event(padapter);
1126                 goto exit;
1127         }
1128
1129 /*      For the DMP WiFi Display project, the driver won't to scan because */
1130 /*      the pmlmepriv->scan_interval is always equal to 3. */
1131 /*      So, the wpa_supplicant won't find out the WPS SoftAP. */
1132
1133         memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1134
1135         if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1136                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1137
1138                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1139                         int len = min_t(int, req->essid_len,
1140                                         IW_ESSID_MAX_SIZE);
1141
1142                         memcpy(ssid[0].Ssid, req->essid, len);
1143                         ssid[0].SsidLength = len;
1144
1145                         DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1146
1147                         spin_lock_bh(&pmlmepriv->lock);
1148
1149                         _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1150
1151                         spin_unlock_bh(&pmlmepriv->lock);
1152                 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
1153                         DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1154                 }
1155         } else {
1156                 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1157                     !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1158                         int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1159                         char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1160                         char section;
1161                         char sec_len;
1162                         int ssid_index = 0;
1163
1164                         while (len >= 1) {
1165                                 section = *(pos++);
1166                                 len -= 1;
1167
1168                                 switch (section) {
1169                                 case WEXT_CSCAN_SSID_SECTION:
1170                                         if (len < 1) {
1171                                                 len = 0;
1172                                                 break;
1173                                         }
1174                                         sec_len = *(pos++); len -= 1;
1175                                         if (sec_len > 0 && sec_len <= len) {
1176                                                 ssid[ssid_index].SsidLength = sec_len;
1177                                                 memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1178                                                 ssid_index++;
1179                                         }
1180                                         pos += sec_len;
1181                                         len -= sec_len;
1182                                         break;
1183                                 case WEXT_CSCAN_TYPE_SECTION:
1184                                 case WEXT_CSCAN_CHANNEL_SECTION:
1185                                         pos += 1;
1186                                         len -= 1;
1187                                         break;
1188                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
1189                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
1190                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1191                                         pos += 2;
1192                                         len -= 2;
1193                                         break;
1194                                 default:
1195                                         len = 0; /*  stop parsing */
1196                                 }
1197                         }
1198
1199                         /* it has still some scan parameter to parse, we only do this now... */
1200                         _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1201                 } else {
1202                         _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1203                 }
1204         }
1205
1206         if (!_status)
1207                 ret = -1;
1208
1209 exit:
1210
1211         return ret;
1212 }
1213
1214 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1215                              union iwreq_data *wrqu, char *extra)
1216 {
1217         struct list_head *plist, *phead;
1218         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1219         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1220         struct __queue *queue   = &(pmlmepriv->scanned_queue);
1221         struct  wlan_network    *pnetwork = NULL;
1222         char *ev = extra;
1223         char *stop = ev + wrqu->data.length;
1224         u32 ret = 0;
1225         u32 cnt = 0;
1226         u32 wait_for_surveydone;
1227         int wait_status;
1228         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1229         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1230
1231         if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
1232                 ret = -EINVAL;
1233                 goto exit;
1234         }
1235
1236         wait_for_surveydone = 100;
1237
1238         wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1239
1240         while (check_fwstate(pmlmepriv, wait_status)) {
1241                 msleep(30);
1242                 cnt++;
1243                 if (cnt > wait_for_surveydone)
1244                         break;
1245         }
1246
1247         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1248
1249         phead = get_list_head(queue);
1250         plist = phead->next;
1251
1252         while (phead != plist) {
1253                 if ((stop - ev) < SCAN_ITEM_SIZE) {
1254                         ret = -E2BIG;
1255                         break;
1256                 }
1257
1258                 pnetwork = container_of(plist, struct wlan_network, list);
1259
1260                 /* report network only if the current channel set contains the channel to which this network belongs */
1261                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1262                         ev = translate_scan(padapter, a, pnetwork, ev, stop);
1263
1264                 plist = plist->next;
1265         }
1266
1267         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1268
1269         wrqu->data.length = ev-extra;
1270         wrqu->data.flags = 0;
1271
1272 exit:
1273         return ret;
1274 }
1275
1276 /* set ssid flow */
1277 /* s1. rtw_set_802_11_infrastructure_mode() */
1278 /* s2. set_802_11_authenticaion_mode() */
1279 /* s3. set_802_11_encryption_mode() */
1280 /* s4. rtw_set_802_11_ssid() */
1281 static int rtw_wx_set_essid(struct net_device *dev,
1282                               struct iw_request_info *a,
1283                               union iwreq_data *wrqu, char *extra)
1284 {
1285         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1286         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1287         struct __queue *queue = &pmlmepriv->scanned_queue;
1288         struct list_head *phead;
1289         struct wlan_network *pnetwork = NULL;
1290         enum ndis_802_11_auth_mode authmode;
1291         struct ndis_802_11_ssid ndis_ssid;
1292         u8 *dst_ssid, *src_ssid;
1293
1294         uint ret = 0, len;
1295
1296
1297         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1298                  ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1299         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1300                 ret = -1;
1301                 goto exit;
1302         }
1303
1304         if (!padapter->bup) {
1305                 ret = -1;
1306                 goto exit;
1307         }
1308
1309         if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1310                 ret = -E2BIG;
1311                 goto exit;
1312         }
1313
1314         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1315                 ret = -1;
1316                 goto exit;
1317         }
1318
1319         authmode = padapter->securitypriv.ndisauthtype;
1320         DBG_88E("=>%s\n", __func__);
1321         if (wrqu->essid.flags && wrqu->essid.length) {
1322                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1323
1324                 if (wrqu->essid.length != 33)
1325                         DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1326
1327                 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1328                 ndis_ssid.SsidLength = len;
1329                 memcpy(ndis_ssid.Ssid, extra, len);
1330                 src_ssid = ndis_ssid.Ssid;
1331
1332                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1333                 spin_lock_bh(&queue->lock);
1334                phead = get_list_head(queue);
1335               pmlmepriv->pscanned = phead->next;
1336
1337                 while (phead != pmlmepriv->pscanned) {
1338                         pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1339
1340                         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1341
1342                         dst_ssid = pnetwork->network.Ssid.Ssid;
1343
1344                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1345                                  ("rtw_wx_set_essid: dst_ssid =%s\n",
1346                                   pnetwork->network.Ssid.Ssid));
1347
1348                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1349                             (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
1350                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1351                                          ("rtw_wx_set_essid: find match, set infra mode\n"));
1352
1353                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1354                                         if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1355                                                 continue;
1356                                 }
1357
1358                                 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1359                                         ret = -1;
1360                                         spin_unlock_bh(&queue->lock);
1361                                         goto exit;
1362                                 }
1363
1364                                 break;
1365                         }
1366                 }
1367                 spin_unlock_bh(&queue->lock);
1368                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1369                          ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1370                 rtw_set_802_11_authentication_mode(padapter, authmode);
1371                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1372                         ret = -1;
1373                         goto exit;
1374                 }
1375         }
1376
1377 exit:
1378
1379         DBG_88E("<=%s, ret %d\n", __func__, ret);
1380
1381
1382         return ret;
1383 }
1384
1385 static int rtw_wx_get_essid(struct net_device *dev,
1386                               struct iw_request_info *a,
1387                               union iwreq_data *wrqu, char *extra)
1388 {
1389         u32 len, ret = 0;
1390         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1391         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1392         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1393
1394         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1395
1396
1397         if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1398             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1399                 len = pcur_bss->Ssid.SsidLength;
1400
1401                 wrqu->essid.length = len;
1402
1403                 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1404
1405                 wrqu->essid.flags = 1;
1406         } else {
1407                 ret = -1;
1408                 goto exit;
1409         }
1410
1411 exit:
1412
1413
1414         return ret;
1415 }
1416
1417 static int rtw_wx_set_rate(struct net_device *dev,
1418                               struct iw_request_info *a,
1419                               union iwreq_data *wrqu, char *extra)
1420 {
1421         int i;
1422         u8 datarates[NumRates];
1423         u32     target_rate = wrqu->bitrate.value;
1424         u32     fixed = wrqu->bitrate.fixed;
1425         u32     ratevalue = 0;
1426          u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1427
1428
1429         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1430         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1431
1432         if (target_rate == -1) {
1433                 ratevalue = 11;
1434                 goto set_rate;
1435         }
1436         target_rate = target_rate/100000;
1437
1438         switch (target_rate) {
1439         case 10:
1440                 ratevalue = 0;
1441                 break;
1442         case 20:
1443                 ratevalue = 1;
1444                 break;
1445         case 55:
1446                 ratevalue = 2;
1447                 break;
1448         case 60:
1449                 ratevalue = 3;
1450                 break;
1451         case 90:
1452                 ratevalue = 4;
1453                 break;
1454         case 110:
1455                 ratevalue = 5;
1456                 break;
1457         case 120:
1458                 ratevalue = 6;
1459                 break;
1460         case 180:
1461                 ratevalue = 7;
1462                 break;
1463         case 240:
1464                 ratevalue = 8;
1465                 break;
1466         case 360:
1467                 ratevalue = 9;
1468                 break;
1469         case 480:
1470                 ratevalue = 10;
1471                 break;
1472         case 540:
1473                 ratevalue = 11;
1474                 break;
1475         default:
1476                 ratevalue = 11;
1477                 break;
1478         }
1479
1480 set_rate:
1481
1482         for (i = 0; i < NumRates; i++) {
1483                 if (ratevalue == mpdatarate[i]) {
1484                         datarates[i] = mpdatarate[i];
1485                         if (fixed == 0)
1486                                 break;
1487                 } else {
1488                         datarates[i] = 0xff;
1489                 }
1490
1491                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1492         }
1493
1494         return 0;
1495 }
1496
1497 static int rtw_wx_get_rate(struct net_device *dev,
1498                              struct iw_request_info *info,
1499                              union iwreq_data *wrqu, char *extra)
1500 {
1501         u16 max_rate = 0;
1502
1503         max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1504
1505         if (max_rate == 0)
1506                 return -EPERM;
1507
1508         wrqu->bitrate.fixed = 0;        /* no auto select */
1509         wrqu->bitrate.value = max_rate * 100000;
1510
1511         return 0;
1512 }
1513
1514 static int rtw_wx_set_rts(struct net_device *dev,
1515                              struct iw_request_info *info,
1516                              union iwreq_data *wrqu, char *extra)
1517 {
1518         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1519
1520
1521         if (wrqu->rts.disabled) {
1522                 padapter->registrypriv.rts_thresh = 2347;
1523         } else {
1524                 if (wrqu->rts.value < 0 ||
1525                     wrqu->rts.value > 2347)
1526                         return -EINVAL;
1527
1528                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1529         }
1530
1531         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1532
1533
1534         return 0;
1535 }
1536
1537 static int rtw_wx_get_rts(struct net_device *dev,
1538                              struct iw_request_info *info,
1539                              union iwreq_data *wrqu, char *extra)
1540 {
1541         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1542
1543
1544         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1545
1546         wrqu->rts.value = padapter->registrypriv.rts_thresh;
1547         wrqu->rts.fixed = 0;    /* no auto select */
1548         /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1549
1550
1551         return 0;
1552 }
1553
1554 static int rtw_wx_set_frag(struct net_device *dev,
1555                              struct iw_request_info *info,
1556                              union iwreq_data *wrqu, char *extra)
1557 {
1558         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1559
1560
1561         if (wrqu->frag.disabled) {
1562                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1563         } else {
1564                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1565                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
1566                         return -EINVAL;
1567
1568                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1569         }
1570
1571         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1572
1573
1574         return 0;
1575 }
1576
1577 static int rtw_wx_get_frag(struct net_device *dev,
1578                              struct iw_request_info *info,
1579                              union iwreq_data *wrqu, char *extra)
1580 {
1581         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1582
1583
1584         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1585
1586         wrqu->frag.value = padapter->xmitpriv.frag_len;
1587         wrqu->frag.fixed = 0;   /* no auto select */
1588
1589
1590         return 0;
1591 }
1592
1593 static int rtw_wx_get_retry(struct net_device *dev,
1594                              struct iw_request_info *info,
1595                              union iwreq_data *wrqu, char *extra)
1596 {
1597         wrqu->retry.value = 7;
1598         wrqu->retry.fixed = 0;  /* no auto select */
1599         wrqu->retry.disabled = 1;
1600
1601         return 0;
1602 }
1603
1604 static int rtw_wx_set_enc(struct net_device *dev,
1605                             struct iw_request_info *info,
1606                             union iwreq_data *wrqu, char *keybuf)
1607 {
1608         u32 key, ret = 0;
1609         u32 keyindex_provided;
1610         struct ndis_802_11_wep   wep;
1611         enum ndis_802_11_auth_mode authmode;
1612
1613         struct iw_point *erq = &(wrqu->encoding);
1614         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1615         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1616         DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1617
1618         memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1619
1620         key = erq->flags & IW_ENCODE_INDEX;
1621
1622
1623         if (erq->flags & IW_ENCODE_DISABLED) {
1624                 DBG_88E("EncryptionDisabled\n");
1625                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1626                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1627                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1628                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1629                 authmode = Ndis802_11AuthModeOpen;
1630                 padapter->securitypriv.ndisauthtype = authmode;
1631
1632                 goto exit;
1633         }
1634
1635         if (key) {
1636                 if (key > WEP_KEYS)
1637                         return -EINVAL;
1638                 key--;
1639                 keyindex_provided = 1;
1640         } else {
1641                 keyindex_provided = 0;
1642                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1643                 DBG_88E("rtw_wx_set_enc, key =%d\n", key);
1644         }
1645
1646         /* set authentication mode */
1647         if (erq->flags & IW_ENCODE_OPEN) {
1648                 DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1649                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1650                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1651                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1652                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1653                 authmode = Ndis802_11AuthModeOpen;
1654                 padapter->securitypriv.ndisauthtype = authmode;
1655         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1656                 DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1657                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1658                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1659                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1660                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1661                 authmode = Ndis802_11AuthModeShared;
1662                 padapter->securitypriv.ndisauthtype = authmode;
1663         } else {
1664                 DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1665
1666                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1667                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1668                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1669                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1670                 authmode = Ndis802_11AuthModeOpen;
1671                 padapter->securitypriv.ndisauthtype = authmode;
1672         }
1673
1674         wep.KeyIndex = key;
1675         if (erq->length > 0) {
1676                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1677
1678                 wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
1679         } else {
1680                 wep.KeyLength = 0;
1681
1682                 if (keyindex_provided == 1) {
1683                         /*  set key_id only, no given KeyMaterial(erq->length == 0). */
1684                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
1685
1686                         DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1687
1688                         switch (padapter->securitypriv.dot11DefKeylen[key]) {
1689                         case 5:
1690                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1691                                 break;
1692                         case 13:
1693                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1694                                 break;
1695                         default:
1696                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1697                                 break;
1698                         }
1699
1700                         goto exit;
1701                 }
1702         }
1703
1704         wep.KeyIndex |= 0x80000000;
1705
1706         memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1707
1708         if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1709                 if (rf_on == pwrpriv->rf_pwrstate)
1710                         ret = -EOPNOTSUPP;
1711                 goto exit;
1712         }
1713
1714 exit:
1715
1716
1717         return ret;
1718 }
1719
1720 static int rtw_wx_get_enc(struct net_device *dev,
1721                             struct iw_request_info *info,
1722                             union iwreq_data *wrqu, char *keybuf)
1723 {
1724         uint key, ret = 0;
1725         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1726         struct iw_point *erq = &(wrqu->encoding);
1727         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1728
1729
1730         if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1731                 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1732                         erq->length = 0;
1733                         erq->flags |= IW_ENCODE_DISABLED;
1734                         return 0;
1735                 }
1736         }
1737
1738         key = erq->flags & IW_ENCODE_INDEX;
1739
1740         if (key) {
1741                 if (key > WEP_KEYS)
1742                         return -EINVAL;
1743                 key--;
1744         } else {
1745                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1746         }
1747
1748         erq->flags = key + 1;
1749
1750         switch (padapter->securitypriv.ndisencryptstatus) {
1751         case Ndis802_11EncryptionNotSupported:
1752         case Ndis802_11EncryptionDisabled:
1753                 erq->length = 0;
1754                 erq->flags |= IW_ENCODE_DISABLED;
1755                 break;
1756         case Ndis802_11Encryption1Enabled:
1757                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1758                 if (erq->length) {
1759                         memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1760
1761                         erq->flags |= IW_ENCODE_ENABLED;
1762
1763                         if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1764                                 erq->flags |= IW_ENCODE_OPEN;
1765                         else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1766                                 erq->flags |= IW_ENCODE_RESTRICTED;
1767                 } else {
1768                         erq->length = 0;
1769                         erq->flags |= IW_ENCODE_DISABLED;
1770                 }
1771                 break;
1772         case Ndis802_11Encryption2Enabled:
1773         case Ndis802_11Encryption3Enabled:
1774                 erq->length = 16;
1775                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1776                 break;
1777         default:
1778                 erq->length = 0;
1779                 erq->flags |= IW_ENCODE_DISABLED;
1780                 break;
1781         }
1782
1783         return ret;
1784 }
1785
1786 static int rtw_wx_get_power(struct net_device *dev,
1787                              struct iw_request_info *info,
1788                              union iwreq_data *wrqu, char *extra)
1789 {
1790         wrqu->power.value = 0;
1791         wrqu->power.fixed = 0;  /* no auto select */
1792         wrqu->power.disabled = 1;
1793
1794         return 0;
1795 }
1796
1797 static int rtw_wx_set_gen_ie(struct net_device *dev,
1798                              struct iw_request_info *info,
1799                              union iwreq_data *wrqu, char *extra)
1800 {
1801         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1802
1803         return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1804 }
1805
1806 static int rtw_wx_set_auth(struct net_device *dev,
1807                              struct iw_request_info *info,
1808                              union iwreq_data *wrqu, char *extra)
1809 {
1810         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1811         struct iw_param *param = (struct iw_param *)&(wrqu->param);
1812         int ret = 0;
1813
1814         switch (param->flags & IW_AUTH_INDEX) {
1815         case IW_AUTH_WPA_VERSION:
1816                 break;
1817         case IW_AUTH_CIPHER_PAIRWISE:
1818
1819                 break;
1820         case IW_AUTH_CIPHER_GROUP:
1821
1822                 break;
1823         case IW_AUTH_KEY_MGMT:
1824                 /*
1825                  *  ??? does not use these parameters
1826                  */
1827                 break;
1828         case IW_AUTH_TKIP_COUNTERMEASURES:
1829                 if (param->value) {
1830                         /*  wpa_supplicant is enabling the tkip countermeasure. */
1831                         padapter->securitypriv.btkip_countermeasure = true;
1832                 } else {
1833                         /*  wpa_supplicant is disabling the tkip countermeasure. */
1834                         padapter->securitypriv.btkip_countermeasure = false;
1835                 }
1836                 break;
1837         case IW_AUTH_DROP_UNENCRYPTED:
1838                 /* HACK:
1839                  *
1840                  * wpa_supplicant calls set_wpa_enabled when the driver
1841                  * is loaded and unloaded, regardless of if WPA is being
1842                  * used.  No other calls are made which can be used to
1843                  * determine if encryption will be used or not prior to
1844                  * association being expected.  If encryption is not being
1845                  * used, drop_unencrypted is set to false, else true -- we
1846                  * can use this to determine if the CAP_PRIVACY_ON bit should
1847                  * be set.
1848                  */
1849
1850                 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
1851                         break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
1852                                         /*  then it needn't reset it; */
1853
1854                 if (param->value) {
1855                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1856                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1857                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1858                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1859                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1860                 }
1861
1862                 break;
1863         case IW_AUTH_80211_AUTH_ALG:
1864                 /*
1865                  *  It's the starting point of a link layer connection using wpa_supplicant
1866                 */
1867                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1868                         LeaveAllPowerSaveMode(padapter);
1869                         rtw_disassoc_cmd(padapter, 500, false);
1870                         DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
1871                         rtw_indicate_disconnect(padapter);
1872                         rtw_free_assoc_resources(padapter, 1);
1873                 }
1874                 ret = wpa_set_auth_algs(dev, (u32)param->value);
1875                 break;
1876         case IW_AUTH_WPA_ENABLED:
1877                 break;
1878         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1879                 break;
1880         case IW_AUTH_PRIVACY_INVOKED:
1881                 break;
1882         default:
1883                 return -EOPNOTSUPP;
1884         }
1885
1886         return ret;
1887 }
1888
1889 static int rtw_wx_set_enc_ext(struct net_device *dev,
1890                              struct iw_request_info *info,
1891                              union iwreq_data *wrqu, char *extra)
1892 {
1893         char *alg_name;
1894         u32 param_len;
1895         struct ieee_param *param = NULL;
1896         struct iw_point *pencoding = &wrqu->encoding;
1897         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1898         int ret = 0;
1899
1900         param_len = sizeof(struct ieee_param) + pext->key_len;
1901         param = (struct ieee_param *)rtw_malloc(param_len);
1902         if (param == NULL)
1903                 return -1;
1904
1905         memset(param, 0, param_len);
1906
1907         param->cmd = IEEE_CMD_SET_ENCRYPTION;
1908         memset(param->sta_addr, 0xff, ETH_ALEN);
1909
1910         switch (pext->alg) {
1911         case IW_ENCODE_ALG_NONE:
1912                 /* todo: remove key */
1913                 /* remove = 1; */
1914                 alg_name = "none";
1915                 break;
1916         case IW_ENCODE_ALG_WEP:
1917                 alg_name = "WEP";
1918                 break;
1919         case IW_ENCODE_ALG_TKIP:
1920                 alg_name = "TKIP";
1921                 break;
1922         case IW_ENCODE_ALG_CCMP:
1923                 alg_name = "CCMP";
1924                 break;
1925         default:
1926                 ret = -1;
1927                 goto exit;
1928         }
1929
1930         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1931
1932         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1933                 param->u.crypt.set_tx = 1;
1934
1935         /* cliW: WEP does not have group key
1936          * just not checking GROUP key setting
1937          */
1938         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
1939             (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1940                 param->u.crypt.set_tx = 0;
1941
1942         param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
1943
1944         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1945                 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1946
1947         if (pext->key_len) {
1948                 param->u.crypt.key_len = pext->key_len;
1949                 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
1950         }
1951
1952         ret =  wpa_set_encryption(dev, param, param_len);
1953
1954 exit:
1955         kfree(param);
1956         return ret;
1957 }
1958
1959 static int rtw_wx_get_nick(struct net_device *dev,
1960                            struct iw_request_info *info,
1961                            union iwreq_data *wrqu, char *extra)
1962 {
1963         if (extra) {
1964                 wrqu->data.length = 14;
1965                 wrqu->data.flags = 1;
1966                 memcpy(extra, "<WIFI@REALTEK>", 14);
1967         }
1968
1969         /* dump debug info here */
1970         return 0;
1971 }
1972
1973 static int dummy(struct net_device *dev, struct iw_request_info *a,
1974                  union iwreq_data *wrqu, char *b)
1975 {
1976         return -1;
1977 }
1978
1979 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
1980 {
1981         uint ret = 0;
1982         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1983
1984         switch (name) {
1985         case IEEE_PARAM_WPA_ENABLED:
1986                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
1987                 switch ((value)&0xff) {
1988                 case 1: /* WPA */
1989                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
1990                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1991                         break;
1992                 case 2: /* WPA2 */
1993                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
1994                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1995                         break;
1996                 }
1997                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1998                          ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
1999                 break;
2000         case IEEE_PARAM_TKIP_COUNTERMEASURES:
2001                 break;
2002         case IEEE_PARAM_DROP_UNENCRYPTED: {
2003                 /* HACK:
2004                  *
2005                  * wpa_supplicant calls set_wpa_enabled when the driver
2006                  * is loaded and unloaded, regardless of if WPA is being
2007                  * used.  No other calls are made which can be used to
2008                  * determine if encryption will be used or not prior to
2009                  * association being expected.  If encryption is not being
2010                  * used, drop_unencrypted is set to false, else true -- we
2011                  * can use this to determine if the CAP_PRIVACY_ON bit should
2012                  * be set.
2013                  */
2014
2015                 break;
2016         }
2017         case IEEE_PARAM_PRIVACY_INVOKED:
2018                 break;
2019
2020         case IEEE_PARAM_AUTH_ALGS:
2021                 ret = wpa_set_auth_algs(dev, value);
2022                 break;
2023         case IEEE_PARAM_IEEE_802_1X:
2024                 break;
2025         case IEEE_PARAM_WPAX_SELECT:
2026                 break;
2027         default:
2028                 ret = -EOPNOTSUPP;
2029                 break;
2030         }
2031         return ret;
2032 }
2033
2034 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2035 {
2036         int ret = 0;
2037         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2038
2039         switch (command) {
2040         case IEEE_MLME_STA_DEAUTH:
2041                 if (!rtw_set_802_11_disassociate(padapter))
2042                         ret = -1;
2043                 break;
2044         case IEEE_MLME_STA_DISASSOC:
2045                 if (!rtw_set_802_11_disassociate(padapter))
2046                         ret = -1;
2047                 break;
2048         default:
2049                 ret = -EOPNOTSUPP;
2050                 break;
2051         }
2052
2053         return ret;
2054 }
2055
2056 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2057 {
2058         struct ieee_param *param;
2059         uint ret = 0;
2060
2061         if (p->length < sizeof(struct ieee_param) || !p->pointer) {
2062                 ret = -EINVAL;
2063                 goto out;
2064         }
2065
2066         param = (struct ieee_param *)rtw_malloc(p->length);
2067         if (param == NULL) {
2068                 ret = -ENOMEM;
2069                 goto out;
2070         }
2071
2072         if (copy_from_user(param, p->pointer, p->length)) {
2073                 kfree(param);
2074                 ret = -EFAULT;
2075                 goto out;
2076         }
2077
2078         switch (param->cmd) {
2079         case IEEE_CMD_SET_WPA_PARAM:
2080                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
2081                 break;
2082
2083         case IEEE_CMD_SET_WPA_IE:
2084                 ret =  rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
2085                                       (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
2086                 break;
2087
2088         case IEEE_CMD_SET_ENCRYPTION:
2089                 ret = wpa_set_encryption(dev, param, p->length);
2090                 break;
2091
2092         case IEEE_CMD_MLME:
2093                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
2094                 break;
2095
2096         default:
2097                 DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
2098                 ret = -EOPNOTSUPP;
2099                 break;
2100         }
2101
2102         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2103                 ret = -EFAULT;
2104
2105         kfree(param);
2106
2107 out:
2108
2109         return ret;
2110 }
2111
2112 #ifdef CONFIG_88EU_AP_MODE
2113 static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
2114 {
2115         struct cmd_obj *ph2c;
2116         struct set_stakey_parm  *psetstakey_para;
2117         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2118         u8 res = _SUCCESS;
2119
2120         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
2121         if (ph2c == NULL) {
2122                 res = _FAIL;
2123                 goto exit;
2124         }
2125
2126         psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
2127         if (psetstakey_para == NULL) {
2128                 kfree(ph2c);
2129                 res = _FAIL;
2130                 goto exit;
2131         }
2132
2133         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
2134
2135         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
2136
2137         memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
2138
2139         memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
2140
2141         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2142
2143 exit:
2144
2145         return res;
2146 }
2147
2148 static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
2149 {
2150         u8 keylen;
2151         struct cmd_obj *pcmd;
2152         struct setkey_parm *psetkeyparm;
2153         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
2154         int res = _SUCCESS;
2155
2156         DBG_88E("%s\n", __func__);
2157
2158         pcmd = kzalloc(sizeof(struct    cmd_obj), GFP_KERNEL);
2159         if (pcmd == NULL) {
2160                 res = _FAIL;
2161                 goto exit;
2162         }
2163         psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
2164         if (psetkeyparm == NULL) {
2165                 kfree(pcmd);
2166                 res = _FAIL;
2167                 goto exit;
2168         }
2169
2170         memset(psetkeyparm, 0, sizeof(struct setkey_parm));
2171
2172         psetkeyparm->keyid = (u8)keyid;
2173
2174         psetkeyparm->algorithm = alg;
2175
2176         psetkeyparm->set_tx = 1;
2177
2178         switch (alg) {
2179         case _WEP40_:
2180                 keylen = 5;
2181                 break;
2182         case _WEP104_:
2183                 keylen = 13;
2184                 break;
2185         case _TKIP_:
2186         case _TKIP_WTMIC_:
2187         case _AES_:
2188         default:
2189                 keylen = 16;
2190         }
2191
2192         memcpy(&(psetkeyparm->key[0]), key, keylen);
2193
2194         pcmd->cmdcode = _SetKey_CMD_;
2195         pcmd->parmbuf = (u8 *)psetkeyparm;
2196         pcmd->cmdsz =  (sizeof(struct setkey_parm));
2197         pcmd->rsp = NULL;
2198         pcmd->rspsz = 0;
2199
2200         INIT_LIST_HEAD(&pcmd->list);
2201
2202         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2203
2204 exit:
2205
2206         return res;
2207 }
2208
2209 static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
2210 {
2211         u8 alg;
2212
2213         switch (keylen) {
2214         case 5:
2215                 alg = _WEP40_;
2216                 break;
2217         case 13:
2218                 alg = _WEP104_;
2219                 break;
2220         default:
2221                 alg = _NO_PRIVACY_;
2222         }
2223
2224         return set_group_key(padapter, key, alg, keyid);
2225 }
2226
2227 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
2228 {
2229         int ret = 0;
2230         u32 wep_key_idx, wep_key_len, wep_total_len;
2231         struct ndis_802_11_wep   *pwep = NULL;
2232         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
2233         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2234         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
2235         struct security_priv *psecuritypriv = &(padapter->securitypriv);
2236         struct sta_priv *pstapriv = &padapter->stapriv;
2237
2238         DBG_88E("%s\n", __func__);
2239         param->u.crypt.err = 0;
2240         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2241         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
2242                 ret =  -EINVAL;
2243                 goto exit;
2244         }
2245         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2246             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2247             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
2248                 if (param->u.crypt.idx >= WEP_KEYS) {
2249                         ret = -EINVAL;
2250                         goto exit;
2251                 }
2252         } else {
2253                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2254                 if (!psta) {
2255                         DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
2256                         goto exit;
2257                 }
2258         }
2259
2260         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
2261                 /* todo:clear default encryption keys */
2262
2263                 DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
2264                 goto exit;
2265         }
2266         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
2267                 DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
2268                 wep_key_idx = param->u.crypt.idx;
2269                 wep_key_len = param->u.crypt.key_len;
2270                 DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
2271                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
2272                         ret = -EINVAL;
2273                         goto exit;
2274                 }
2275
2276                 if (wep_key_len > 0) {
2277                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
2278                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
2279                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
2280                         if (pwep == NULL) {
2281                                 DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
2282                                 goto exit;
2283                         }
2284
2285                         memset(pwep, 0, wep_total_len);
2286
2287                         pwep->KeyLength = wep_key_len;
2288                         pwep->Length = wep_total_len;
2289                 }
2290
2291                 pwep->KeyIndex = wep_key_idx;
2292
2293                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
2294
2295                 if (param->u.crypt.set_tx) {
2296                         DBG_88E("wep, set_tx = 1\n");
2297
2298                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
2299                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
2300                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2301
2302                         if (pwep->KeyLength == 13) {
2303                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
2304                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2305                         }
2306
2307                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
2308
2309                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
2310
2311                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2312
2313                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2314                 } else {
2315                         DBG_88E("wep, set_tx = 0\n");
2316
2317                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
2318                         /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
2319
2320                       memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
2321
2322                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2323
2324                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2325                 }
2326
2327                 goto exit;
2328         }
2329
2330         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
2331                 if (param->u.crypt.set_tx == 1) {
2332                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2333                                 DBG_88E("%s, set group_key, WEP\n", __func__);
2334
2335                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2336                                             param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2337
2338                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2339                                 if (param->u.crypt.key_len == 13)
2340                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2341                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2342                                 DBG_88E("%s, set group_key, TKIP\n", __func__);
2343                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2344                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2345                                             param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2346                                 /* set mic key */
2347                                 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
2348                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
2349
2350                                 psecuritypriv->busetkipkey = true;
2351                         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2352                                 DBG_88E("%s, set group_key, CCMP\n", __func__);
2353                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
2354                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2355                                             param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2356                         } else {
2357                                 DBG_88E("%s, set group_key, none\n", __func__);
2358                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2359                         }
2360                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2361                         psecuritypriv->binstallGrpkey = true;
2362                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2363                         set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2364                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2365                         if (pbcmc_sta) {
2366                                 pbcmc_sta->ieee8021x_blocked = false;
2367                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2368                         }
2369                 }
2370                 goto exit;
2371         }
2372
2373         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
2374                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2375                         if (param->u.crypt.set_tx == 1) {
2376                                 memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2377
2378                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2379                                         DBG_88E("%s, set pairwise key, WEP\n", __func__);
2380
2381                                         psta->dot118021XPrivacy = _WEP40_;
2382                                         if (param->u.crypt.key_len == 13)
2383                                                 psta->dot118021XPrivacy = _WEP104_;
2384                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2385                                         DBG_88E("%s, set pairwise key, TKIP\n", __func__);
2386
2387                                         psta->dot118021XPrivacy = _TKIP_;
2388
2389                                         /* set mic key */
2390                                         memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
2391                                         memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
2392
2393                                         psecuritypriv->busetkipkey = true;
2394                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2395                                         DBG_88E("%s, set pairwise key, CCMP\n", __func__);
2396
2397                                         psta->dot118021XPrivacy = _AES_;
2398                                 } else {
2399                                         DBG_88E("%s, set pairwise key, none\n", __func__);
2400
2401                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
2402                                 }
2403
2404                                 set_pairwise_key(padapter, psta);
2405
2406                                 psta->ieee8021x_blocked = false;
2407                         } else { /* group key??? */
2408                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2409                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2410                                                     param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2411                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2412                                         if (param->u.crypt.key_len == 13)
2413                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2414                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2415                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2416
2417                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2418                                                     param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2419
2420                                         /* set mic key */
2421                                         memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
2422                                         memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
2423
2424                                         psecuritypriv->busetkipkey = true;
2425                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2426                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
2427
2428                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2429                                                     param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2430                                 } else {
2431                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2432                                 }
2433
2434                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2435
2436                                 psecuritypriv->binstallGrpkey = true;
2437
2438                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2439
2440                                 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2441
2442                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2443                                 if (pbcmc_sta) {
2444                                         pbcmc_sta->ieee8021x_blocked = false;
2445                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2446                                 }
2447                         }
2448                 }
2449         }
2450
2451 exit:
2452
2453         kfree(pwep);
2454
2455         return ret;
2456 }
2457
2458 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
2459 {
2460         int ret = 0;
2461         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2462         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2463         struct sta_priv *pstapriv = &padapter->stapriv;
2464         unsigned char *pbuf = param->u.bcn_ie.buf;
2465
2466         DBG_88E("%s, len =%d\n", __func__, len);
2467
2468         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2469                 return -EINVAL;
2470
2471         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
2472
2473         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
2474                 pstapriv->max_num_sta = NUM_STA;
2475
2476         if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
2477                 ret = 0;
2478         else
2479                 ret = -EINVAL;
2480
2481         return ret;
2482 }
2483
2484 static int rtw_hostapd_sta_flush(struct net_device *dev)
2485 {
2486         int ret = 0;
2487         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2488
2489         DBG_88E("%s\n", __func__);
2490
2491         flush_all_cam_entry(padapter);  /* clear CAM */
2492
2493         ret = rtw_sta_flush(padapter);
2494
2495         return ret;
2496 }
2497
2498 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
2499 {
2500         int ret = 0;
2501         struct sta_info *psta = NULL;
2502         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2503         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2504         struct sta_priv *pstapriv = &padapter->stapriv;
2505
2506         DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
2507
2508         if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
2509                 return -EINVAL;
2510
2511         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2512             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2513             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2514                 return -EINVAL;
2515
2516         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2517         if (psta) {
2518                 int flags = param->u.add_sta.flags;
2519
2520                 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
2521
2522                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
2523
2524                 /* check wmm cap. */
2525                 if (WLAN_STA_WME&flags)
2526                         psta->qos_option = 1;
2527                 else
2528                         psta->qos_option = 0;
2529
2530                 if (pmlmepriv->qospriv.qos_option == 0)
2531                         psta->qos_option = 0;
2532
2533                 /* chec 802.11n ht cap. */
2534                 if (WLAN_STA_HT&flags) {
2535                         psta->htpriv.ht_option = true;
2536                         psta->qos_option = 1;
2537                         memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
2538                 } else {
2539                         psta->htpriv.ht_option = false;
2540                 }
2541
2542                 if (pmlmepriv->htpriv.ht_option == false)
2543                         psta->htpriv.ht_option = false;
2544
2545                 update_sta_info_apmode(padapter, psta);
2546         } else {
2547                 ret = -ENOMEM;
2548         }
2549
2550         return ret;
2551 }
2552
2553 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
2554 {
2555         int ret = 0;
2556         struct sta_info *psta = NULL;
2557         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2558         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2559         struct sta_priv *pstapriv = &padapter->stapriv;
2560         int updated = 0;
2561
2562         DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
2563
2564         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2565                 return -EINVAL;
2566
2567         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2568             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2569             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2570                 return -EINVAL;
2571
2572         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2573         if (psta) {
2574                 spin_lock_bh(&pstapriv->asoc_list_lock);
2575                 if (!list_empty(&psta->asoc_list)) {
2576                         list_del_init(&psta->asoc_list);
2577                         pstapriv->asoc_list_cnt--;
2578                         updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
2579                 }
2580                 spin_unlock_bh(&pstapriv->asoc_list_lock);
2581                 associated_clients_update(padapter, updated);
2582                 psta = NULL;
2583         } else {
2584                 DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
2585         }
2586
2587         return ret;
2588 }
2589
2590 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
2591 {
2592         int ret = 0;
2593         struct sta_info *psta = NULL;
2594         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2595         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2596         struct sta_priv *pstapriv = &padapter->stapriv;
2597         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
2598         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
2599
2600         DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
2601
2602         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2603                 return -EINVAL;
2604
2605         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
2606             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
2607             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
2608                 return -EINVAL;
2609
2610         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
2611         if (psta) {
2612                 psta_data->aid = (u16)psta->aid;
2613                 psta_data->capability = psta->capability;
2614                 psta_data->flags = psta->flags;
2615
2616 /*
2617                 nonerp_set : BIT(0)
2618                 no_short_slot_time_set : BIT(1)
2619                 no_short_preamble_set : BIT(2)
2620                 no_ht_gf_set : BIT(3)
2621                 no_ht_set : BIT(4)
2622                 ht_20mhz_set : BIT(5)
2623 */
2624
2625                 psta_data->sta_set = ((psta->nonerp_set) |
2626                                       (psta->no_short_slot_time_set << 1) |
2627                                       (psta->no_short_preamble_set << 2) |
2628                                       (psta->no_ht_gf_set << 3) |
2629                                       (psta->no_ht_set << 4) |
2630                                       (psta->ht_20mhz_set << 5));
2631                 psta_data->tx_supp_rates_len =  psta->bssratelen;
2632                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
2633                 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
2634                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
2635                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
2636                 psta_data->rx_drops = psta->sta_stats.rx_drops;
2637                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
2638                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
2639                 psta_data->tx_drops = psta->sta_stats.tx_drops;
2640         } else {
2641                 ret = -1;
2642         }
2643
2644         return ret;
2645 }
2646
2647 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
2648 {
2649         int ret = 0;
2650         struct sta_info *psta = NULL;
2651         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2652         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2653         struct sta_priv *pstapriv = &padapter->stapriv;
2654
2655         DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
2656
2657         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2658                 return -EINVAL;
2659
2660         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2661             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2662             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2663                 return -EINVAL;
2664
2665         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2666         if (psta) {
2667                 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
2668                         int wpa_ie_len;
2669                         int copy_len;
2670
2671                         wpa_ie_len = psta->wpa_ie[1];
2672                         copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2);
2673                         param->u.wpa_ie.len = copy_len;
2674                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
2675                 } else {
2676                         DBG_88E("sta's wpa_ie is NONE\n");
2677                 }
2678         } else {
2679                 ret = -1;
2680         }
2681
2682         return ret;
2683 }
2684
2685 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
2686 {
2687         int ret = 0;
2688         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2689         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2690         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2691         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2692         int ie_len;
2693
2694         DBG_88E("%s, len =%d\n", __func__, len);
2695
2696         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2697                 return -EINVAL;
2698
2699         ie_len = len-12-2;/*  12 = param header, 2:no packed */
2700
2701         kfree(pmlmepriv->wps_beacon_ie);
2702         pmlmepriv->wps_beacon_ie = NULL;
2703
2704         if (ie_len > 0) {
2705                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
2706                 pmlmepriv->wps_beacon_ie_len = ie_len;
2707                 if (pmlmepriv->wps_beacon_ie == NULL) {
2708                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2709                         return -EINVAL;
2710                 }
2711
2712                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
2713
2714                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
2715
2716                 pmlmeext->bstart_bss = true;
2717         }
2718
2719         return ret;
2720 }
2721
2722 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
2723 {
2724         int ret = 0;
2725         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2726         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2727         int ie_len;
2728
2729         DBG_88E("%s, len =%d\n", __func__, len);
2730
2731         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2732                 return -EINVAL;
2733
2734         ie_len = len-12-2;/*  12 = param header, 2:no packed */
2735
2736         kfree(pmlmepriv->wps_probe_resp_ie);
2737         pmlmepriv->wps_probe_resp_ie = NULL;
2738
2739         if (ie_len > 0) {
2740                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
2741                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
2742                 if (pmlmepriv->wps_probe_resp_ie == NULL) {
2743                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2744                         return -EINVAL;
2745                 }
2746                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
2747         }
2748
2749         return ret;
2750 }
2751
2752 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
2753 {
2754         int ret = 0;
2755         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2756         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2757         int ie_len;
2758
2759         DBG_88E("%s, len =%d\n", __func__, len);
2760
2761         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2762                 return -EINVAL;
2763
2764         ie_len = len-12-2;/*  12 = param header, 2:no packed */
2765
2766         kfree(pmlmepriv->wps_assoc_resp_ie);
2767         pmlmepriv->wps_assoc_resp_ie = NULL;
2768
2769         if (ie_len > 0) {
2770                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
2771                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
2772                 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
2773                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2774                         return -EINVAL;
2775                 }
2776
2777                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
2778         }
2779
2780         return ret;
2781 }
2782
2783 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
2784 {
2785         int ret = 0;
2786         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2787         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2788         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2789         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2790
2791         u8 value;
2792
2793         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2794                 return -EINVAL;
2795
2796         if (param->u.wpa_param.name != 0) /* dummy test... */
2797                 DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
2798         value = param->u.wpa_param.value;
2799
2800         /* use the same definition of hostapd's ignore_broadcast_ssid */
2801         if (value != 1 && value != 2)
2802                 value = 0;
2803         DBG_88E("%s value(%u)\n", __func__, value);
2804         pmlmeinfo->hidden_ssid_mode = value;
2805         return ret;
2806 }
2807
2808 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
2809 {
2810         int ret = 0;
2811         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2812         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2813
2814         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2815                 return -EINVAL;
2816
2817         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2818             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2819             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2820                 return -EINVAL;
2821         ret = rtw_acl_remove_sta(padapter, param->sta_addr);
2822         return ret;
2823 }
2824
2825 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
2826 {
2827         int ret = 0;
2828         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2829         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2830
2831         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2832                 return -EINVAL;
2833
2834         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2835             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2836             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2837                 return -EINVAL;
2838         ret = rtw_acl_add_sta(padapter, param->sta_addr);
2839         return ret;
2840 }
2841
2842 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
2843 {
2844         int ret = 0;
2845         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2846         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2847
2848         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2849                 return -EINVAL;
2850
2851         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
2852
2853         return ret;
2854 }
2855
2856 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
2857 {
2858         struct ieee_param *param;
2859         int ret = 0;
2860         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2861
2862         /*
2863         * this function is expect to call in master mode, which allows no power saving
2864         * so, we just check hw_init_completed
2865         */
2866
2867         if (!padapter->hw_init_completed) {
2868                 ret = -EPERM;
2869                 goto out;
2870         }
2871
2872         if (!p->pointer) {
2873                 ret = -EINVAL;
2874                 goto out;
2875         }
2876
2877         param = (struct ieee_param *)rtw_malloc(p->length);
2878         if (param == NULL) {
2879                 ret = -ENOMEM;
2880                 goto out;
2881         }
2882
2883         if (copy_from_user(param, p->pointer, p->length)) {
2884                 kfree(param);
2885                 ret = -EFAULT;
2886                 goto out;
2887         }
2888
2889         switch (param->cmd) {
2890         case RTL871X_HOSTAPD_FLUSH:
2891                 ret = rtw_hostapd_sta_flush(dev);
2892                 break;
2893         case RTL871X_HOSTAPD_ADD_STA:
2894                 ret = rtw_add_sta(dev, param);
2895                 break;
2896         case RTL871X_HOSTAPD_REMOVE_STA:
2897                 ret = rtw_del_sta(dev, param);
2898                 break;
2899         case RTL871X_HOSTAPD_SET_BEACON:
2900                 ret = rtw_set_beacon(dev, param, p->length);
2901                 break;
2902         case RTL871X_SET_ENCRYPTION:
2903                 ret = rtw_set_encryption(dev, param, p->length);
2904                 break;
2905         case RTL871X_HOSTAPD_GET_WPAIE_STA:
2906                 ret = rtw_get_sta_wpaie(dev, param);
2907                 break;
2908         case RTL871X_HOSTAPD_SET_WPS_BEACON:
2909                 ret = rtw_set_wps_beacon(dev, param, p->length);
2910                 break;
2911         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
2912                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
2913                 break;
2914         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
2915                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
2916                 break;
2917         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
2918                 ret = rtw_set_hidden_ssid(dev, param, p->length);
2919                 break;
2920         case RTL871X_HOSTAPD_GET_INFO_STA:
2921                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
2922                 break;
2923         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
2924                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
2925                 break;
2926         case RTL871X_HOSTAPD_ACL_ADD_STA:
2927                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
2928                 break;
2929         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
2930                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
2931                 break;
2932         default:
2933                 DBG_88E("Unknown hostapd request: %d\n", param->cmd);
2934                 ret = -EOPNOTSUPP;
2935                 break;
2936         }
2937
2938         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2939                 ret = -EFAULT;
2940         kfree(param);
2941 out:
2942         return ret;
2943 }
2944 #endif
2945
2946 #include <rtw_android.h>
2947 static int rtw_wx_set_priv(struct net_device *dev,
2948                                 struct iw_request_info *info,
2949                                 union iwreq_data *awrq,
2950                                 char *extra)
2951 {
2952         int ret = 0;
2953         int len = 0;
2954         char *ext;
2955         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2956         struct iw_point *dwrq = (struct iw_point *)awrq;
2957
2958         if (dwrq->length == 0)
2959                 return -EFAULT;
2960
2961         len = dwrq->length;
2962         ext = vmalloc(len);
2963         if (!ext)
2964                 return -ENOMEM;
2965
2966         if (copy_from_user(ext, dwrq->pointer, len)) {
2967                 vfree(ext);
2968                 return -EFAULT;
2969         }
2970
2971         /* added for wps2.0 @20110524 */
2972         if (dwrq->flags == 0x8766 && len > 8) {
2973                 u32 cp_sz;
2974                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2975                 u8 *probereq_wpsie = ext;
2976                 int probereq_wpsie_len = len;
2977                 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2978
2979                 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
2980                     (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
2981                         cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
2982
2983                         pmlmepriv->wps_probe_req_ie_len = 0;
2984                         kfree(pmlmepriv->wps_probe_req_ie);
2985                         pmlmepriv->wps_probe_req_ie = NULL;
2986
2987                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
2988                         if (pmlmepriv->wps_probe_req_ie == NULL) {
2989                                 pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2990                                 ret =  -EINVAL;
2991                                 goto FREE_EXT;
2992                         }
2993                         memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
2994                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
2995                 }
2996                 goto FREE_EXT;
2997         }
2998
2999         if (len >= WEXT_CSCAN_HEADER_SIZE &&
3000             !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
3001                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
3002                 goto FREE_EXT;
3003         }
3004
3005 FREE_EXT:
3006
3007         vfree(ext);
3008
3009         return ret;
3010 }
3011
3012 static iw_handler rtw_handlers[] = {
3013         NULL,                                   /* SIOCSIWCOMMIT */
3014         rtw_wx_get_name,                /* SIOCGIWNAME */
3015         dummy,                                  /* SIOCSIWNWID */
3016         dummy,                                  /* SIOCGIWNWID */
3017         rtw_wx_set_freq,                /* SIOCSIWFREQ */
3018         rtw_wx_get_freq,                /* SIOCGIWFREQ */
3019         rtw_wx_set_mode,                /* SIOCSIWMODE */
3020         rtw_wx_get_mode,                /* SIOCGIWMODE */
3021         dummy,                                  /* SIOCSIWSENS */
3022         rtw_wx_get_sens,                /* SIOCGIWSENS */
3023         NULL,                                   /* SIOCSIWRANGE */
3024         rtw_wx_get_range,               /* SIOCGIWRANGE */
3025         rtw_wx_set_priv,                /* SIOCSIWPRIV */
3026         NULL,                                   /* SIOCGIWPRIV */
3027         NULL,                                   /* SIOCSIWSTATS */
3028         NULL,                                   /* SIOCGIWSTATS */
3029         dummy,                                  /* SIOCSIWSPY */
3030         dummy,                                  /* SIOCGIWSPY */
3031         NULL,                                   /* SIOCGIWTHRSPY */
3032         NULL,                                   /* SIOCWIWTHRSPY */
3033         rtw_wx_set_wap,         /* SIOCSIWAP */
3034         rtw_wx_get_wap,         /* SIOCGIWAP */
3035         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
3036         dummy,                                  /* SIOCGIWAPLIST -- depricated */
3037         rtw_wx_set_scan,                /* SIOCSIWSCAN */
3038         rtw_wx_get_scan,                /* SIOCGIWSCAN */
3039         rtw_wx_set_essid,               /* SIOCSIWESSID */
3040         rtw_wx_get_essid,               /* SIOCGIWESSID */
3041         dummy,                                  /* SIOCSIWNICKN */
3042         rtw_wx_get_nick,                /* SIOCGIWNICKN */
3043         NULL,                                   /* -- hole -- */
3044         NULL,                                   /* -- hole -- */
3045         rtw_wx_set_rate,                /* SIOCSIWRATE */
3046         rtw_wx_get_rate,                /* SIOCGIWRATE */
3047         rtw_wx_set_rts,                 /* SIOCSIWRTS */
3048         rtw_wx_get_rts,                 /* SIOCGIWRTS */
3049         rtw_wx_set_frag,                /* SIOCSIWFRAG */
3050         rtw_wx_get_frag,                /* SIOCGIWFRAG */
3051         dummy,                                  /* SIOCSIWTXPOW */
3052         dummy,                                  /* SIOCGIWTXPOW */
3053         dummy,                                  /* SIOCSIWRETRY */
3054         rtw_wx_get_retry,               /* SIOCGIWRETRY */
3055         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
3056         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
3057         dummy,                                  /* SIOCSIWPOWER */
3058         rtw_wx_get_power,               /* SIOCGIWPOWER */
3059         NULL,                                   /*---hole---*/
3060         NULL,                                   /*---hole---*/
3061         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
3062         NULL,                                   /* SIOCGWGENIE */
3063         rtw_wx_set_auth,                /* SIOCSIWAUTH */
3064         NULL,                                   /* SIOCGIWAUTH */
3065         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
3066         NULL,                                   /* SIOCGIWENCODEEXT */
3067         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
3068         NULL,                                   /*---hole---*/
3069 };
3070
3071 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
3072 {
3073         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3074         struct iw_statistics *piwstats = &padapter->iwstats;
3075         int tmp_level = 0;
3076         int tmp_qual = 0;
3077         int tmp_noise = 0;
3078
3079         if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3080                 piwstats->qual.qual = 0;
3081                 piwstats->qual.level = 0;
3082                 piwstats->qual.noise = 0;
3083         } else {
3084                 tmp_level = padapter->recvpriv.signal_strength;
3085                 tmp_qual = padapter->recvpriv.signal_qual;
3086                 tmp_noise = padapter->recvpriv.noise;
3087
3088                 piwstats->qual.level = tmp_level;
3089                 piwstats->qual.qual = tmp_qual;
3090                 piwstats->qual.noise = tmp_noise;
3091         }
3092         piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
3093         return &padapter->iwstats;
3094 }
3095
3096 struct iw_handler_def rtw_handlers_def = {
3097         .standard = rtw_handlers,
3098         .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
3099         .get_wireless_stats = rtw_get_wireless_stats,
3100 };
3101
3102 #include <rtw_android.h>
3103 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3104 {
3105         struct iwreq *wrq = (struct iwreq *)rq;
3106         int ret = 0;
3107
3108         switch (cmd) {
3109         case RTL_IOCTL_WPA_SUPPLICANT:
3110                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
3111                 break;
3112 #ifdef CONFIG_88EU_AP_MODE
3113         case RTL_IOCTL_HOSTAPD:
3114                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
3115                 break;
3116 #endif /*  CONFIG_88EU_AP_MODE */
3117         case (SIOCDEVPRIVATE+1):
3118                 ret = rtw_android_priv_cmd(dev, rq, cmd);
3119                 break;
3120         default:
3121                 ret = -EOPNOTSUPP;
3122                 break;
3123         }
3124         return ret;
3125 }