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