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