GNU Linux-libre 4.4.284-gnu1
[releases.git] / 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 &&
1178                                             sec_len <= len &&
1179                                             sec_len <= 32) {
1180                                                 ssid[ssid_index].SsidLength = sec_len;
1181                                                 memcpy(ssid[ssid_index].Ssid, pos, sec_len);
1182                                                 ssid_index++;
1183                                         }
1184                                         pos += sec_len;
1185                                         len -= sec_len;
1186                                         break;
1187                                 case WEXT_CSCAN_TYPE_SECTION:
1188                                 case WEXT_CSCAN_CHANNEL_SECTION:
1189                                         pos += 1;
1190                                         len -= 1;
1191                                         break;
1192                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
1193                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
1194                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1195                                         pos += 2;
1196                                         len -= 2;
1197                                         break;
1198                                 default:
1199                                         len = 0; /*  stop parsing */
1200                                 }
1201                         }
1202
1203                         /* it has still some scan parameter to parse, we only do this now... */
1204                         _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1205                 } else {
1206                         _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1207                 }
1208         }
1209
1210         if (!_status)
1211                 ret = -1;
1212
1213 exit:
1214
1215         return ret;
1216 }
1217
1218 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1219                              union iwreq_data *wrqu, char *extra)
1220 {
1221         struct list_head *plist, *phead;
1222         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1223         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1224         struct __queue *queue   = &(pmlmepriv->scanned_queue);
1225         struct  wlan_network    *pnetwork = NULL;
1226         char *ev = extra;
1227         char *stop = ev + wrqu->data.length;
1228         u32 ret = 0;
1229         u32 cnt = 0;
1230         u32 wait_for_surveydone;
1231         int wait_status;
1232         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1233         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1234
1235         if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
1236                 ret = -EINVAL;
1237                 goto exit;
1238         }
1239
1240         wait_for_surveydone = 100;
1241
1242         wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1243
1244         while (check_fwstate(pmlmepriv, wait_status)) {
1245                 msleep(30);
1246                 cnt++;
1247                 if (cnt > wait_for_surveydone)
1248                         break;
1249         }
1250
1251         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1252
1253         phead = get_list_head(queue);
1254         plist = phead->next;
1255
1256         while (phead != plist) {
1257                 if ((stop - ev) < SCAN_ITEM_SIZE) {
1258                         ret = -E2BIG;
1259                         break;
1260                 }
1261
1262                 pnetwork = container_of(plist, struct wlan_network, list);
1263
1264                 /* report network only if the current channel set contains the channel to which this network belongs */
1265                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1266                         ev = translate_scan(padapter, a, pnetwork, ev, stop);
1267
1268                 plist = plist->next;
1269         }
1270
1271         spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1272
1273         wrqu->data.length = ev-extra;
1274         wrqu->data.flags = 0;
1275
1276 exit:
1277         return ret;
1278 }
1279
1280 /* set ssid flow */
1281 /* s1. rtw_set_802_11_infrastructure_mode() */
1282 /* s2. set_802_11_authenticaion_mode() */
1283 /* s3. set_802_11_encryption_mode() */
1284 /* s4. rtw_set_802_11_ssid() */
1285 static int rtw_wx_set_essid(struct net_device *dev,
1286                               struct iw_request_info *a,
1287                               union iwreq_data *wrqu, char *extra)
1288 {
1289         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1290         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1291         struct __queue *queue = &pmlmepriv->scanned_queue;
1292         struct list_head *phead;
1293         struct wlan_network *pnetwork = NULL;
1294         enum ndis_802_11_auth_mode authmode;
1295         struct ndis_802_11_ssid ndis_ssid;
1296         u8 *dst_ssid, *src_ssid;
1297
1298         uint ret = 0, len;
1299
1300
1301         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1302                  ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1303         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1304                 ret = -1;
1305                 goto exit;
1306         }
1307
1308         if (!padapter->bup) {
1309                 ret = -1;
1310                 goto exit;
1311         }
1312
1313         if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1314                 ret = -E2BIG;
1315                 goto exit;
1316         }
1317
1318         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1319                 ret = -1;
1320                 goto exit;
1321         }
1322
1323         authmode = padapter->securitypriv.ndisauthtype;
1324         DBG_88E("=>%s\n", __func__);
1325         if (wrqu->essid.flags && wrqu->essid.length) {
1326                 len = min_t(uint, wrqu->essid.length, IW_ESSID_MAX_SIZE);
1327
1328                 if (wrqu->essid.length != 33)
1329                         DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1330
1331                 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1332                 ndis_ssid.SsidLength = len;
1333                 memcpy(ndis_ssid.Ssid, extra, len);
1334                 src_ssid = ndis_ssid.Ssid;
1335
1336                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1337                 spin_lock_bh(&queue->lock);
1338                phead = get_list_head(queue);
1339               pmlmepriv->pscanned = phead->next;
1340
1341                 while (phead != pmlmepriv->pscanned) {
1342                         pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1343
1344                         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1345
1346                         dst_ssid = pnetwork->network.Ssid.Ssid;
1347
1348                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1349                                  ("rtw_wx_set_essid: dst_ssid =%s\n",
1350                                   pnetwork->network.Ssid.Ssid));
1351
1352                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1353                             (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
1354                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1355                                          ("rtw_wx_set_essid: find match, set infra mode\n"));
1356
1357                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1358                                         if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1359                                                 continue;
1360                                 }
1361
1362                                 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1363                                         ret = -1;
1364                                         spin_unlock_bh(&queue->lock);
1365                                         goto exit;
1366                                 }
1367
1368                                 break;
1369                         }
1370                 }
1371                 spin_unlock_bh(&queue->lock);
1372                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1373                          ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1374                 rtw_set_802_11_authentication_mode(padapter, authmode);
1375                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1376                         ret = -1;
1377                         goto exit;
1378                 }
1379         }
1380
1381 exit:
1382
1383         DBG_88E("<=%s, ret %d\n", __func__, ret);
1384
1385
1386         return ret;
1387 }
1388
1389 static int rtw_wx_get_essid(struct net_device *dev,
1390                               struct iw_request_info *a,
1391                               union iwreq_data *wrqu, char *extra)
1392 {
1393         u32 len, ret = 0;
1394         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1395         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1396         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1397
1398         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1399
1400
1401         if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1402             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1403                 len = pcur_bss->Ssid.SsidLength;
1404                 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1405         } else {
1406                 len = 0;
1407                 *extra = 0;
1408         }
1409         wrqu->essid.length = len;
1410         wrqu->essid.flags = 1;
1411
1412         return ret;
1413 }
1414
1415 static int rtw_wx_set_rate(struct net_device *dev,
1416                               struct iw_request_info *a,
1417                               union iwreq_data *wrqu, char *extra)
1418 {
1419         int i;
1420         u8 datarates[NumRates];
1421         u32     target_rate = wrqu->bitrate.value;
1422         u32     fixed = wrqu->bitrate.fixed;
1423         u32     ratevalue = 0;
1424          u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1425
1426
1427         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1428         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1429
1430         if (target_rate == -1) {
1431                 ratevalue = 11;
1432                 goto set_rate;
1433         }
1434         target_rate = target_rate/100000;
1435
1436         switch (target_rate) {
1437         case 10:
1438                 ratevalue = 0;
1439                 break;
1440         case 20:
1441                 ratevalue = 1;
1442                 break;
1443         case 55:
1444                 ratevalue = 2;
1445                 break;
1446         case 60:
1447                 ratevalue = 3;
1448                 break;
1449         case 90:
1450                 ratevalue = 4;
1451                 break;
1452         case 110:
1453                 ratevalue = 5;
1454                 break;
1455         case 120:
1456                 ratevalue = 6;
1457                 break;
1458         case 180:
1459                 ratevalue = 7;
1460                 break;
1461         case 240:
1462                 ratevalue = 8;
1463                 break;
1464         case 360:
1465                 ratevalue = 9;
1466                 break;
1467         case 480:
1468                 ratevalue = 10;
1469                 break;
1470         case 540:
1471                 ratevalue = 11;
1472                 break;
1473         default:
1474                 ratevalue = 11;
1475                 break;
1476         }
1477
1478 set_rate:
1479
1480         for (i = 0; i < NumRates; i++) {
1481                 if (ratevalue == mpdatarate[i]) {
1482                         datarates[i] = mpdatarate[i];
1483                         if (fixed == 0)
1484                                 break;
1485                 } else {
1486                         datarates[i] = 0xff;
1487                 }
1488
1489                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1490         }
1491
1492         return 0;
1493 }
1494
1495 static int rtw_wx_get_rate(struct net_device *dev,
1496                              struct iw_request_info *info,
1497                              union iwreq_data *wrqu, char *extra)
1498 {
1499         u16 max_rate = 0;
1500
1501         max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1502
1503         if (max_rate == 0)
1504                 return -EPERM;
1505
1506         wrqu->bitrate.fixed = 0;        /* no auto select */
1507         wrqu->bitrate.value = max_rate * 100000;
1508
1509         return 0;
1510 }
1511
1512 static int rtw_wx_set_rts(struct net_device *dev,
1513                              struct iw_request_info *info,
1514                              union iwreq_data *wrqu, char *extra)
1515 {
1516         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1517
1518
1519         if (wrqu->rts.disabled) {
1520                 padapter->registrypriv.rts_thresh = 2347;
1521         } else {
1522                 if (wrqu->rts.value < 0 ||
1523                     wrqu->rts.value > 2347)
1524                         return -EINVAL;
1525
1526                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1527         }
1528
1529         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1530
1531
1532         return 0;
1533 }
1534
1535 static int rtw_wx_get_rts(struct net_device *dev,
1536                              struct iw_request_info *info,
1537                              union iwreq_data *wrqu, char *extra)
1538 {
1539         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1540
1541
1542         DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1543
1544         wrqu->rts.value = padapter->registrypriv.rts_thresh;
1545         wrqu->rts.fixed = 0;    /* no auto select */
1546         /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1547
1548
1549         return 0;
1550 }
1551
1552 static int rtw_wx_set_frag(struct net_device *dev,
1553                              struct iw_request_info *info,
1554                              union iwreq_data *wrqu, char *extra)
1555 {
1556         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1557
1558
1559         if (wrqu->frag.disabled) {
1560                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1561         } else {
1562                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1563                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
1564                         return -EINVAL;
1565
1566                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1567         }
1568
1569         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1570
1571
1572         return 0;
1573 }
1574
1575 static int rtw_wx_get_frag(struct net_device *dev,
1576                              struct iw_request_info *info,
1577                              union iwreq_data *wrqu, char *extra)
1578 {
1579         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1580
1581
1582         DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1583
1584         wrqu->frag.value = padapter->xmitpriv.frag_len;
1585         wrqu->frag.fixed = 0;   /* no auto select */
1586
1587
1588         return 0;
1589 }
1590
1591 static int rtw_wx_get_retry(struct net_device *dev,
1592                              struct iw_request_info *info,
1593                              union iwreq_data *wrqu, char *extra)
1594 {
1595         wrqu->retry.value = 7;
1596         wrqu->retry.fixed = 0;  /* no auto select */
1597         wrqu->retry.disabled = 1;
1598
1599         return 0;
1600 }
1601
1602 static int rtw_wx_set_enc(struct net_device *dev,
1603                             struct iw_request_info *info,
1604                             union iwreq_data *wrqu, char *keybuf)
1605 {
1606         u32 key, ret = 0;
1607         u32 keyindex_provided;
1608         struct ndis_802_11_wep   wep;
1609         enum ndis_802_11_auth_mode authmode;
1610
1611         struct iw_point *erq = &(wrqu->encoding);
1612         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1613         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1614         DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1615
1616         memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1617
1618         key = erq->flags & IW_ENCODE_INDEX;
1619
1620
1621         if (erq->flags & IW_ENCODE_DISABLED) {
1622                 DBG_88E("EncryptionDisabled\n");
1623                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1624                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1625                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1626                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1627                 authmode = Ndis802_11AuthModeOpen;
1628                 padapter->securitypriv.ndisauthtype = authmode;
1629
1630                 goto exit;
1631         }
1632
1633         if (key) {
1634                 if (key > WEP_KEYS)
1635                         return -EINVAL;
1636                 key--;
1637                 keyindex_provided = 1;
1638         } else {
1639                 keyindex_provided = 0;
1640                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1641                 DBG_88E("rtw_wx_set_enc, key =%d\n", key);
1642         }
1643
1644         /* set authentication mode */
1645         if (erq->flags & IW_ENCODE_OPEN) {
1646                 DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1647                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1648                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1649                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1650                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1651                 authmode = Ndis802_11AuthModeOpen;
1652                 padapter->securitypriv.ndisauthtype = authmode;
1653         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1654                 DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1655                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1656                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1657                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1658                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1659                 authmode = Ndis802_11AuthModeShared;
1660                 padapter->securitypriv.ndisauthtype = authmode;
1661         } else {
1662                 DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1663
1664                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1665                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1666                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1667                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1668                 authmode = Ndis802_11AuthModeOpen;
1669                 padapter->securitypriv.ndisauthtype = authmode;
1670         }
1671
1672         wep.KeyIndex = key;
1673         if (erq->length > 0) {
1674                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1675
1676                 wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
1677         } else {
1678                 wep.KeyLength = 0;
1679
1680                 if (keyindex_provided == 1) {
1681                         /*  set key_id only, no given KeyMaterial(erq->length == 0). */
1682                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
1683
1684                         DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1685
1686                         switch (padapter->securitypriv.dot11DefKeylen[key]) {
1687                         case 5:
1688                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1689                                 break;
1690                         case 13:
1691                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1692                                 break;
1693                         default:
1694                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1695                                 break;
1696                         }
1697
1698                         goto exit;
1699                 }
1700         }
1701
1702         wep.KeyIndex |= 0x80000000;
1703
1704         memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1705
1706         if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1707                 if (rf_on == pwrpriv->rf_pwrstate)
1708                         ret = -EOPNOTSUPP;
1709                 goto exit;
1710         }
1711
1712 exit:
1713
1714
1715         return ret;
1716 }
1717
1718 static int rtw_wx_get_enc(struct net_device *dev,
1719                             struct iw_request_info *info,
1720                             union iwreq_data *wrqu, char *keybuf)
1721 {
1722         uint key, ret = 0;
1723         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1724         struct iw_point *erq = &(wrqu->encoding);
1725         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1726
1727
1728         if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1729                 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1730                         erq->length = 0;
1731                         erq->flags |= IW_ENCODE_DISABLED;
1732                         return 0;
1733                 }
1734         }
1735
1736         key = erq->flags & IW_ENCODE_INDEX;
1737
1738         if (key) {
1739                 if (key > WEP_KEYS)
1740                         return -EINVAL;
1741                 key--;
1742         } else {
1743                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1744         }
1745
1746         erq->flags = key + 1;
1747
1748         switch (padapter->securitypriv.ndisencryptstatus) {
1749         case Ndis802_11EncryptionNotSupported:
1750         case Ndis802_11EncryptionDisabled:
1751                 erq->length = 0;
1752                 erq->flags |= IW_ENCODE_DISABLED;
1753                 break;
1754         case Ndis802_11Encryption1Enabled:
1755                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1756                 if (erq->length) {
1757                         memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1758
1759                         erq->flags |= IW_ENCODE_ENABLED;
1760
1761                         if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1762                                 erq->flags |= IW_ENCODE_OPEN;
1763                         else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1764                                 erq->flags |= IW_ENCODE_RESTRICTED;
1765                 } else {
1766                         erq->length = 0;
1767                         erq->flags |= IW_ENCODE_DISABLED;
1768                 }
1769                 break;
1770         case Ndis802_11Encryption2Enabled:
1771         case Ndis802_11Encryption3Enabled:
1772                 erq->length = 16;
1773                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1774                 break;
1775         default:
1776                 erq->length = 0;
1777                 erq->flags |= IW_ENCODE_DISABLED;
1778                 break;
1779         }
1780
1781         return ret;
1782 }
1783
1784 static int rtw_wx_get_power(struct net_device *dev,
1785                              struct iw_request_info *info,
1786                              union iwreq_data *wrqu, char *extra)
1787 {
1788         wrqu->power.value = 0;
1789         wrqu->power.fixed = 0;  /* no auto select */
1790         wrqu->power.disabled = 1;
1791
1792         return 0;
1793 }
1794
1795 static int rtw_wx_set_gen_ie(struct net_device *dev,
1796                              struct iw_request_info *info,
1797                              union iwreq_data *wrqu, char *extra)
1798 {
1799         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1800
1801         return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1802 }
1803
1804 static int rtw_wx_set_auth(struct net_device *dev,
1805                              struct iw_request_info *info,
1806                              union iwreq_data *wrqu, char *extra)
1807 {
1808         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1809         struct iw_param *param = (struct iw_param *)&(wrqu->param);
1810         int ret = 0;
1811
1812         switch (param->flags & IW_AUTH_INDEX) {
1813         case IW_AUTH_WPA_VERSION:
1814                 break;
1815         case IW_AUTH_CIPHER_PAIRWISE:
1816
1817                 break;
1818         case IW_AUTH_CIPHER_GROUP:
1819
1820                 break;
1821         case IW_AUTH_KEY_MGMT:
1822                 /*
1823                  *  ??? does not use these parameters
1824                  */
1825                 break;
1826         case IW_AUTH_TKIP_COUNTERMEASURES:
1827                 if (param->value) {
1828                         /*  wpa_supplicant is enabling the tkip countermeasure. */
1829                         padapter->securitypriv.btkip_countermeasure = true;
1830                 } else {
1831                         /*  wpa_supplicant is disabling the tkip countermeasure. */
1832                         padapter->securitypriv.btkip_countermeasure = false;
1833                 }
1834                 break;
1835         case IW_AUTH_DROP_UNENCRYPTED:
1836                 /* HACK:
1837                  *
1838                  * wpa_supplicant calls set_wpa_enabled when the driver
1839                  * is loaded and unloaded, regardless of if WPA is being
1840                  * used.  No other calls are made which can be used to
1841                  * determine if encryption will be used or not prior to
1842                  * association being expected.  If encryption is not being
1843                  * used, drop_unencrypted is set to false, else true -- we
1844                  * can use this to determine if the CAP_PRIVACY_ON bit should
1845                  * be set.
1846                  */
1847
1848                 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
1849                         break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
1850                                         /*  then it needn't reset it; */
1851
1852                 if (param->value) {
1853                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1854                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1855                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1856                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1857                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1858                 }
1859
1860                 break;
1861         case IW_AUTH_80211_AUTH_ALG:
1862                 /*
1863                  *  It's the starting point of a link layer connection using wpa_supplicant
1864                 */
1865                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1866                         LeaveAllPowerSaveMode(padapter);
1867                         rtw_disassoc_cmd(padapter, 500, false);
1868                         DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
1869                         rtw_indicate_disconnect(padapter);
1870                         rtw_free_assoc_resources(padapter);
1871                 }
1872                 ret = wpa_set_auth_algs(dev, (u32)param->value);
1873                 break;
1874         case IW_AUTH_WPA_ENABLED:
1875                 break;
1876         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1877                 break;
1878         case IW_AUTH_PRIVACY_INVOKED:
1879                 break;
1880         default:
1881                 return -EOPNOTSUPP;
1882         }
1883
1884         return ret;
1885 }
1886
1887 static int rtw_wx_set_enc_ext(struct net_device *dev,
1888                              struct iw_request_info *info,
1889                              union iwreq_data *wrqu, char *extra)
1890 {
1891         char *alg_name;
1892         u32 param_len;
1893         struct ieee_param *param = NULL;
1894         struct iw_point *pencoding = &wrqu->encoding;
1895         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1896         int ret = 0;
1897
1898         param_len = sizeof(struct ieee_param) + pext->key_len;
1899         param = (struct ieee_param *)rtw_malloc(param_len);
1900         if (param == NULL)
1901                 return -1;
1902
1903         memset(param, 0, param_len);
1904
1905         param->cmd = IEEE_CMD_SET_ENCRYPTION;
1906         memset(param->sta_addr, 0xff, ETH_ALEN);
1907
1908         switch (pext->alg) {
1909         case IW_ENCODE_ALG_NONE:
1910                 /* todo: remove key */
1911                 /* remove = 1; */
1912                 alg_name = "none";
1913                 break;
1914         case IW_ENCODE_ALG_WEP:
1915                 alg_name = "WEP";
1916                 break;
1917         case IW_ENCODE_ALG_TKIP:
1918                 alg_name = "TKIP";
1919                 break;
1920         case IW_ENCODE_ALG_CCMP:
1921                 alg_name = "CCMP";
1922                 break;
1923         default:
1924                 ret = -1;
1925                 goto exit;
1926         }
1927
1928         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1929
1930         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1931                 param->u.crypt.set_tx = 1;
1932
1933         /* cliW: WEP does not have group key
1934          * just not checking GROUP key setting
1935          */
1936         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
1937             (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1938                 param->u.crypt.set_tx = 0;
1939
1940         param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
1941
1942         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1943                 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1944
1945         if (pext->key_len) {
1946                 param->u.crypt.key_len = pext->key_len;
1947                 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
1948         }
1949
1950         ret =  wpa_set_encryption(dev, param, param_len);
1951
1952 exit:
1953         kfree(param);
1954         return ret;
1955 }
1956
1957 static int rtw_wx_get_nick(struct net_device *dev,
1958                            struct iw_request_info *info,
1959                            union iwreq_data *wrqu, char *extra)
1960 {
1961         if (extra) {
1962                 wrqu->data.length = 14;
1963                 wrqu->data.flags = 1;
1964                 memcpy(extra, "<WIFI@REALTEK>", 14);
1965         }
1966
1967         /* dump debug info here */
1968         return 0;
1969 }
1970
1971 static int dummy(struct net_device *dev, struct iw_request_info *a,
1972                  union iwreq_data *wrqu, char *b)
1973 {
1974         return -1;
1975 }
1976
1977 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
1978 {
1979         uint ret = 0;
1980         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1981
1982         switch (name) {
1983         case IEEE_PARAM_WPA_ENABLED:
1984                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
1985                 switch ((value)&0xff) {
1986                 case 1: /* WPA */
1987                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
1988                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1989                         break;
1990                 case 2: /* WPA2 */
1991                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
1992                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1993                         break;
1994                 }
1995                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1996                          ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
1997                 break;
1998         case IEEE_PARAM_TKIP_COUNTERMEASURES:
1999                 break;
2000         case IEEE_PARAM_DROP_UNENCRYPTED: {
2001                 /* HACK:
2002                  *
2003                  * wpa_supplicant calls set_wpa_enabled when the driver
2004                  * is loaded and unloaded, regardless of if WPA is being
2005                  * used.  No other calls are made which can be used to
2006                  * determine if encryption will be used or not prior to
2007                  * association being expected.  If encryption is not being
2008                  * used, drop_unencrypted is set to false, else true -- we
2009                  * can use this to determine if the CAP_PRIVACY_ON bit should
2010                  * be set.
2011                  */
2012
2013                 break;
2014         }
2015         case IEEE_PARAM_PRIVACY_INVOKED:
2016                 break;
2017
2018         case IEEE_PARAM_AUTH_ALGS:
2019                 ret = wpa_set_auth_algs(dev, value);
2020                 break;
2021         case IEEE_PARAM_IEEE_802_1X:
2022                 break;
2023         case IEEE_PARAM_WPAX_SELECT:
2024                 break;
2025         default:
2026                 ret = -EOPNOTSUPP;
2027                 break;
2028         }
2029         return ret;
2030 }
2031
2032 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2033 {
2034         int ret = 0;
2035         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2036
2037         switch (command) {
2038         case IEEE_MLME_STA_DEAUTH:
2039                 if (!rtw_set_802_11_disassociate(padapter))
2040                         ret = -1;
2041                 break;
2042         case IEEE_MLME_STA_DISASSOC:
2043                 if (!rtw_set_802_11_disassociate(padapter))
2044                         ret = -1;
2045                 break;
2046         default:
2047                 ret = -EOPNOTSUPP;
2048                 break;
2049         }
2050
2051         return ret;
2052 }
2053
2054 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2055 {
2056         struct ieee_param *param;
2057         uint ret = 0;
2058
2059         if (!p->pointer || p->length != sizeof(struct ieee_param)) {
2060                 ret = -EINVAL;
2061                 goto out;
2062         }
2063
2064         param = (struct ieee_param *)rtw_malloc(p->length);
2065         if (param == NULL) {
2066                 ret = -ENOMEM;
2067                 goto out;
2068         }
2069
2070         if (copy_from_user(param, p->pointer, p->length)) {
2071                 kfree(param);
2072                 ret = -EFAULT;
2073                 goto out;
2074         }
2075
2076         switch (param->cmd) {
2077         case IEEE_CMD_SET_WPA_PARAM:
2078                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
2079                 break;
2080
2081         case IEEE_CMD_SET_WPA_IE:
2082                 ret =  rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
2083                                       (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
2084                 break;
2085
2086         case IEEE_CMD_SET_ENCRYPTION:
2087                 ret = wpa_set_encryption(dev, param, p->length);
2088                 break;
2089
2090         case IEEE_CMD_MLME:
2091                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
2092                 break;
2093
2094         default:
2095                 DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
2096                 ret = -EOPNOTSUPP;
2097                 break;
2098         }
2099
2100         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2101                 ret = -EFAULT;
2102
2103         kfree(param);
2104
2105 out:
2106
2107         return ret;
2108 }
2109
2110 #ifdef CONFIG_88EU_AP_MODE
2111 static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
2112 {
2113         struct cmd_obj *ph2c;
2114         struct set_stakey_parm  *psetstakey_para;
2115         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2116         u8 res = _SUCCESS;
2117
2118         ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
2119         if (ph2c == NULL) {
2120                 res = _FAIL;
2121                 goto exit;
2122         }
2123
2124         psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
2125         if (psetstakey_para == NULL) {
2126                 kfree(ph2c);
2127                 res = _FAIL;
2128                 goto exit;
2129         }
2130
2131         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
2132
2133         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
2134
2135         memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
2136
2137         memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
2138
2139         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2140
2141 exit:
2142
2143         return res;
2144 }
2145
2146 static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
2147 {
2148         u8 keylen;
2149         struct cmd_obj *pcmd;
2150         struct setkey_parm *psetkeyparm;
2151         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
2152         int res = _SUCCESS;
2153
2154         DBG_88E("%s\n", __func__);
2155
2156         pcmd = kzalloc(sizeof(struct    cmd_obj), GFP_KERNEL);
2157         if (pcmd == NULL) {
2158                 res = _FAIL;
2159                 goto exit;
2160         }
2161         psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
2162         if (psetkeyparm == NULL) {
2163                 kfree(pcmd);
2164                 res = _FAIL;
2165                 goto exit;
2166         }
2167
2168         memset(psetkeyparm, 0, sizeof(struct setkey_parm));
2169
2170         psetkeyparm->keyid = (u8)keyid;
2171
2172         psetkeyparm->algorithm = alg;
2173
2174         psetkeyparm->set_tx = 1;
2175
2176         switch (alg) {
2177         case _WEP40_:
2178                 keylen = 5;
2179                 break;
2180         case _WEP104_:
2181                 keylen = 13;
2182                 break;
2183         case _TKIP_:
2184         case _TKIP_WTMIC_:
2185         case _AES_:
2186         default:
2187                 keylen = 16;
2188         }
2189
2190         memcpy(&(psetkeyparm->key[0]), key, keylen);
2191
2192         pcmd->cmdcode = _SetKey_CMD_;
2193         pcmd->parmbuf = (u8 *)psetkeyparm;
2194         pcmd->cmdsz =  (sizeof(struct setkey_parm));
2195         pcmd->rsp = NULL;
2196         pcmd->rspsz = 0;
2197
2198         INIT_LIST_HEAD(&pcmd->list);
2199
2200         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2201
2202 exit:
2203
2204         return res;
2205 }
2206
2207 static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
2208 {
2209         u8 alg;
2210
2211         switch (keylen) {
2212         case 5:
2213                 alg = _WEP40_;
2214                 break;
2215         case 13:
2216                 alg = _WEP104_;
2217                 break;
2218         default:
2219                 alg = _NO_PRIVACY_;
2220         }
2221
2222         return set_group_key(padapter, key, alg, keyid);
2223 }
2224
2225 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
2226 {
2227         int ret = 0;
2228         u32 wep_key_idx, wep_key_len, wep_total_len;
2229         struct ndis_802_11_wep   *pwep = NULL;
2230         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
2231         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2232         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
2233         struct security_priv *psecuritypriv = &(padapter->securitypriv);
2234         struct sta_priv *pstapriv = &padapter->stapriv;
2235
2236         DBG_88E("%s\n", __func__);
2237         param->u.crypt.err = 0;
2238         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2239         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
2240                 ret =  -EINVAL;
2241                 goto exit;
2242         }
2243         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2244             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2245             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
2246                 if (param->u.crypt.idx >= WEP_KEYS) {
2247                         ret = -EINVAL;
2248                         goto exit;
2249                 }
2250         } else {
2251                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2252                 if (!psta) {
2253                         DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
2254                         goto exit;
2255                 }
2256         }
2257
2258         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
2259                 /* todo:clear default encryption keys */
2260
2261                 DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
2262                 goto exit;
2263         }
2264         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
2265                 DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
2266                 wep_key_idx = param->u.crypt.idx;
2267                 wep_key_len = param->u.crypt.key_len;
2268                 DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
2269                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
2270                         ret = -EINVAL;
2271                         goto exit;
2272                 }
2273
2274                 if (wep_key_len > 0) {
2275                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
2276                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
2277                         pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
2278                         if (pwep == NULL) {
2279                                 DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
2280                                 goto exit;
2281                         }
2282
2283                         memset(pwep, 0, wep_total_len);
2284
2285                         pwep->KeyLength = wep_key_len;
2286                         pwep->Length = wep_total_len;
2287                 }
2288
2289                 pwep->KeyIndex = wep_key_idx;
2290
2291                 memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
2292
2293                 if (param->u.crypt.set_tx) {
2294                         DBG_88E("wep, set_tx = 1\n");
2295
2296                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
2297                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
2298                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2299
2300                         if (pwep->KeyLength == 13) {
2301                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
2302                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2303                         }
2304
2305                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
2306
2307                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
2308
2309                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2310
2311                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2312                 } else {
2313                         DBG_88E("wep, set_tx = 0\n");
2314
2315                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
2316                         /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
2317
2318                       memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
2319
2320                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2321
2322                         set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2323                 }
2324
2325                 goto exit;
2326         }
2327
2328         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
2329                 if (param->u.crypt.set_tx == 1) {
2330                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2331                                 DBG_88E("%s, set group_key, WEP\n", __func__);
2332
2333                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2334                                             param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2335
2336                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2337                                 if (param->u.crypt.key_len == 13)
2338                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2339                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2340                                 DBG_88E("%s, set group_key, TKIP\n", __func__);
2341                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2342                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2343                                             param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2344                                 /* set mic key */
2345                                 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
2346                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
2347
2348                                 psecuritypriv->busetkipkey = true;
2349                         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2350                                 DBG_88E("%s, set group_key, CCMP\n", __func__);
2351                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
2352                                 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2353                                             param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2354                         } else {
2355                                 DBG_88E("%s, set group_key, none\n", __func__);
2356                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2357                         }
2358                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2359                         psecuritypriv->binstallGrpkey = true;
2360                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2361                         set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2362                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2363                         if (pbcmc_sta) {
2364                                 pbcmc_sta->ieee8021x_blocked = false;
2365                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2366                         }
2367                 }
2368                 goto exit;
2369         }
2370
2371         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
2372                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2373                         if (param->u.crypt.set_tx == 1) {
2374                                 memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2375
2376                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2377                                         DBG_88E("%s, set pairwise key, WEP\n", __func__);
2378
2379                                         psta->dot118021XPrivacy = _WEP40_;
2380                                         if (param->u.crypt.key_len == 13)
2381                                                 psta->dot118021XPrivacy = _WEP104_;
2382                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2383                                         DBG_88E("%s, set pairwise key, TKIP\n", __func__);
2384
2385                                         psta->dot118021XPrivacy = _TKIP_;
2386
2387                                         /* set mic key */
2388                                         memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
2389                                         memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
2390
2391                                         psecuritypriv->busetkipkey = true;
2392                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2393                                         DBG_88E("%s, set pairwise key, CCMP\n", __func__);
2394
2395                                         psta->dot118021XPrivacy = _AES_;
2396                                 } else {
2397                                         DBG_88E("%s, set pairwise key, none\n", __func__);
2398
2399                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
2400                                 }
2401
2402                                 set_pairwise_key(padapter, psta);
2403
2404                                 psta->ieee8021x_blocked = false;
2405                         } else { /* group key??? */
2406                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2407                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2408                                                     param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2409                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2410                                         if (param->u.crypt.key_len == 13)
2411                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2412                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2413                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2414
2415                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2416                                                     param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2417
2418                                         /* set mic key */
2419                                         memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
2420                                         memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
2421
2422                                         psecuritypriv->busetkipkey = true;
2423                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2424                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
2425
2426                                         memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2427                                                     param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
2428                                 } else {
2429                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2430                                 }
2431
2432                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2433
2434                                 psecuritypriv->binstallGrpkey = true;
2435
2436                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2437
2438                                 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2439
2440                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2441                                 if (pbcmc_sta) {
2442                                         pbcmc_sta->ieee8021x_blocked = false;
2443                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2444                                 }
2445                         }
2446                 }
2447         }
2448
2449 exit:
2450
2451         kfree(pwep);
2452
2453         return ret;
2454 }
2455
2456 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
2457 {
2458         int ret = 0;
2459         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2460         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2461         struct sta_priv *pstapriv = &padapter->stapriv;
2462         unsigned char *pbuf = param->u.bcn_ie.buf;
2463
2464         DBG_88E("%s, len =%d\n", __func__, len);
2465
2466         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2467                 return -EINVAL;
2468
2469         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
2470
2471         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
2472                 pstapriv->max_num_sta = NUM_STA;
2473
2474         if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
2475                 ret = 0;
2476         else
2477                 ret = -EINVAL;
2478
2479         return ret;
2480 }
2481
2482 static int rtw_hostapd_sta_flush(struct net_device *dev)
2483 {
2484         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2485
2486         DBG_88E("%s\n", __func__);
2487
2488         flush_all_cam_entry(padapter);  /* clear CAM */
2489
2490         return rtw_sta_flush(padapter);
2491 }
2492
2493 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
2494 {
2495         int ret = 0;
2496         struct sta_info *psta = NULL;
2497         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2498         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2499         struct sta_priv *pstapriv = &padapter->stapriv;
2500
2501         DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
2502
2503         if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
2504                 return -EINVAL;
2505
2506         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2507             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2508             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2509                 return -EINVAL;
2510
2511         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2512         if (psta) {
2513                 int flags = param->u.add_sta.flags;
2514
2515                 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
2516
2517                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
2518
2519                 /* check wmm cap. */
2520                 if (WLAN_STA_WME&flags)
2521                         psta->qos_option = 1;
2522                 else
2523                         psta->qos_option = 0;
2524
2525                 if (pmlmepriv->qospriv.qos_option == 0)
2526                         psta->qos_option = 0;
2527
2528                 /* chec 802.11n ht cap. */
2529                 if (WLAN_STA_HT&flags) {
2530                         psta->htpriv.ht_option = true;
2531                         psta->qos_option = 1;
2532                         memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
2533                 } else {
2534                         psta->htpriv.ht_option = false;
2535                 }
2536
2537                 if (pmlmepriv->htpriv.ht_option == false)
2538                         psta->htpriv.ht_option = false;
2539
2540                 update_sta_info_apmode(padapter, psta);
2541         } else {
2542                 ret = -ENOMEM;
2543         }
2544
2545         return ret;
2546 }
2547
2548 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
2549 {
2550         int ret = 0;
2551         struct sta_info *psta = NULL;
2552         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2553         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2554         struct sta_priv *pstapriv = &padapter->stapriv;
2555         int updated = 0;
2556
2557         DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
2558
2559         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2560                 return -EINVAL;
2561
2562         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2563             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2564             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2565                 return -EINVAL;
2566
2567         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2568         if (psta) {
2569                 spin_lock_bh(&pstapriv->asoc_list_lock);
2570                 if (!list_empty(&psta->asoc_list)) {
2571                         list_del_init(&psta->asoc_list);
2572                         pstapriv->asoc_list_cnt--;
2573                         updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
2574                 }
2575                 spin_unlock_bh(&pstapriv->asoc_list_lock);
2576                 associated_clients_update(padapter, updated);
2577                 psta = NULL;
2578         } else {
2579                 DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
2580         }
2581
2582         return ret;
2583 }
2584
2585 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
2586 {
2587         int ret = 0;
2588         struct sta_info *psta = NULL;
2589         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2590         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2591         struct sta_priv *pstapriv = &padapter->stapriv;
2592         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
2593         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
2594
2595         DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
2596
2597         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2598                 return -EINVAL;
2599
2600         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
2601             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
2602             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
2603                 return -EINVAL;
2604
2605         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
2606         if (psta) {
2607                 psta_data->aid = (u16)psta->aid;
2608                 psta_data->capability = psta->capability;
2609                 psta_data->flags = psta->flags;
2610
2611 /*
2612                 nonerp_set : BIT(0)
2613                 no_short_slot_time_set : BIT(1)
2614                 no_short_preamble_set : BIT(2)
2615                 no_ht_gf_set : BIT(3)
2616                 no_ht_set : BIT(4)
2617                 ht_20mhz_set : BIT(5)
2618 */
2619
2620                 psta_data->sta_set = ((psta->nonerp_set) |
2621                                       (psta->no_short_slot_time_set << 1) |
2622                                       (psta->no_short_preamble_set << 2) |
2623                                       (psta->no_ht_gf_set << 3) |
2624                                       (psta->no_ht_set << 4) |
2625                                       (psta->ht_20mhz_set << 5));
2626                 psta_data->tx_supp_rates_len =  psta->bssratelen;
2627                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
2628                 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
2629                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
2630                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
2631                 psta_data->rx_drops = psta->sta_stats.rx_drops;
2632                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
2633                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
2634                 psta_data->tx_drops = psta->sta_stats.tx_drops;
2635         } else {
2636                 ret = -1;
2637         }
2638
2639         return ret;
2640 }
2641
2642 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
2643 {
2644         int ret = 0;
2645         struct sta_info *psta = NULL;
2646         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2647         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2648         struct sta_priv *pstapriv = &padapter->stapriv;
2649
2650         DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
2651
2652         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2653                 return -EINVAL;
2654
2655         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2656             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2657             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2658                 return -EINVAL;
2659
2660         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2661         if (psta) {
2662                 if (psta->wpa_ie[0] == WLAN_EID_RSN ||
2663                     psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
2664                         int wpa_ie_len;
2665                         int copy_len;
2666
2667                         wpa_ie_len = psta->wpa_ie[1];
2668                         copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
2669                         param->u.wpa_ie.len = copy_len;
2670                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
2671                 } else {
2672                         DBG_88E("sta's wpa_ie is NONE\n");
2673                 }
2674         } else {
2675                 ret = -1;
2676         }
2677
2678         return ret;
2679 }
2680
2681 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
2682 {
2683         int ret = 0;
2684         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2685         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2686         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2687         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2688         int ie_len;
2689
2690         DBG_88E("%s, len =%d\n", __func__, len);
2691
2692         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2693                 return -EINVAL;
2694
2695         ie_len = len-12-2;/*  12 = param header, 2:no packed */
2696
2697         kfree(pmlmepriv->wps_beacon_ie);
2698         pmlmepriv->wps_beacon_ie = NULL;
2699
2700         if (ie_len > 0) {
2701                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
2702                 pmlmepriv->wps_beacon_ie_len = ie_len;
2703                 if (pmlmepriv->wps_beacon_ie == NULL) {
2704                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2705                         return -EINVAL;
2706                 }
2707
2708                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
2709
2710                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
2711
2712                 pmlmeext->bstart_bss = true;
2713         }
2714
2715         return ret;
2716 }
2717
2718 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
2719 {
2720         int ret = 0;
2721         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2722         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2723         int ie_len;
2724
2725         DBG_88E("%s, len =%d\n", __func__, len);
2726
2727         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2728                 return -EINVAL;
2729
2730         ie_len = len-12-2;/*  12 = param header, 2:no packed */
2731
2732         kfree(pmlmepriv->wps_probe_resp_ie);
2733         pmlmepriv->wps_probe_resp_ie = NULL;
2734
2735         if (ie_len > 0) {
2736                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
2737                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
2738                 if (pmlmepriv->wps_probe_resp_ie == NULL) {
2739                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2740                         return -EINVAL;
2741                 }
2742                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
2743         }
2744
2745         return ret;
2746 }
2747
2748 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
2749 {
2750         int ret = 0;
2751         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2752         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2753         int ie_len;
2754
2755         DBG_88E("%s, len =%d\n", __func__, len);
2756
2757         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2758                 return -EINVAL;
2759
2760         ie_len = len-12-2;/*  12 = param header, 2:no packed */
2761
2762         kfree(pmlmepriv->wps_assoc_resp_ie);
2763         pmlmepriv->wps_assoc_resp_ie = NULL;
2764
2765         if (ie_len > 0) {
2766                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
2767                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
2768                 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
2769                         DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2770                         return -EINVAL;
2771                 }
2772
2773                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
2774         }
2775
2776         return ret;
2777 }
2778
2779 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
2780 {
2781         int ret = 0;
2782         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2783         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2784         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2785         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2786
2787         u8 value;
2788
2789         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2790                 return -EINVAL;
2791
2792         if (param->u.wpa_param.name != 0) /* dummy test... */
2793                 DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
2794         value = param->u.wpa_param.value;
2795
2796         /* use the same definition of hostapd's ignore_broadcast_ssid */
2797         if (value != 1 && value != 2)
2798                 value = 0;
2799         DBG_88E("%s value(%u)\n", __func__, value);
2800         pmlmeinfo->hidden_ssid_mode = value;
2801         return ret;
2802 }
2803
2804 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
2805 {
2806         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2807         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2808
2809         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2810                 return -EINVAL;
2811
2812         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2813             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2814             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2815                 return -EINVAL;
2816         return rtw_acl_remove_sta(padapter, param->sta_addr);
2817 }
2818
2819 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
2820 {
2821         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2822         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2823
2824         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2825                 return -EINVAL;
2826
2827         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2828             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2829             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2830                 return -EINVAL;
2831         return rtw_acl_add_sta(padapter, param->sta_addr);
2832 }
2833
2834 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
2835 {
2836         int ret = 0;
2837         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2838         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2839
2840         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2841                 return -EINVAL;
2842
2843         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
2844
2845         return ret;
2846 }
2847
2848 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
2849 {
2850         struct ieee_param *param;
2851         int ret = 0;
2852         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2853
2854         /*
2855         * this function is expect to call in master mode, which allows no power saving
2856         * so, we just check hw_init_completed
2857         */
2858
2859         if (!padapter->hw_init_completed) {
2860                 ret = -EPERM;
2861                 goto out;
2862         }
2863
2864         if (!p->pointer || p->length != sizeof(struct ieee_param)) {
2865                 ret = -EINVAL;
2866                 goto out;
2867         }
2868
2869         param = (struct ieee_param *)rtw_malloc(p->length);
2870         if (param == NULL) {
2871                 ret = -ENOMEM;
2872                 goto out;
2873         }
2874
2875         if (copy_from_user(param, p->pointer, p->length)) {
2876                 kfree(param);
2877                 ret = -EFAULT;
2878                 goto out;
2879         }
2880
2881         switch (param->cmd) {
2882         case RTL871X_HOSTAPD_FLUSH:
2883                 ret = rtw_hostapd_sta_flush(dev);
2884                 break;
2885         case RTL871X_HOSTAPD_ADD_STA:
2886                 ret = rtw_add_sta(dev, param);
2887                 break;
2888         case RTL871X_HOSTAPD_REMOVE_STA:
2889                 ret = rtw_del_sta(dev, param);
2890                 break;
2891         case RTL871X_HOSTAPD_SET_BEACON:
2892                 ret = rtw_set_beacon(dev, param, p->length);
2893                 break;
2894         case RTL871X_SET_ENCRYPTION:
2895                 ret = rtw_set_encryption(dev, param, p->length);
2896                 break;
2897         case RTL871X_HOSTAPD_GET_WPAIE_STA:
2898                 ret = rtw_get_sta_wpaie(dev, param);
2899                 break;
2900         case RTL871X_HOSTAPD_SET_WPS_BEACON:
2901                 ret = rtw_set_wps_beacon(dev, param, p->length);
2902                 break;
2903         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
2904                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
2905                 break;
2906         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
2907                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
2908                 break;
2909         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
2910                 ret = rtw_set_hidden_ssid(dev, param, p->length);
2911                 break;
2912         case RTL871X_HOSTAPD_GET_INFO_STA:
2913                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
2914                 break;
2915         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
2916                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
2917                 break;
2918         case RTL871X_HOSTAPD_ACL_ADD_STA:
2919                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
2920                 break;
2921         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
2922                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
2923                 break;
2924         default:
2925                 DBG_88E("Unknown hostapd request: %d\n", param->cmd);
2926                 ret = -EOPNOTSUPP;
2927                 break;
2928         }
2929
2930         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2931                 ret = -EFAULT;
2932         kfree(param);
2933 out:
2934         return ret;
2935 }
2936 #endif
2937
2938 #include <rtw_android.h>
2939 static int rtw_wx_set_priv(struct net_device *dev,
2940                                 struct iw_request_info *info,
2941                                 union iwreq_data *awrq,
2942                                 char *extra)
2943 {
2944         int ret = 0;
2945         int len = 0;
2946         char *ext;
2947         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2948         struct iw_point *dwrq = (struct iw_point *)awrq;
2949
2950         if (dwrq->length == 0)
2951                 return -EFAULT;
2952
2953         len = dwrq->length;
2954         ext = vmalloc(len);
2955         if (!ext)
2956                 return -ENOMEM;
2957
2958         if (copy_from_user(ext, dwrq->pointer, len)) {
2959                 vfree(ext);
2960                 return -EFAULT;
2961         }
2962
2963         /* added for wps2.0 @20110524 */
2964         if (dwrq->flags == 0x8766 && len > 8) {
2965                 u32 cp_sz;
2966                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2967                 u8 *probereq_wpsie = ext;
2968                 int probereq_wpsie_len = len;
2969                 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2970
2971                 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
2972                     (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
2973                         cp_sz = min(probereq_wpsie_len, MAX_WPS_IE_LEN);
2974
2975                         pmlmepriv->wps_probe_req_ie_len = 0;
2976                         kfree(pmlmepriv->wps_probe_req_ie);
2977                         pmlmepriv->wps_probe_req_ie = NULL;
2978
2979                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
2980                         if (pmlmepriv->wps_probe_req_ie == NULL) {
2981                                 pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2982                                 ret =  -EINVAL;
2983                                 goto FREE_EXT;
2984                         }
2985                         memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
2986                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
2987                 }
2988                 goto FREE_EXT;
2989         }
2990
2991         if (len >= WEXT_CSCAN_HEADER_SIZE &&
2992             !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
2993                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
2994                 goto FREE_EXT;
2995         }
2996
2997 FREE_EXT:
2998
2999         vfree(ext);
3000
3001         return ret;
3002 }
3003
3004 static iw_handler rtw_handlers[] = {
3005         NULL,                                   /* SIOCSIWCOMMIT */
3006         rtw_wx_get_name,                /* SIOCGIWNAME */
3007         dummy,                                  /* SIOCSIWNWID */
3008         dummy,                                  /* SIOCGIWNWID */
3009         rtw_wx_set_freq,                /* SIOCSIWFREQ */
3010         rtw_wx_get_freq,                /* SIOCGIWFREQ */
3011         rtw_wx_set_mode,                /* SIOCSIWMODE */
3012         rtw_wx_get_mode,                /* SIOCGIWMODE */
3013         dummy,                                  /* SIOCSIWSENS */
3014         rtw_wx_get_sens,                /* SIOCGIWSENS */
3015         NULL,                                   /* SIOCSIWRANGE */
3016         rtw_wx_get_range,               /* SIOCGIWRANGE */
3017         rtw_wx_set_priv,                /* SIOCSIWPRIV */
3018         NULL,                                   /* SIOCGIWPRIV */
3019         NULL,                                   /* SIOCSIWSTATS */
3020         NULL,                                   /* SIOCGIWSTATS */
3021         dummy,                                  /* SIOCSIWSPY */
3022         dummy,                                  /* SIOCGIWSPY */
3023         NULL,                                   /* SIOCGIWTHRSPY */
3024         NULL,                                   /* SIOCWIWTHRSPY */
3025         rtw_wx_set_wap,         /* SIOCSIWAP */
3026         rtw_wx_get_wap,         /* SIOCGIWAP */
3027         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
3028         dummy,                                  /* SIOCGIWAPLIST -- depricated */
3029         rtw_wx_set_scan,                /* SIOCSIWSCAN */
3030         rtw_wx_get_scan,                /* SIOCGIWSCAN */
3031         rtw_wx_set_essid,               /* SIOCSIWESSID */
3032         rtw_wx_get_essid,               /* SIOCGIWESSID */
3033         dummy,                                  /* SIOCSIWNICKN */
3034         rtw_wx_get_nick,                /* SIOCGIWNICKN */
3035         NULL,                                   /* -- hole -- */
3036         NULL,                                   /* -- hole -- */
3037         rtw_wx_set_rate,                /* SIOCSIWRATE */
3038         rtw_wx_get_rate,                /* SIOCGIWRATE */
3039         rtw_wx_set_rts,                 /* SIOCSIWRTS */
3040         rtw_wx_get_rts,                 /* SIOCGIWRTS */
3041         rtw_wx_set_frag,                /* SIOCSIWFRAG */
3042         rtw_wx_get_frag,                /* SIOCGIWFRAG */
3043         dummy,                                  /* SIOCSIWTXPOW */
3044         dummy,                                  /* SIOCGIWTXPOW */
3045         dummy,                                  /* SIOCSIWRETRY */
3046         rtw_wx_get_retry,               /* SIOCGIWRETRY */
3047         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
3048         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
3049         dummy,                                  /* SIOCSIWPOWER */
3050         rtw_wx_get_power,               /* SIOCGIWPOWER */
3051         NULL,                                   /*---hole---*/
3052         NULL,                                   /*---hole---*/
3053         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
3054         NULL,                                   /* SIOCGWGENIE */
3055         rtw_wx_set_auth,                /* SIOCSIWAUTH */
3056         NULL,                                   /* SIOCGIWAUTH */
3057         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
3058         NULL,                                   /* SIOCGIWENCODEEXT */
3059         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
3060         NULL,                                   /*---hole---*/
3061 };
3062
3063 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
3064 {
3065         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3066         struct iw_statistics *piwstats = &padapter->iwstats;
3067         int tmp_level = 0;
3068         int tmp_qual = 0;
3069         int tmp_noise = 0;
3070
3071         if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3072                 piwstats->qual.qual = 0;
3073                 piwstats->qual.level = 0;
3074                 piwstats->qual.noise = 0;
3075         } else {
3076                 tmp_level = padapter->recvpriv.signal_strength;
3077                 tmp_qual = padapter->recvpriv.signal_qual;
3078                 tmp_noise = padapter->recvpriv.noise;
3079
3080                 piwstats->qual.level = tmp_level;
3081                 piwstats->qual.qual = tmp_qual;
3082                 piwstats->qual.noise = tmp_noise;
3083         }
3084         piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
3085         return &padapter->iwstats;
3086 }
3087
3088 struct iw_handler_def rtw_handlers_def = {
3089         .standard = rtw_handlers,
3090         .num_standard = ARRAY_SIZE(rtw_handlers),
3091         .get_wireless_stats = rtw_get_wireless_stats,
3092 };
3093
3094 #include <rtw_android.h>
3095 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3096 {
3097         struct iwreq *wrq = (struct iwreq *)rq;
3098         int ret = 0;
3099
3100         switch (cmd) {
3101         case RTL_IOCTL_WPA_SUPPLICANT:
3102                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
3103                 break;
3104 #ifdef CONFIG_88EU_AP_MODE
3105         case RTL_IOCTL_HOSTAPD:
3106                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
3107                 break;
3108 #endif /*  CONFIG_88EU_AP_MODE */
3109         case (SIOCDEVPRIVATE+1):
3110                 ret = rtw_android_priv_cmd(dev, rq, cmd);
3111                 break;
3112         default:
3113                 ret = -EOPNOTSUPP;
3114                 break;
3115         }
3116         return ret;
3117 }