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