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