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