staging: rtl8723bs: remove unused macros
[linux-2.6-microblaze.git] / drivers / staging / rtl8723bs / os_dep / ioctl_linux.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7
8 #include <linux/etherdevice.h>
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11 #include <rtw_mp.h>
12 #include <hal_btcoex.h>
13 #include <linux/jiffies.h>
14 #include <linux/kernel.h>
15
16 #define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV+30)
17
18 #define SCAN_ITEM_SIZE 768
19 #define MAX_CUSTOM_LEN 64
20 #define RATE_COUNT 4
21
22 /*  combo scan */
23 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
24 #define WEXT_CSCAN_HEADER_SIZE          12
25 #define WEXT_CSCAN_SSID_SECTION         'S'
26 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
27 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
28 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
29 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
30 #define WEXT_CSCAN_TYPE_SECTION         'T'
31
32 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
33         6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
34
35 void indicate_wx_scan_complete_event(struct adapter *padapter)
36 {
37         union iwreq_data wrqu;
38
39         memset(&wrqu, 0, sizeof(union iwreq_data));
40 }
41
42
43 void rtw_indicate_wx_assoc_event(struct adapter *padapter)
44 {
45         union iwreq_data wrqu;
46         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
47         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
48         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
49         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
50
51         memset(&wrqu, 0, sizeof(union iwreq_data));
52
53         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
54
55         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
56                 memcpy(wrqu.ap_addr.sa_data, pnetwork->mac_address, ETH_ALEN);
57         else
58                 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.mac_address, ETH_ALEN);
59
60         netdev_dbg(padapter->pnetdev, "assoc success\n");
61 }
62
63 void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
64 {
65         union iwreq_data wrqu;
66
67         memset(&wrqu, 0, sizeof(union iwreq_data));
68
69         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
70         eth_zero_addr(wrqu.ap_addr.sa_data);
71 }
72
73 static char *translate_scan(struct adapter *padapter,
74                                 struct iw_request_info *info, struct wlan_network *pnetwork,
75                                 char *start, char *stop)
76 {
77         struct iw_event iwe;
78         u16 cap;
79         u32 ht_ielen = 0;
80         char *custom = NULL;
81         char *p;
82         u16 max_rate = 0, rate, ht_cap = false, vht_cap = false;
83         u32 i = 0;
84         u8 bw_40MHz = 0, short_GI = 0;
85         u16 mcs_rate = 0, vht_data_rate = 0;
86         u8 ie_offset = (pnetwork->network.reserved[0] == 2 ? 0 : 12);
87         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
88         u8 ss, sq;
89
90         /*  AP MAC address  */
91         iwe.cmd = SIOCGIWAP;
92         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
93
94         memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.mac_address, ETH_ALEN);
95         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
96
97         /* Add the ESSID */
98         iwe.cmd = SIOCGIWESSID;
99         iwe.u.data.flags = 1;
100         iwe.u.data.length = min((u16)pnetwork->network.ssid.ssid_length, (u16)32);
101         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
102
103         /* parsing HT_CAP_IE */
104         if (pnetwork->network.reserved[0] == 2) { /*  Probe Request */
105                 p = rtw_get_ie(&pnetwork->network.ies[0], WLAN_EID_HT_CAPABILITY, &ht_ielen, pnetwork->network.ie_length);
106         } else {
107                 p = rtw_get_ie(&pnetwork->network.ies[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pnetwork->network.ie_length-12);
108         }
109         if (p && ht_ielen > 0) {
110                 struct ieee80211_ht_cap *pht_capie;
111                 ht_cap = true;
112                 pht_capie = (struct ieee80211_ht_cap *)(p+2);
113                 memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
114                 bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
115                 short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
116         }
117
118         /* Add the protocol name */
119         iwe.cmd = SIOCGIWNAME;
120         if (rtw_is_cckratesonly_included((u8 *)&pnetwork->network.supported_rates)) {
121                 if (ht_cap)
122                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
123                 else
124                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
125         } else if (rtw_is_cckrates_included((u8 *)&pnetwork->network.supported_rates)) {
126                 if (ht_cap)
127                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
128                 else
129                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
130         } else {
131                 if (pnetwork->network.configuration.ds_config <= 14) {
132                         if (ht_cap)
133                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
134                         else
135                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
136                 }
137         }
138
139         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
140
141           /* Add mode */
142         if (pnetwork->network.reserved[0] == 2) { /*  Probe Request */
143                 cap = 0;
144         } else {
145                 __le16 le_tmp;
146
147                 iwe.cmd = SIOCGIWMODE;
148                 memcpy((u8 *)&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
149                 cap = le16_to_cpu(le_tmp);
150         }
151
152         if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_ESS)) {
153                 if (cap & WLAN_CAPABILITY_ESS)
154                         iwe.u.mode = IW_MODE_MASTER;
155                 else
156                         iwe.u.mode = IW_MODE_ADHOC;
157
158                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
159         }
160
161         if (pnetwork->network.configuration.ds_config < 1)
162                 pnetwork->network.configuration.ds_config = 1;
163
164          /* Add frequency/channel */
165         iwe.cmd = SIOCGIWFREQ;
166         iwe.u.freq.m = rtw_ch2freq(pnetwork->network.configuration.ds_config) * 100000;
167         iwe.u.freq.e = 1;
168         iwe.u.freq.i = pnetwork->network.configuration.ds_config;
169         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
170
171         /* Add encryption capability */
172         iwe.cmd = SIOCGIWENCODE;
173         if (cap & WLAN_CAPABILITY_PRIVACY)
174                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
175         else
176                 iwe.u.data.flags = IW_ENCODE_DISABLED;
177         iwe.u.data.length = 0;
178         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
179
180         /*Add basic and extended rates */
181         max_rate = 0;
182         custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC);
183         if (!custom)
184                 return start;
185         p = custom;
186         p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
187         while (pnetwork->network.supported_rates[i] != 0) {
188                 rate = pnetwork->network.supported_rates[i]&0x7F;
189                 if (rate > max_rate)
190                         max_rate = rate;
191                 p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
192                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
193                 i++;
194         }
195
196         if (vht_cap) {
197                 max_rate = vht_data_rate;
198         } else if (ht_cap) {
199                 if (mcs_rate & 0x8000) /* MCS15 */
200                         max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
201                 else /* default MCS7 */
202                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
203
204                 max_rate = max_rate*2;/* Mbps/2; */
205         }
206
207         iwe.cmd = SIOCGIWRATE;
208         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
209         iwe.u.bitrate.value = max_rate * 500000;
210         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
211
212         /* parsing WPA/WPA2 IE */
213         if (pnetwork->network.reserved[0] != 2) { /*  Probe Request */
214                 u8 *buf;
215                 u8 wpa_ie[255], rsn_ie[255];
216                 u16 wpa_len = 0, rsn_len = 0;
217                 u8 *p;
218                 rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
219
220                 buf = kzalloc(MAX_WPA_IE_LEN*2, GFP_ATOMIC);
221                 if (!buf)
222                         return start;
223                 if (wpa_len > 0) {
224                         p = buf;
225                         p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf), "wpa_ie =");
226                         for (i = 0; i < wpa_len; i++)
227                                 p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf),
228                                                 "%02x", wpa_ie[i]);
229
230                         if (wpa_len > 100) {
231                                 printk("-----------------Len %d----------------\n", wpa_len);
232                                 for (i = 0; i < wpa_len; i++)
233                                         printk("%02x ", wpa_ie[i]);
234                                 printk("\n");
235                                 printk("-----------------Len %d----------------\n", wpa_len);
236                         }
237
238                         memset(&iwe, 0, sizeof(iwe));
239                         iwe.cmd = IWEVCUSTOM;
240                         iwe.u.data.length = strlen(buf);
241                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
242
243                         memset(&iwe, 0, sizeof(iwe));
244                         iwe.cmd = IWEVGENIE;
245                         iwe.u.data.length = wpa_len;
246                         start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
247                 }
248                 if (rsn_len > 0) {
249                         p = buf;
250                         memset(buf, 0, MAX_WPA_IE_LEN*2);
251                         p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf), "rsn_ie =");
252                         for (i = 0; i < rsn_len; i++)
253                                 p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf),
254                                                 "%02x", rsn_ie[i]);
255                         memset(&iwe, 0, sizeof(iwe));
256                         iwe.cmd = IWEVCUSTOM;
257                         iwe.u.data.length = strlen(buf);
258                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
259
260                         memset(&iwe, 0, sizeof(iwe));
261                         iwe.cmd = IWEVGENIE;
262                         iwe.u.data.length = rsn_len;
263                         start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
264                 }
265                 kfree(buf);
266         }
267
268         { /* parsing WPS IE */
269                 uint cnt = 0, total_ielen;
270                 u8 *wpsie_ptr = NULL;
271                 uint wps_ielen = 0;
272
273                 u8 *ie_ptr;
274                 total_ielen = pnetwork->network.ie_length - ie_offset;
275
276                 if (pnetwork->network.reserved[0] == 2) { /*  Probe Request */
277                         ie_ptr = pnetwork->network.ies;
278                         total_ielen = pnetwork->network.ie_length;
279                 } else {    /*  Beacon or Probe Respones */
280                         ie_ptr = pnetwork->network.ies + _FIXED_IE_LENGTH_;
281                         total_ielen = pnetwork->network.ie_length - _FIXED_IE_LENGTH_;
282                 }
283
284                 while (cnt < total_ielen) {
285                         if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
286                                 wpsie_ptr = &ie_ptr[cnt];
287                                 iwe.cmd = IWEVGENIE;
288                                 iwe.u.data.length = (u16)wps_ielen;
289                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
290                         }
291                         cnt += ie_ptr[cnt + 1] + 2; /* goto next */
292                 }
293         }
294
295         /* Add quality statistics */
296         iwe.cmd = IWEVQUAL;
297         iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
298                 | IW_QUAL_NOISE_INVALID;
299
300         if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
301                 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
302                 ss = padapter->recvpriv.signal_strength;
303                 sq = padapter->recvpriv.signal_qual;
304         } else {
305                 ss = pnetwork->network.phy_info.signal_strength;
306                 sq = pnetwork->network.phy_info.signal_quality;
307         }
308
309
310         iwe.u.qual.level = (u8)ss;/*  */
311
312         iwe.u.qual.qual = (u8)sq;   /*  signal quality */
313
314         iwe.u.qual.noise = 0; /*  noise level */
315
316         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
317
318         {
319                 u8 *buf;
320                 u8 *pos;
321
322                 buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
323                 if (!buf)
324                         goto exit;
325
326                 pos = pnetwork->network.reserved;
327                 memset(&iwe, 0, sizeof(iwe));
328                 iwe.cmd = IWEVCUSTOM;
329                 iwe.u.data.length = scnprintf(buf, MAX_WPA_IE_LEN, "fm =%02X%02X", pos[1], pos[0]);
330                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
331                 kfree(buf);
332         }
333 exit:
334         kfree(custom);
335
336         return start;
337 }
338
339 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
340 {
341         struct adapter *padapter = rtw_netdev_priv(dev);
342         int ret = 0;
343
344         if ((value & IW_AUTH_ALG_SHARED_KEY) && (value & IW_AUTH_ALG_OPEN_SYSTEM)) {
345                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
346                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
347                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
348         } else if (value & IW_AUTH_ALG_SHARED_KEY)      {
349                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
350
351                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
352                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
353         } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
354                 /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
355                 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
356                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
357                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
358                 }
359         } else {
360                 ret = -EINVAL;
361         }
362
363         return ret;
364
365 }
366
367 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
368 {
369         int ret = 0;
370         u32 wep_key_idx, wep_key_len, wep_total_len;
371         struct ndis_802_11_wep   *pwep = NULL;
372         struct adapter *padapter = rtw_netdev_priv(dev);
373         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
374         struct security_priv *psecuritypriv = &padapter->securitypriv;
375
376         param->u.crypt.err = 0;
377         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
378
379         if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
380                 ret =  -EINVAL;
381                 goto exit;
382         }
383
384         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
385             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
386             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
387                 if (param->u.crypt.idx >= WEP_KEYS ||
388                     param->u.crypt.idx >= BIP_MAX_KEYID) {
389                         ret = -EINVAL;
390                         goto exit;
391                 }
392         } else {
393                 {
394                         ret = -EINVAL;
395                         goto exit;
396                 }
397         }
398
399         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
400
401                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
402                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
403                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
404
405                 wep_key_idx = param->u.crypt.idx;
406                 wep_key_len = param->u.crypt.key_len;
407
408                 if (wep_key_idx > WEP_KEYS)
409                         return -EINVAL;
410
411                 if (wep_key_len > 0) {
412                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
413                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
414                         pwep = kzalloc(wep_total_len, GFP_KERNEL);
415                         if (!pwep) {
416                                 ret = -ENOMEM;
417                                 goto exit;
418                         }
419
420                         pwep->key_length = wep_key_len;
421                         pwep->length = wep_total_len;
422
423                         if (wep_key_len == 13) {
424                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
425                                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
426                         }
427                 } else {
428                         ret = -EINVAL;
429                         goto exit;
430                 }
431
432                 pwep->key_index = wep_key_idx;
433                 pwep->key_index |= 0x80000000;
434
435                 memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
436
437                 if (param->u.crypt.set_tx) {
438                         if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
439                                 ret = -EOPNOTSUPP;
440                 } else {
441                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
442                         /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */
443
444                         if (wep_key_idx >= WEP_KEYS) {
445                                 ret = -EOPNOTSUPP;
446                                 goto exit;
447                         }
448
449                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
450                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
451                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
452                 }
453
454                 goto exit;
455         }
456
457         if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
458                 struct sta_info *psta, *pbcmc_sta;
459                 struct sta_priv *pstapriv = &padapter->stapriv;
460
461                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
462                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
463                         if (psta == NULL) {
464                                 /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
465                         } else {
466                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
467                                 if (strcmp(param->u.crypt.alg, "none") != 0)
468                                         psta->ieee8021x_blocked = false;
469
470                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
471                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
472                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
473                                 }
474
475                                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
476                                         memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
477
478                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
479                                                 /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
480                                                 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
481                                                 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
482
483                                                 padapter->securitypriv.busetkipkey = false;
484                                                 /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
485                                         }
486
487                                         rtw_setstakey_cmd(padapter, psta, true, true);
488                                 } else { /* group key */
489                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
490                                                 memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
491                                                 /* only TKIP group key need to install this */
492                                                 if (param->u.crypt.key_len > 16) {
493                                                         memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
494                                                         memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
495                                                 }
496                                                 padapter->securitypriv.binstallGrpkey = true;
497
498                                                 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
499
500                                                 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
501                                         } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
502                                                 /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
503                                                 /* save the IGTK key, length 16 bytes */
504                                                 memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
505                                                 /*printk("IGTK key below:\n");
506                                                 for (no = 0;no<16;no++)
507                                                         printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
508                                                 printk("\n");*/
509                                                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
510                                                 padapter->securitypriv.binstallBIPkey = true;
511                                         }
512                                 }
513                         }
514
515                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
516                         if (pbcmc_sta == NULL) {
517                                 /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
518                         } else {
519                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
520                                 if (strcmp(param->u.crypt.alg, "none") != 0)
521                                         pbcmc_sta->ieee8021x_blocked = false;
522
523                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
524                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
525                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
526                                 }
527                         }
528                 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
529                         /* adhoc mode */
530                 }
531         }
532
533 exit:
534
535         kfree(pwep);
536         return ret;
537 }
538
539 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
540 {
541         u8 *buf = NULL;
542         int group_cipher = 0, pairwise_cipher = 0;
543         int ret = 0;
544         u8 null_addr[] = {0, 0, 0, 0, 0, 0};
545
546         if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
547                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
548                 if (pie == NULL)
549                         return ret;
550                 else
551                         return -EINVAL;
552         }
553
554         if (ielen) {
555                 buf = rtw_zmalloc(ielen);
556                 if (buf == NULL) {
557                         ret =  -ENOMEM;
558                         goto exit;
559                 }
560
561                 memcpy(buf, pie, ielen);
562
563                 if (ielen < RSN_HEADER_LEN) {
564                         ret  = -1;
565                         goto exit;
566                 }
567
568                 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
569                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
570                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
571                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
572                 }
573
574                 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
575                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
576                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
577                         memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
578                 }
579
580                 if (group_cipher == 0)
581                         group_cipher = WPA_CIPHER_NONE;
582                 if (pairwise_cipher == 0)
583                         pairwise_cipher = WPA_CIPHER_NONE;
584
585                 switch (group_cipher) {
586                 case WPA_CIPHER_NONE:
587                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
588                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
589                         break;
590                 case WPA_CIPHER_WEP40:
591                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
592                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
593                         break;
594                 case WPA_CIPHER_TKIP:
595                         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
596                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
597                         break;
598                 case WPA_CIPHER_CCMP:
599                         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
600                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
601                         break;
602                 case WPA_CIPHER_WEP104:
603                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
604                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
605                         break;
606                 }
607
608                 switch (pairwise_cipher) {
609                 case WPA_CIPHER_NONE:
610                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
611                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
612                         break;
613                 case WPA_CIPHER_WEP40:
614                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
615                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
616                         break;
617                 case WPA_CIPHER_TKIP:
618                         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
619                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
620                         break;
621                 case WPA_CIPHER_CCMP:
622                         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
623                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
624                         break;
625                 case WPA_CIPHER_WEP104:
626                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
627                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
628                         break;
629                 }
630
631                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
632                 {/* set wps_ie */
633                         u16 cnt = 0;
634                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
635
636                         while (cnt < ielen) {
637                                 eid = buf[cnt];
638
639                                 if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
640                                         padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN;
641
642                                         memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
643
644                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
645
646                                         cnt += buf[cnt+1]+2;
647
648                                         break;
649                                 } else {
650                                         cnt += buf[cnt+1]+2; /* goto next */
651                                 }
652                         }
653                 }
654         }
655
656         /* TKIP and AES disallow multicast packets until installing group key */
657         if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
658                 || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
659                 || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
660                 /* WPS open need to enable multicast */
661                 /*  check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
662                 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
663
664 exit:
665
666         kfree(buf);
667
668         return ret;
669 }
670
671 static int rtw_wx_get_name(struct net_device *dev,
672                              struct iw_request_info *info,
673                              union iwreq_data *wrqu, char *extra)
674 {
675         struct adapter *padapter = rtw_netdev_priv(dev);
676         u32 ht_ielen = 0;
677         char *p;
678         u8 ht_cap = false;
679         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
680         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
681         NDIS_802_11_RATES_EX *prates = NULL;
682
683         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
684                 /* parsing HT_CAP_IE */
685                 p = rtw_get_ie(&pcur_bss->ies[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pcur_bss->ie_length-12);
686                 if (p && ht_ielen > 0)
687                         ht_cap = true;
688
689                 prates = &pcur_bss->supported_rates;
690
691                 if (rtw_is_cckratesonly_included((u8 *)prates)) {
692                         if (ht_cap)
693                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
694                         else
695                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
696                 } else if (rtw_is_cckrates_included((u8 *)prates)) {
697                         if (ht_cap)
698                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
699                         else
700                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
701                 } else {
702                         if (pcur_bss->configuration.ds_config <= 14) {
703                                 if (ht_cap)
704                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
705                                 else
706                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
707                         }
708                 }
709         } else {
710                 /* prates = &padapter->registrypriv.dev_network.supported_rates; */
711                 /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
712                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
713         }
714         return 0;
715 }
716
717 static int rtw_wx_set_freq(struct net_device *dev,
718                              struct iw_request_info *info,
719                              union iwreq_data *wrqu, char *extra)
720 {
721         return 0;
722 }
723
724 static int rtw_wx_get_freq(struct net_device *dev,
725                              struct iw_request_info *info,
726                              union iwreq_data *wrqu, char *extra)
727 {
728         struct adapter *padapter = rtw_netdev_priv(dev);
729         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
730         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
731
732         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
733                 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->configuration.ds_config-1] * 100000; */
734                 wrqu->freq.m = rtw_ch2freq(pcur_bss->configuration.ds_config) * 100000;
735                 wrqu->freq.e = 1;
736                 wrqu->freq.i = pcur_bss->configuration.ds_config;
737
738         } else {
739                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
740                 wrqu->freq.e = 1;
741                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
742         }
743
744         return 0;
745 }
746
747 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
748                              union iwreq_data *wrqu, char *b)
749 {
750         struct adapter *padapter = rtw_netdev_priv(dev);
751         enum ndis_802_11_network_infrastructure networkType;
752         int ret = 0;
753
754         if (_FAIL == rtw_pwr_wakeup(padapter)) {
755                 ret = -EPERM;
756                 goto exit;
757         }
758
759         if (!padapter->hw_init_completed) {
760                 ret = -EPERM;
761                 goto exit;
762         }
763
764         switch (wrqu->mode) {
765         case IW_MODE_AUTO:
766                 networkType = Ndis802_11AutoUnknown;
767                 break;
768         case IW_MODE_ADHOC:
769                 networkType = Ndis802_11IBSS;
770                 break;
771         case IW_MODE_MASTER:
772                 networkType = Ndis802_11APMode;
773                 /* rtw_setopmode_cmd(padapter, networkType, true); */
774                 break;
775         case IW_MODE_INFRA:
776                 networkType = Ndis802_11Infrastructure;
777                 break;
778         default:
779                 ret = -EINVAL;
780                 goto exit;
781         }
782
783 /*
784         if (Ndis802_11APMode == networkType)
785         {
786                 rtw_setopmode_cmd(padapter, networkType, true);
787         }
788         else
789         {
790                 rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown, true);
791         }
792 */
793
794         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
795
796                 ret = -EPERM;
797                 goto exit;
798
799         }
800
801         rtw_setopmode_cmd(padapter, networkType, true);
802
803 exit:
804         return ret;
805 }
806
807 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
808                              union iwreq_data *wrqu, char *b)
809 {
810         struct adapter *padapter = rtw_netdev_priv(dev);
811         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
812
813         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
814                 wrqu->mode = IW_MODE_INFRA;
815         } else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
816                        (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
817                 wrqu->mode = IW_MODE_ADHOC;
818         } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
819                 wrqu->mode = IW_MODE_MASTER;
820         } else {
821                 wrqu->mode = IW_MODE_AUTO;
822         }
823         return 0;
824 }
825
826
827 static int rtw_wx_set_pmkid(struct net_device *dev,
828                              struct iw_request_info *a,
829                              union iwreq_data *wrqu, char *extra)
830 {
831         struct adapter *padapter = rtw_netdev_priv(dev);
832         u8          j, blInserted = false;
833         int         intReturn = false;
834         struct security_priv *psecuritypriv = &padapter->securitypriv;
835         struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
836         u8     strZeroMacAddress[ETH_ALEN] = { 0x00 };
837         u8     strIssueBssid[ETH_ALEN] = { 0x00 };
838
839         /*
840         There are the BSSID information in the bssid.sa_data array.
841         If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
842         If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
843         If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
844         */
845
846         memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
847         if (pPMK->cmd == IW_PMKSA_ADD) {
848                 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
849                         return intReturn;
850                 else
851                     intReturn = true;
852
853                 blInserted = false;
854
855                 /* overwrite PMKID */
856                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
857                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
858
859                                 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
860                                 psecuritypriv->PMKIDList[j].bUsed = true;
861                                 psecuritypriv->PMKIDIndex = j+1;
862                                 blInserted = true;
863                                 break;
864                         }
865                 }
866
867                 if (!blInserted) {
868
869                     memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
870                     memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
871
872                     psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
873                     psecuritypriv->PMKIDIndex++;
874                     if (psecuritypriv->PMKIDIndex == 16)
875                         psecuritypriv->PMKIDIndex = 0;
876                 }
877         } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
878                 intReturn = true;
879                 for (j = 0; j < NUM_PMKID_CACHE; j++) {
880                         if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
881                                 /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
882                                 eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
883                                 psecuritypriv->PMKIDList[j].bUsed = false;
884                                 break;
885                         }
886                 }
887         } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
888                 memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
889                 psecuritypriv->PMKIDIndex = 0;
890                 intReturn = true;
891         }
892         return intReturn;
893 }
894
895 static int rtw_wx_get_sens(struct net_device *dev,
896                              struct iw_request_info *info,
897                              union iwreq_data *wrqu, char *extra)
898 {
899         {
900                 wrqu->sens.value = 0;
901                 wrqu->sens.fixed = 0;   /* no auto select */
902                 wrqu->sens.disabled = 1;
903         }
904         return 0;
905 }
906
907 static int rtw_wx_get_range(struct net_device *dev,
908                                 struct iw_request_info *info,
909                                 union iwreq_data *wrqu, char *extra)
910 {
911         struct iw_range *range = (struct iw_range *)extra;
912         struct adapter *padapter = rtw_netdev_priv(dev);
913         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
914
915         u16 val;
916         int i;
917
918         wrqu->data.length = sizeof(*range);
919         memset(range, 0, sizeof(*range));
920
921         /* Let's try to keep this struct in the same order as in
922          * linux/include/wireless.h
923          */
924
925         /* TODO: See what values we can set, and remove the ones we can't
926          * set, or fill them with some default data.
927          */
928
929         /* ~5 Mb/s real (802.11b) */
930         range->throughput = 5 * 1000 * 1000;
931
932         /* signal level threshold range */
933
934         /* percent values between 0 and 100. */
935         range->max_qual.qual = 100;
936         range->max_qual.level = 100;
937         range->max_qual.noise = 100;
938         range->max_qual.updated = 7; /* Updated all three */
939
940
941         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
942         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
943         range->avg_qual.level = 256 - 78;
944         range->avg_qual.noise = 0;
945         range->avg_qual.updated = 7; /* Updated all three */
946
947         range->num_bitrates = RATE_COUNT;
948
949         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
950                 range->bitrate[i] = rtw_rates[i];
951
952         range->min_frag = MIN_FRAG_THRESHOLD;
953         range->max_frag = MAX_FRAG_THRESHOLD;
954
955         range->pm_capa = 0;
956
957         range->we_version_compiled = WIRELESS_EXT;
958         range->we_version_source = 16;
959
960         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
961
962                 /*  Include only legal frequencies for some countries */
963                 if (pmlmeext->channel_set[i].ChannelNum != 0) {
964                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
965                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
966                         range->freq[val].e = 1;
967                         val++;
968                 }
969
970                 if (val == IW_MAX_FREQUENCIES)
971                         break;
972         }
973
974         range->num_channels = val;
975         range->num_frequency = val;
976
977 /*  Commented by Albert 2009/10/13 */
978 /*  The following code will proivde the security capability to network manager. */
979 /*  If the driver doesn't provide this capability to network manager, */
980 /*  the WPA/WPA2 routers can't be chosen in the network manager. */
981
982 /*
983 #define IW_SCAN_CAPA_NONE               0x00
984 #define IW_SCAN_CAPA_ESSID              0x01
985 #define IW_SCAN_CAPA_BSSID              0x02
986 #define IW_SCAN_CAPA_CHANNEL    0x04
987 #define IW_SCAN_CAPA_MODE               0x08
988 #define IW_SCAN_CAPA_RATE               0x10
989 #define IW_SCAN_CAPA_TYPE               0x20
990 #define IW_SCAN_CAPA_TIME               0x40
991 */
992
993         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
994                           IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
995
996         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_BSSID |
997                                         IW_SCAN_CAPA_CHANNEL | IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
998
999         return 0;
1000 }
1001
1002 /* set bssid flow */
1003 /* s1. rtw_set_802_11_infrastructure_mode() */
1004 /* s2. rtw_set_802_11_authentication_mode() */
1005 /* s3. set_802_11_encryption_mode() */
1006 /* s4. rtw_set_802_11_bssid() */
1007 static int rtw_wx_set_wap(struct net_device *dev,
1008                          struct iw_request_info *info,
1009                          union iwreq_data *awrq,
1010                          char *extra)
1011 {
1012         uint ret = 0;
1013         struct adapter *padapter = rtw_netdev_priv(dev);
1014         struct sockaddr *temp = (struct sockaddr *)awrq;
1015         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1016         struct list_head        *phead;
1017         u8 *dst_bssid, *src_bssid;
1018         struct __queue  *queue  = &(pmlmepriv->scanned_queue);
1019         struct  wlan_network    *pnetwork = NULL;
1020         enum ndis_802_11_authentication_mode    authmode;
1021
1022         rtw_ps_deny(padapter, PS_DENY_JOIN);
1023         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1024                 ret = -1;
1025                 goto exit;
1026         }
1027
1028         if (!padapter->bup) {
1029                 ret = -1;
1030                 goto exit;
1031         }
1032
1033
1034         if (temp->sa_family != ARPHRD_ETHER) {
1035                 ret = -EINVAL;
1036                 goto exit;
1037         }
1038
1039         authmode = padapter->securitypriv.ndisauthtype;
1040         spin_lock_bh(&queue->lock);
1041         phead = get_list_head(queue);
1042         list_for_each(pmlmepriv->pscanned, phead) {
1043                 pnetwork = list_entry(pmlmepriv->pscanned,
1044                                       struct wlan_network, list);
1045
1046                 dst_bssid = pnetwork->network.mac_address;
1047
1048                 src_bssid = temp->sa_data;
1049
1050                 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1051                         if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.infrastructure_mode)) {
1052                                 ret = -1;
1053                                 spin_unlock_bh(&queue->lock);
1054                                 goto exit;
1055                         }
1056                         break;
1057                 }
1058
1059         }
1060         spin_unlock_bh(&queue->lock);
1061
1062         rtw_set_802_11_authentication_mode(padapter, authmode);
1063         /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1064         if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1065                 ret = -1;
1066                 goto exit;
1067         }
1068
1069 exit:
1070
1071         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1072
1073         return ret;
1074 }
1075
1076 static int rtw_wx_get_wap(struct net_device *dev,
1077                             struct iw_request_info *info,
1078                             union iwreq_data *wrqu, char *extra)
1079 {
1080
1081         struct adapter *padapter = rtw_netdev_priv(dev);
1082         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1083         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1084
1085         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1086
1087         eth_zero_addr(wrqu->ap_addr.sa_data);
1088
1089         if  (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1090                         ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
1091                         ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true)) {
1092                 memcpy(wrqu->ap_addr.sa_data, pcur_bss->mac_address, ETH_ALEN);
1093         } else {
1094                 eth_zero_addr(wrqu->ap_addr.sa_data);
1095         }
1096
1097         return 0;
1098 }
1099
1100 static int rtw_wx_set_mlme(struct net_device *dev,
1101                              struct iw_request_info *info,
1102                              union iwreq_data *wrqu, char *extra)
1103 {
1104         int ret = 0;
1105         struct adapter *padapter = rtw_netdev_priv(dev);
1106         struct iw_mlme *mlme = (struct iw_mlme *)extra;
1107
1108
1109         if (mlme == NULL)
1110                 return -1;
1111
1112         switch (mlme->cmd) {
1113         case IW_MLME_DEAUTH:
1114                 if (!rtw_set_802_11_disassociate(padapter))
1115                         ret = -1;
1116                 break;
1117         case IW_MLME_DISASSOC:
1118                 if (!rtw_set_802_11_disassociate(padapter))
1119                         ret = -1;
1120                 break;
1121         default:
1122                 return -EOPNOTSUPP;
1123         }
1124
1125         return ret;
1126 }
1127
1128 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1129                              union iwreq_data *wrqu, char *extra)
1130 {
1131         u8 _status = false;
1132         int ret = 0;
1133         struct adapter *padapter = rtw_netdev_priv(dev);
1134         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1135         struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1136
1137         rtw_ps_deny(padapter, PS_DENY_SCAN);
1138         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1139                 ret = -1;
1140                 goto exit;
1141         }
1142
1143         if (padapter->bDriverStopped) {
1144                 ret = -1;
1145                 goto exit;
1146         }
1147
1148         if (!padapter->bup) {
1149                 ret = -1;
1150                 goto exit;
1151         }
1152
1153         if (!padapter->hw_init_completed) {
1154                 ret = -1;
1155                 goto exit;
1156         }
1157
1158         /*  When Busy Traffic, driver do not site survey. So driver return success. */
1159         /*  wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1160         /*  modify by thomas 2011-02-22. */
1161         if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1162                 indicate_wx_scan_complete_event(padapter);
1163                 goto exit;
1164         }
1165
1166         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
1167                 indicate_wx_scan_complete_event(padapter);
1168                 goto exit;
1169         }
1170
1171         memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1172
1173         if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1174                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1175
1176                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1177                         int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1178
1179                         memcpy(ssid[0].ssid, req->essid, len);
1180                         ssid[0].ssid_length = len;
1181
1182                         spin_lock_bh(&pmlmepriv->lock);
1183
1184                         _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1185
1186                         spin_unlock_bh(&pmlmepriv->lock);
1187
1188                 }
1189
1190         } else if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
1191                 && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1192                 int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1193                 char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1194                 char section;
1195                 char sec_len;
1196                 int ssid_index = 0;
1197
1198                 while (len >= 1) {
1199                         section = *(pos++); len -= 1;
1200
1201                         switch (section) {
1202                         case WEXT_CSCAN_SSID_SECTION:
1203                                 if (len < 1) {
1204                                         len = 0;
1205                                         break;
1206                                 }
1207
1208                                 sec_len = *(pos++); len -= 1;
1209
1210                                 if (sec_len > 0 && sec_len <= len) {
1211                                         ssid[ssid_index].ssid_length = sec_len;
1212                                         memcpy(ssid[ssid_index].ssid, pos, ssid[ssid_index].ssid_length);
1213                                         ssid_index++;
1214                                 }
1215
1216                                 pos += sec_len; len -= sec_len;
1217                                 break;
1218
1219
1220                         case WEXT_CSCAN_CHANNEL_SECTION:
1221                                 pos += 1; len -= 1;
1222                                 break;
1223                         case WEXT_CSCAN_ACTV_DWELL_SECTION:
1224                                 pos += 2; len -= 2;
1225                                 break;
1226                         case WEXT_CSCAN_PASV_DWELL_SECTION:
1227                                 pos += 2; len -= 2;
1228                                 break;
1229                         case WEXT_CSCAN_HOME_DWELL_SECTION:
1230                                 pos += 2; len -= 2;
1231                                 break;
1232                         case WEXT_CSCAN_TYPE_SECTION:
1233                                 pos += 1; len -= 1;
1234                                 break;
1235                         default:
1236                                 len = 0; /*  stop parsing */
1237                         }
1238                 }
1239
1240                 /* jeff: it has still some scan parameter to parse, we only do this now... */
1241                 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1242
1243         } else {
1244                 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1245         }
1246
1247         if (_status == false)
1248                 ret = -1;
1249
1250 exit:
1251
1252         rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
1253
1254         return ret;
1255 }
1256
1257 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1258                              union iwreq_data *wrqu, char *extra)
1259 {
1260         struct list_head                                        *plist, *phead;
1261         struct adapter *padapter = rtw_netdev_priv(dev);
1262         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1263         struct __queue                          *queue  = &(pmlmepriv->scanned_queue);
1264         struct  wlan_network    *pnetwork = NULL;
1265         char *ev = extra;
1266         char *stop = ev + wrqu->data.length;
1267         u32 ret = 0;
1268         signed int wait_status;
1269
1270         if (adapter_to_pwrctl(padapter)->brfoffbyhw && padapter->bDriverStopped) {
1271                 ret = -EINVAL;
1272                 goto exit;
1273         }
1274
1275         wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1276
1277         if (check_fwstate(pmlmepriv, wait_status))
1278                 return -EAGAIN;
1279
1280         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1281
1282         phead = get_list_head(queue);
1283         list_for_each(plist, phead) {
1284                 if ((stop - ev) < SCAN_ITEM_SIZE) {
1285                         ret = -E2BIG;
1286                         break;
1287                 }
1288
1289                 pnetwork = list_entry(plist, struct wlan_network, list);
1290
1291                 /* report network only if the current channel set contains the channel to which this network belongs */
1292                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.configuration.ds_config) >= 0
1293                         && true == rtw_validate_ssid(&(pnetwork->network.ssid))) {
1294
1295                         ev = translate_scan(padapter, a, pnetwork, ev, stop);
1296                 }
1297
1298         }
1299
1300         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1301
1302         wrqu->data.length = ev-extra;
1303         wrqu->data.flags = 0;
1304
1305 exit:
1306
1307         return ret;
1308
1309 }
1310
1311 /* set ssid flow */
1312 /* s1. rtw_set_802_11_infrastructure_mode() */
1313 /* s2. set_802_11_authenticaion_mode() */
1314 /* s3. set_802_11_encryption_mode() */
1315 /* s4. rtw_set_802_11_ssid() */
1316 static int rtw_wx_set_essid(struct net_device *dev,
1317                               struct iw_request_info *a,
1318                               union iwreq_data *wrqu, char *extra)
1319 {
1320         struct adapter *padapter = rtw_netdev_priv(dev);
1321         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1322         struct __queue *queue = &pmlmepriv->scanned_queue;
1323         struct list_head *phead;
1324         struct wlan_network *pnetwork = NULL;
1325         enum ndis_802_11_authentication_mode authmode;
1326         struct ndis_802_11_ssid ndis_ssid;
1327         u8 *dst_ssid, *src_ssid;
1328
1329         uint ret = 0, len;
1330
1331         rtw_ps_deny(padapter, PS_DENY_JOIN);
1332         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1333                 ret = -1;
1334                 goto exit;
1335         }
1336
1337         if (!padapter->bup) {
1338                 ret = -1;
1339                 goto exit;
1340         }
1341
1342         if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1343                 ret = -E2BIG;
1344                 goto exit;
1345         }
1346
1347         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1348                 ret = -1;
1349                 goto exit;
1350         }
1351
1352         authmode = padapter->securitypriv.ndisauthtype;
1353         if (wrqu->essid.flags && wrqu->essid.length) {
1354                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1355
1356                 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1357                 ndis_ssid.ssid_length = len;
1358                 memcpy(ndis_ssid.ssid, extra, len);
1359                 src_ssid = ndis_ssid.ssid;
1360
1361                 spin_lock_bh(&queue->lock);
1362                 phead = get_list_head(queue);
1363                 list_for_each(pmlmepriv->pscanned, phead) {
1364                         pnetwork = list_entry(pmlmepriv->pscanned,
1365                                               struct wlan_network, list);
1366
1367                         dst_ssid = pnetwork->network.ssid.ssid;
1368
1369                         if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) &&
1370                                 (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) {
1371                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1372                                         if (pnetwork->network.infrastructure_mode != pmlmepriv->cur_network.network.infrastructure_mode)
1373                                                 continue;
1374                                 }
1375
1376                                 if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.infrastructure_mode) == false) {
1377                                         ret = -1;
1378                                         spin_unlock_bh(&queue->lock);
1379                                         goto exit;
1380                                 }
1381
1382                                 break;
1383                         }
1384                 }
1385                 spin_unlock_bh(&queue->lock);
1386                 rtw_set_802_11_authentication_mode(padapter, authmode);
1387                 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1388                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1389                         ret = -1;
1390                         goto exit;
1391                 }
1392         }
1393
1394 exit:
1395
1396         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1397
1398         return ret;
1399 }
1400
1401 static int rtw_wx_get_essid(struct net_device *dev,
1402                               struct iw_request_info *a,
1403                               union iwreq_data *wrqu, char *extra)
1404 {
1405         u32 len, ret = 0;
1406         struct adapter *padapter = rtw_netdev_priv(dev);
1407         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1408         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1409
1410         if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
1411               (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
1412                 len = pcur_bss->ssid.ssid_length;
1413
1414                 wrqu->essid.length = len;
1415
1416                 memcpy(extra, pcur_bss->ssid.ssid, len);
1417
1418                 wrqu->essid.flags = 1;
1419         } else {
1420                 ret = -1;
1421                 goto exit;
1422         }
1423
1424 exit:
1425         return ret;
1426 }
1427
1428 static int rtw_wx_set_rate(struct net_device *dev,
1429                               struct iw_request_info *a,
1430                               union iwreq_data *wrqu, char *extra)
1431 {
1432         int     i, ret = 0;
1433         struct adapter *padapter = rtw_netdev_priv(dev);
1434         u8 datarates[NumRates];
1435         u32 target_rate = wrqu->bitrate.value;
1436         u32 fixed = wrqu->bitrate.fixed;
1437         u32 ratevalue = 0;
1438         u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1439
1440         if (target_rate == -1) {
1441                 ratevalue = 11;
1442                 goto set_rate;
1443         }
1444         target_rate = target_rate/100000;
1445
1446         switch (target_rate) {
1447         case 10:
1448                 ratevalue = 0;
1449                 break;
1450         case 20:
1451                 ratevalue = 1;
1452                 break;
1453         case 55:
1454                 ratevalue = 2;
1455                 break;
1456         case 60:
1457                 ratevalue = 3;
1458                 break;
1459         case 90:
1460                 ratevalue = 4;
1461                 break;
1462         case 110:
1463                 ratevalue = 5;
1464                 break;
1465         case 120:
1466                 ratevalue = 6;
1467                 break;
1468         case 180:
1469                 ratevalue = 7;
1470                 break;
1471         case 240:
1472                 ratevalue = 8;
1473                 break;
1474         case 360:
1475                 ratevalue = 9;
1476                 break;
1477         case 480:
1478                 ratevalue = 10;
1479                 break;
1480         case 540:
1481                 ratevalue = 11;
1482                 break;
1483         default:
1484                 ratevalue = 11;
1485                 break;
1486         }
1487
1488 set_rate:
1489
1490         for (i = 0; i < NumRates; i++) {
1491                 if (ratevalue == mpdatarate[i]) {
1492                         datarates[i] = mpdatarate[i];
1493                         if (fixed == 0)
1494                                 break;
1495                 } else {
1496                         datarates[i] = 0xff;
1497                 }
1498         }
1499
1500         if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1501                 ret = -1;
1502
1503         return ret;
1504 }
1505
1506 static int rtw_wx_get_rate(struct net_device *dev,
1507                              struct iw_request_info *info,
1508                              union iwreq_data *wrqu, char *extra)
1509 {
1510         u16 max_rate = 0;
1511
1512         max_rate = rtw_get_cur_max_rate(rtw_netdev_priv(dev));
1513
1514         if (max_rate == 0)
1515                 return -EPERM;
1516
1517         wrqu->bitrate.fixed = 0;        /* no auto select */
1518         wrqu->bitrate.value = max_rate * 100000;
1519
1520         return 0;
1521 }
1522
1523 static int rtw_wx_set_rts(struct net_device *dev,
1524                              struct iw_request_info *info,
1525                              union iwreq_data *wrqu, char *extra)
1526 {
1527         struct adapter *padapter = rtw_netdev_priv(dev);
1528
1529         if (wrqu->rts.disabled)
1530                 padapter->registrypriv.rts_thresh = 2347;
1531         else {
1532                 if (wrqu->rts.value < 0 ||
1533                     wrqu->rts.value > 2347)
1534                         return -EINVAL;
1535
1536                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1537         }
1538
1539         return 0;
1540 }
1541
1542 static int rtw_wx_get_rts(struct net_device *dev,
1543                              struct iw_request_info *info,
1544                              union iwreq_data *wrqu, char *extra)
1545 {
1546         struct adapter *padapter = rtw_netdev_priv(dev);
1547
1548         wrqu->rts.value = padapter->registrypriv.rts_thresh;
1549         wrqu->rts.fixed = 0;    /* no auto select */
1550         /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1551
1552         return 0;
1553 }
1554
1555 static int rtw_wx_set_frag(struct net_device *dev,
1556                              struct iw_request_info *info,
1557                              union iwreq_data *wrqu, char *extra)
1558 {
1559         struct adapter *padapter = rtw_netdev_priv(dev);
1560
1561         if (wrqu->frag.disabled)
1562                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1563         else {
1564                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1565                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
1566                         return -EINVAL;
1567
1568                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1569         }
1570
1571         return 0;
1572
1573 }
1574
1575 static int rtw_wx_get_frag(struct net_device *dev,
1576                              struct iw_request_info *info,
1577                              union iwreq_data *wrqu, char *extra)
1578 {
1579         struct adapter *padapter = rtw_netdev_priv(dev);
1580
1581         wrqu->frag.value = padapter->xmitpriv.frag_len;
1582         wrqu->frag.fixed = 0;   /* no auto select */
1583         /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
1584
1585         return 0;
1586 }
1587
1588 static int rtw_wx_get_retry(struct net_device *dev,
1589                              struct iw_request_info *info,
1590                              union iwreq_data *wrqu, char *extra)
1591 {
1592         /* struct adapter *padapter = rtw_netdev_priv(dev); */
1593
1594
1595         wrqu->retry.value = 7;
1596         wrqu->retry.fixed = 0;  /* no auto select */
1597         wrqu->retry.disabled = 1;
1598
1599         return 0;
1600
1601 }
1602
1603 static int rtw_wx_set_enc(struct net_device *dev,
1604                             struct iw_request_info *info,
1605                             union iwreq_data *wrqu, char *keybuf)
1606 {
1607         u32 key, ret = 0;
1608         u32 keyindex_provided;
1609         struct ndis_802_11_wep   wep;
1610         enum ndis_802_11_authentication_mode authmode;
1611
1612         struct iw_point *erq = &(wrqu->encoding);
1613         struct adapter *padapter = rtw_netdev_priv(dev);
1614         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1615
1616         memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1617
1618         key = erq->flags & IW_ENCODE_INDEX;
1619
1620         if (erq->flags & IW_ENCODE_DISABLED) {
1621                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1622                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1623                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1624                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
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         }
1640
1641         /* set authentication mode */
1642         if (erq->flags & IW_ENCODE_OPEN) {
1643                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1644
1645                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1646
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                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1653
1654                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1655
1656                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1657                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1658                 authmode = Ndis802_11AuthModeShared;
1659                 padapter->securitypriv.ndisauthtype = authmode;
1660         } else {
1661                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1662                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1663                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1664                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1665                 authmode = Ndis802_11AuthModeOpen;
1666                 padapter->securitypriv.ndisauthtype = authmode;
1667         }
1668
1669         wep.key_index = key;
1670         if (erq->length > 0) {
1671                 wep.key_length = erq->length <= 5 ? 5 : 13;
1672
1673                 wep.length = wep.key_length + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
1674         } else {
1675                 wep.key_length = 0;
1676
1677                 if (keyindex_provided == 1) { /*  set key_id only, no given key_material(erq->length == 0). */
1678                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
1679
1680                         switch (padapter->securitypriv.dot11DefKeylen[key]) {
1681                         case 5:
1682                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1683                                 break;
1684                         case 13:
1685                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1686                                 break;
1687                         default:
1688                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1689                                 break;
1690                         }
1691
1692                         goto exit;
1693
1694                 }
1695
1696         }
1697
1698         wep.key_index |= 0x80000000;
1699
1700         memcpy(wep.key_material, keybuf, wep.key_length);
1701
1702         if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1703                 if (rf_on == pwrpriv->rf_pwrstate)
1704                         ret = -EOPNOTSUPP;
1705                 goto exit;
1706         }
1707
1708 exit:
1709         return ret;
1710 }
1711
1712 static int rtw_wx_get_enc(struct net_device *dev,
1713                             struct iw_request_info *info,
1714                             union iwreq_data *wrqu, char *keybuf)
1715 {
1716         uint key, ret = 0;
1717         struct adapter *padapter = rtw_netdev_priv(dev);
1718         struct iw_point *erq = &(wrqu->encoding);
1719         struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1720
1721         if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1722                  if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true) {
1723                          erq->length = 0;
1724                          erq->flags |= IW_ENCODE_DISABLED;
1725                          return 0;
1726                  }
1727         }
1728
1729
1730         key = erq->flags & IW_ENCODE_INDEX;
1731
1732         if (key) {
1733                 if (key > WEP_KEYS)
1734                         return -EINVAL;
1735                 key--;
1736         } else {
1737                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1738         }
1739
1740         erq->flags = key + 1;
1741
1742         /* if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
1743         /*  */
1744         /*       erq->flags |= IW_ENCODE_OPEN; */
1745         /*  */
1746
1747         switch (padapter->securitypriv.ndisencryptstatus) {
1748         case Ndis802_11EncryptionNotSupported:
1749         case Ndis802_11EncryptionDisabled:
1750                 erq->length = 0;
1751                 erq->flags |= IW_ENCODE_DISABLED;
1752                 break;
1753         case Ndis802_11Encryption1Enabled:
1754                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1755
1756                 if (erq->length) {
1757                         memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1758
1759                         erq->flags |= IW_ENCODE_ENABLED;
1760
1761                         if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1762                                 erq->flags |= IW_ENCODE_OPEN;
1763                         else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1764                                 erq->flags |= IW_ENCODE_RESTRICTED;
1765                 } else {
1766                         erq->length = 0;
1767                         erq->flags |= IW_ENCODE_DISABLED;
1768                 }
1769                 break;
1770         case Ndis802_11Encryption2Enabled:
1771         case Ndis802_11Encryption3Enabled:
1772                 erq->length = 16;
1773                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1774                 break;
1775         default:
1776                 erq->length = 0;
1777                 erq->flags |= IW_ENCODE_DISABLED;
1778                 break;
1779         }
1780         return ret;
1781 }
1782
1783 static int rtw_wx_get_power(struct net_device *dev,
1784                              struct iw_request_info *info,
1785                              union iwreq_data *wrqu, char *extra)
1786 {
1787         /* struct adapter *padapter = rtw_netdev_priv(dev); */
1788
1789         wrqu->power.value = 0;
1790         wrqu->power.fixed = 0;  /* no auto select */
1791         wrqu->power.disabled = 1;
1792
1793         return 0;
1794 }
1795
1796 static int rtw_wx_set_gen_ie(struct net_device *dev,
1797                              struct iw_request_info *info,
1798                              union iwreq_data *wrqu, char *extra)
1799 {
1800         struct adapter *padapter = rtw_netdev_priv(dev);
1801
1802         return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1803 }
1804
1805 static int rtw_wx_set_auth(struct net_device *dev,
1806                            struct iw_request_info *info,
1807                            union iwreq_data *wrqu, char *extra)
1808 {
1809         struct adapter *padapter = rtw_netdev_priv(dev);
1810         struct iw_param *param = (struct iw_param *)&(wrqu->param);
1811         int ret = 0;
1812
1813         switch (param->flags & IW_AUTH_INDEX) {
1814         case IW_AUTH_WPA_VERSION:
1815                 break;
1816         case IW_AUTH_CIPHER_PAIRWISE:
1817                 break;
1818         case IW_AUTH_CIPHER_GROUP:
1819                 break;
1820         case IW_AUTH_KEY_MGMT:
1821                 /*
1822                  *  ??? does not use these parameters
1823                  */
1824                 break;
1825         case IW_AUTH_TKIP_COUNTERMEASURES:
1826                 /* wpa_supplicant is setting the tkip countermeasure. */
1827                 if (param->value) /* enabling */
1828                         padapter->securitypriv.btkip_countermeasure = true;
1829                 else /* disabling */
1830                         padapter->securitypriv.btkip_countermeasure = false;
1831                 break;
1832         case IW_AUTH_DROP_UNENCRYPTED:
1833                 /* HACK:
1834                  *
1835                  * wpa_supplicant calls set_wpa_enabled when the driver
1836                  * is loaded and unloaded, regardless of if WPA is being
1837                  * used.  No other calls are made which can be used to
1838                  * determine if encryption will be used or not prior to
1839                  * association being expected.  If encryption is not being
1840                  * used, drop_unencrypted is set to false, else true -- we
1841                  * can use this to determine if the CAP_PRIVACY_ON bit should
1842                  * be set.
1843                  */
1844
1845                 /*
1846                  * This means init value, or using wep, ndisencryptstatus =
1847                  * Ndis802_11Encryption1Enabled, then it needn't reset it;
1848                  */
1849                 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
1850                         break;
1851
1852                 if (param->value) {
1853                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1854                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1855                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1856                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1857                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1858                 }
1859
1860                 break;
1861         case IW_AUTH_80211_AUTH_ALG:
1862                 /*
1863                  *  It's the starting point of a link layer connection using wpa_supplicant
1864                  */
1865                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1866                         LeaveAllPowerSaveMode(padapter);
1867                         rtw_disassoc_cmd(padapter, 500, false);
1868                         rtw_indicate_disconnect(padapter);
1869                         rtw_free_assoc_resources(padapter, 1);
1870                 }
1871
1872                 ret = wpa_set_auth_algs(dev, (u32)param->value);
1873                 break;
1874         case IW_AUTH_WPA_ENABLED:
1875                 break;
1876         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1877                 break;
1878         case IW_AUTH_PRIVACY_INVOKED:
1879                 break;
1880         default:
1881                 return -EOPNOTSUPP;
1882         }
1883
1884         return ret;
1885 }
1886
1887 static int rtw_wx_set_enc_ext(struct net_device *dev,
1888                              struct iw_request_info *info,
1889                              union iwreq_data *wrqu, char *extra)
1890 {
1891         char *alg_name;
1892         u32 param_len;
1893         struct ieee_param *param = NULL;
1894         struct iw_point *pencoding = &wrqu->encoding;
1895         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1896         int ret = 0;
1897
1898         param_len = sizeof(struct ieee_param) + pext->key_len;
1899         param = kzalloc(param_len, GFP_KERNEL);
1900         if (param == NULL)
1901                 return -1;
1902
1903         param->cmd = IEEE_CMD_SET_ENCRYPTION;
1904         eth_broadcast_addr(param->sta_addr);
1905
1906
1907         switch (pext->alg) {
1908         case IW_ENCODE_ALG_NONE:
1909                 /* todo: remove key */
1910                 /* remove = 1; */
1911                 alg_name = "none";
1912                 break;
1913         case IW_ENCODE_ALG_WEP:
1914                 alg_name = "WEP";
1915                 break;
1916         case IW_ENCODE_ALG_TKIP:
1917                 alg_name = "TKIP";
1918                 break;
1919         case IW_ENCODE_ALG_CCMP:
1920                 alg_name = "CCMP";
1921                 break;
1922         case IW_ENCODE_ALG_AES_CMAC:
1923                 alg_name = "BIP";
1924                 break;
1925         default:
1926                 ret = -1;
1927                 goto exit;
1928         }
1929
1930         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1931
1932         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1933                 param->u.crypt.set_tx = 1;
1934
1935         /* cliW: WEP does not have group key
1936          * just not checking GROUP key setting
1937          */
1938         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
1939                 ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1940                 || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC))) {
1941                 param->u.crypt.set_tx = 0;
1942         }
1943
1944         param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1945
1946         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1947                 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1948
1949         if (pext->key_len) {
1950                 param->u.crypt.key_len = pext->key_len;
1951                 /* memcpy(param + 1, pext + 1, pext->key_len); */
1952                 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
1953         }
1954
1955         if (pencoding->flags & IW_ENCODE_DISABLED) {
1956                 /* todo: remove key */
1957                 /* remove = 1; */
1958         }
1959
1960         ret =  wpa_set_encryption(dev, param, param_len);
1961
1962 exit:
1963         kfree(param);
1964
1965         return ret;
1966 }
1967
1968
1969 static int rtw_wx_get_nick(struct net_device *dev,
1970                              struct iw_request_info *info,
1971                              union iwreq_data *wrqu, char *extra)
1972 {
1973         /* struct adapter *padapter = rtw_netdev_priv(dev); */
1974          /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
1975          /* struct security_priv *psecuritypriv = &padapter->securitypriv; */
1976
1977         if (extra) {
1978                 wrqu->data.length = 14;
1979                 wrqu->data.flags = 1;
1980                 memcpy(extra, "<WIFI@REALTEK>", 14);
1981         }
1982         return 0;
1983 }
1984
1985 static int rtw_wx_read32(struct net_device *dev,
1986                          struct iw_request_info *info,
1987                          union iwreq_data *wrqu, char *extra)
1988 {
1989         struct adapter *padapter;
1990         struct iw_point *p;
1991         u16 len;
1992         u32 addr;
1993         u32 data32;
1994         u32 bytes;
1995         u8 *ptmp;
1996         int ret;
1997
1998
1999         ret = 0;
2000         padapter = rtw_netdev_priv(dev);
2001         p = &wrqu->data;
2002         len = p->length;
2003         if (0 == len)
2004                 return -EINVAL;
2005
2006         ptmp = rtw_malloc(len);
2007         if (NULL == ptmp)
2008                 return -ENOMEM;
2009
2010         if (copy_from_user(ptmp, p->pointer, len)) {
2011                 ret = -EFAULT;
2012                 goto exit;
2013         }
2014
2015         bytes = 0;
2016         addr = 0;
2017         sscanf(ptmp, "%d,%x", &bytes, &addr);
2018
2019         switch (bytes) {
2020         case 1:
2021                 data32 = rtw_read8(padapter, addr);
2022                 sprintf(extra, "0x%02X", data32);
2023                 break;
2024         case 2:
2025                 data32 = rtw_read16(padapter, addr);
2026                 sprintf(extra, "0x%04X", data32);
2027                 break;
2028         case 4:
2029                 data32 = rtw_read32(padapter, addr);
2030                 sprintf(extra, "0x%08X", data32);
2031                 break;
2032         default:
2033                 ret = -EINVAL;
2034                 goto exit;
2035         }
2036
2037 exit:
2038         kfree(ptmp);
2039
2040         return ret;
2041 }
2042
2043 static int rtw_wx_write32(struct net_device *dev,
2044                           struct iw_request_info *info,
2045                           union iwreq_data *wrqu, char *extra)
2046 {
2047         struct adapter *padapter = rtw_netdev_priv(dev);
2048
2049         u32 addr;
2050         u32 data32;
2051         u32 bytes;
2052
2053
2054         bytes = 0;
2055         addr = 0;
2056         data32 = 0;
2057         sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
2058
2059         switch (bytes) {
2060         case 1:
2061                 rtw_write8(padapter, addr, (u8)data32);
2062                 break;
2063         case 2:
2064                 rtw_write16(padapter, addr, (u16)data32);
2065                 break;
2066         case 4:
2067                 rtw_write32(padapter, addr, data32);
2068                 break;
2069         default:
2070                 return -EINVAL;
2071         }
2072
2073         return 0;
2074 }
2075
2076 static int rtw_wx_read_rf(struct net_device *dev,
2077                           struct iw_request_info *info,
2078                           union iwreq_data *wrqu, char *extra)
2079 {
2080         struct adapter *padapter = rtw_netdev_priv(dev);
2081         u32 path, addr, data32;
2082
2083
2084         path = *(u32 *)extra;
2085         addr = *((u32 *)extra + 1);
2086         data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
2087         /*
2088          * IMPORTANT!!
2089          * Only when wireless private ioctl is at odd order,
2090          * "extra" would be copied to user space.
2091          */
2092         sprintf(extra, "0x%05x", data32);
2093
2094         return 0;
2095 }
2096
2097 static int rtw_wx_write_rf(struct net_device *dev,
2098                            struct iw_request_info *info,
2099                            union iwreq_data *wrqu, char *extra)
2100 {
2101         struct adapter *padapter = rtw_netdev_priv(dev);
2102         u32 path, addr, data32;
2103
2104
2105         path = *(u32 *)extra;
2106         addr = *((u32 *)extra + 1);
2107         data32 = *((u32 *)extra + 2);
2108         rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
2109
2110         return 0;
2111 }
2112
2113 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
2114                  union iwreq_data *wrqu, char *b)
2115 {
2116         return -1;
2117 }
2118
2119 static int dummy(struct net_device *dev, struct iw_request_info *a,
2120                  union iwreq_data *wrqu, char *b)
2121 {
2122         /* struct adapter *padapter = rtw_netdev_priv(dev); */
2123         /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
2124
2125         return -1;
2126
2127 }
2128
2129 static int rtw_wx_set_channel_plan(struct net_device *dev,
2130                                    struct iw_request_info *info,
2131                                    union iwreq_data *wrqu, char *extra)
2132 {
2133         struct adapter *padapter = rtw_netdev_priv(dev);
2134         u8 channel_plan_req = (u8)(*((int *)wrqu));
2135
2136         if (rtw_set_chplan_cmd(padapter, channel_plan_req, 1, 1) != _SUCCESS)
2137                 return -EPERM;
2138
2139         return 0;
2140 }
2141
2142 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
2143                 struct iw_request_info *a,
2144                 union iwreq_data *wrqu, char *b)
2145 {
2146         return 0;
2147 }
2148
2149 static int rtw_wx_get_sensitivity(struct net_device *dev,
2150                                 struct iw_request_info *info,
2151                                 union iwreq_data *wrqu, char *buf)
2152 {
2153         return 0;
2154 }
2155
2156 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
2157                                 struct iw_request_info *info,
2158                                 union iwreq_data *wrqu, char *extra)
2159 {
2160         return 0;
2161 }
2162
2163 /*
2164 typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
2165                           union iwreq_data *wrqu, char *extra);
2166 */
2167 /*
2168  *For all data larger than 16 octets, we need to use a
2169  *pointer to memory allocated in user space.
2170  */
2171 static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
2172                                                 union iwreq_data *wrqu, char *extra)
2173 {
2174         return 0;
2175 }
2176
2177 static int rtw_get_ap_info(struct net_device *dev,
2178                            struct iw_request_info *info,
2179                            union iwreq_data *wrqu, char *extra)
2180 {
2181         int ret = 0;
2182         int wpa_ielen;
2183         u32 cnt = 0;
2184         struct list_head        *plist, *phead;
2185         unsigned char *pbuf;
2186         u8 bssid[ETH_ALEN];
2187         char data[32];
2188         struct wlan_network *pnetwork = NULL;
2189         struct adapter *padapter = rtw_netdev_priv(dev);
2190         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2191         struct __queue *queue = &(pmlmepriv->scanned_queue);
2192         struct iw_point *pdata = &wrqu->data;
2193
2194         if ((padapter->bDriverStopped) || (pdata == NULL)) {
2195                 ret = -EINVAL;
2196                 goto exit;
2197         }
2198
2199         while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == true) {
2200                 msleep(30);
2201                 cnt++;
2202                 if (cnt > 100)
2203                         break;
2204         }
2205
2206
2207         /* pdata->length = 0;? */
2208         pdata->flags = 0;
2209         if (pdata->length >= 32) {
2210                 if (copy_from_user(data, pdata->pointer, 32)) {
2211                         ret = -EINVAL;
2212                         goto exit;
2213                 }
2214         } else {
2215                 ret = -EINVAL;
2216                 goto exit;
2217         }
2218
2219         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2220
2221         phead = get_list_head(queue);
2222         list_for_each(plist, phead) {
2223                 pnetwork = list_entry(plist, struct wlan_network, list);
2224
2225                 if (!mac_pton(data, bssid)) {
2226                         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2227                         return -EINVAL;
2228                 }
2229
2230
2231                 if (!memcmp(bssid, pnetwork->network.mac_address, ETH_ALEN)) { /* BSSID match, then check if supporting wpa/wpa2 */
2232
2233                         pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length-12);
2234                         if (pbuf && (wpa_ielen > 0)) {
2235                                 pdata->flags = 1;
2236                                 break;
2237                         }
2238
2239                         pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length-12);
2240                         if (pbuf && (wpa_ielen > 0)) {
2241                                 pdata->flags = 2;
2242                                 break;
2243                         }
2244                 }
2245
2246         }
2247
2248         spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2249
2250         if (pdata->length >= 34) {
2251                 if (copy_to_user((u8 __force __user *)pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
2252                         ret = -EINVAL;
2253                         goto exit;
2254                 }
2255         }
2256
2257 exit:
2258
2259         return ret;
2260
2261 }
2262
2263 static int rtw_set_pid(struct net_device *dev,
2264                        struct iw_request_info *info,
2265                        union iwreq_data *wrqu, char *extra)
2266 {
2267
2268         int ret = 0;
2269         struct adapter *padapter = rtw_netdev_priv(dev);
2270         int *pdata = (int *)wrqu;
2271         int selector;
2272
2273         if ((padapter->bDriverStopped) || (pdata == NULL)) {
2274                 ret = -EINVAL;
2275                 goto exit;
2276         }
2277
2278         selector = *pdata;
2279         if (selector < 3 && selector >= 0)
2280                 padapter->pid[selector] = *(pdata+1);
2281
2282 exit:
2283
2284         return ret;
2285
2286 }
2287
2288 static int rtw_wps_start(struct net_device *dev,
2289                          struct iw_request_info *info,
2290                          union iwreq_data *wrqu, char *extra)
2291 {
2292
2293         int ret = 0;
2294         struct adapter *padapter = rtw_netdev_priv(dev);
2295         struct iw_point *pdata = &wrqu->data;
2296         u32   u32wps_start = 0;
2297
2298         if ((true == padapter->bDriverStopped) || (true == padapter->bSurpriseRemoved) || (NULL == pdata)) {
2299                 ret = -EINVAL;
2300                 goto exit;
2301         }
2302
2303         if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4)) {
2304                 ret = -EFAULT;
2305                 goto exit;
2306         }
2307         if (u32wps_start == 0)
2308                 u32wps_start = *extra;
2309
2310 exit:
2311
2312         return ret;
2313
2314 }
2315
2316 static int rtw_p2p_set(struct net_device *dev,
2317                        struct iw_request_info *info,
2318                        union iwreq_data *wrqu, char *extra)
2319 {
2320
2321         return 0;
2322
2323 }
2324
2325 static int rtw_p2p_get(struct net_device *dev,
2326                        struct iw_request_info *info,
2327                        union iwreq_data *wrqu, char *extra)
2328 {
2329
2330         return 0;
2331
2332 }
2333
2334 static int rtw_p2p_get2(struct net_device *dev,
2335                                                 struct iw_request_info *info,
2336                                                 union iwreq_data *wrqu, char *extra)
2337 {
2338
2339         return 0;
2340
2341 }
2342
2343 static int rtw_rereg_nd_name(struct net_device *dev,
2344                              struct iw_request_info *info,
2345                              union iwreq_data *wrqu, char *extra)
2346 {
2347         int ret = 0;
2348         struct adapter *padapter = rtw_netdev_priv(dev);
2349         struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
2350         char new_ifname[IFNAMSIZ];
2351
2352         if (rereg_priv->old_ifname[0] == 0) {
2353                 char *reg_ifname;
2354                 reg_ifname = padapter->registrypriv.ifname;
2355
2356                 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
2357                 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
2358         }
2359
2360         if (wrqu->data.length > IFNAMSIZ)
2361                 return -EFAULT;
2362
2363         if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
2364                 return -EFAULT;
2365
2366         if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
2367                 return ret;
2368
2369         ret = rtw_change_ifname(padapter, new_ifname);
2370         if (ret != 0)
2371                 goto exit;
2372
2373         strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
2374         rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
2375
2376         if (!memcmp(new_ifname, "disable%d", 9)) {
2377                 /*  free network queue for Android's timming issue */
2378                 rtw_free_network_queue(padapter, true);
2379
2380                 /*  the interface is being "disabled", we can do deeper IPS */
2381                 /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
2382         }
2383 exit:
2384         return ret;
2385
2386 }
2387
2388 static int rtw_dbg_port(struct net_device *dev,
2389                         struct iw_request_info *info,
2390                         union iwreq_data *wrqu, char *extra)
2391 {
2392         u8 major_cmd, minor_cmd;
2393         u16 arg;
2394         u32 extra_arg, *pdata, val32;
2395         struct adapter *padapter = rtw_netdev_priv(dev);
2396         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2397         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2398
2399         pdata = (u32 *)&wrqu->data;
2400
2401         val32 = *pdata;
2402         arg = (u16)(val32&0x0000ffff);
2403         major_cmd = (u8)(val32>>24);
2404         minor_cmd = (u8)((val32>>16)&0x00ff);
2405
2406         extra_arg = *(pdata+1);
2407
2408         switch (major_cmd) {
2409                 case 0x70:/* read_reg */
2410                         switch (minor_cmd) {
2411                                 case 1:
2412                                         break;
2413                                 case 2:
2414                                         break;
2415                                 case 4:
2416                                         break;
2417                         }
2418                         break;
2419                 case 0x71:/* write_reg */
2420                         switch (minor_cmd) {
2421                                 case 1:
2422                                         rtw_write8(padapter, arg, extra_arg);
2423                                         break;
2424                                 case 2:
2425                                         rtw_write16(padapter, arg, extra_arg);
2426                                         break;
2427                                 case 4:
2428                                         rtw_write32(padapter, arg, extra_arg);
2429                                         break;
2430                         }
2431                         break;
2432                 case 0x72:/* read_bb */
2433                         break;
2434                 case 0x73:/* write_bb */
2435                         rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
2436                         break;
2437                 case 0x74:/* read_rf */
2438                         break;
2439                 case 0x75:/* write_rf */
2440                         rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
2441                         break;
2442
2443                 case 0x76:
2444                         switch (minor_cmd) {
2445                                 case 0x00: /* normal mode, */
2446                                         padapter->recvpriv.is_signal_dbg = 0;
2447                                         break;
2448                                 case 0x01: /* dbg mode */
2449                                         padapter->recvpriv.is_signal_dbg = 1;
2450                                         extra_arg = extra_arg > 100 ? 100 : extra_arg;
2451                                         padapter->recvpriv.signal_strength_dbg = extra_arg;
2452                                         break;
2453                         }
2454                         break;
2455                 case 0x78: /* IOL test */
2456                         break;
2457                 case 0x79:
2458                         {
2459                                 /*
2460                                 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
2461                                 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
2462                                 */
2463                                 u8 value =  extra_arg & 0x0f;
2464                                 u8 sign = minor_cmd;
2465                                 u16 write_value = 0;
2466
2467                                 if (sign)
2468                                         value = value | 0x10;
2469
2470                                 write_value = value | (value << 5);
2471                                 rtw_write16(padapter, 0x6d9, write_value);
2472                         }
2473                         break;
2474                 case 0x7a:
2475                         receive_disconnect(padapter, pmlmeinfo->network.mac_address
2476                                 , WLAN_REASON_EXPIRATION_CHK);
2477                         break;
2478                 case 0x7F:
2479                         switch (minor_cmd) {
2480                                 case 0x0:
2481                                         break;
2482                                 case 0x01:
2483                                         break;
2484                                 case 0x02:
2485                                         break;
2486                                 case 0x03:
2487                                         break;
2488                                 case 0x04:
2489
2490                                         break;
2491                                 case 0x05:
2492                                         break;
2493                                 case 0x06:
2494                                         {
2495                                                 u32 ODMFlag;
2496                                                 rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
2497                                                 ODMFlag = (u32)(0x0f&arg);
2498                                                 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
2499                                         }
2500                                         break;
2501                                 case 0x07:
2502                                         break;
2503                                 case 0x08:
2504                                         {
2505                                         }
2506                                         break;
2507                                 case 0x09:
2508                                         break;
2509                                 case 0x0a:
2510                                         {
2511                                                 int max_mac_id = 0;
2512                                                 max_mac_id = rtw_search_max_mac_id(padapter);
2513                                                 printk("%s ==> max_mac_id = %d\n", __func__, max_mac_id);
2514                                         }
2515                                         break;
2516                                 case 0x0b: /* Enable = 1, Disable = 0 driver control vrtl_carrier_sense. */
2517                                         if (arg == 0) {
2518                                                 padapter->driver_vcs_en = 0;
2519                                         } else if (arg == 1) {
2520                                                 padapter->driver_vcs_en = 1;
2521
2522                                                 if (extra_arg > 2)
2523                                                         padapter->driver_vcs_type = 1;
2524                                                 else
2525                                                         padapter->driver_vcs_type = extra_arg;
2526                                         }
2527                                         break;
2528                                 case 0x0c:/* dump rx/tx packet */
2529                                         {
2530                                                 if (arg == 0)
2531                                                         /* pHalData->bDumpRxPkt =extra_arg; */
2532                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
2533                                                 else if (arg == 1)
2534                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
2535                                         }
2536                                         break;
2537                                 case 0x0e:
2538                                         {
2539                                                 if (arg == 0) {
2540                                                         padapter->driver_rx_ampdu_factor = 0xFF;
2541                                                 } else if (arg == 1) {
2542
2543                                                         if ((extra_arg & 0x03) > 0x03)
2544                                                                 padapter->driver_rx_ampdu_factor = 0xFF;
2545                                                         else
2546                                                                 padapter->driver_rx_ampdu_factor = extra_arg;
2547                                                 }
2548                                         }
2549                                         break;
2550
2551                                 case 0x10:/*  driver version display */
2552                                         netdev_dbg(dev, "%s %s\n", "rtl8723bs", DRIVERVERSION);
2553                                         break;
2554                                 case 0x11:/* dump linked status */
2555                                         {
2556                                                  linked_info_dump(padapter, extra_arg);
2557                                         }
2558                                         break;
2559                                 case 0x12: /* set rx_stbc */
2560                                 {
2561                                         struct registry_priv *pregpriv = &padapter->registrypriv;
2562                                         /*  0: disable, bit(0):enable 2.4g */
2563                                         /* default is set to enable 2.4GHZ */
2564                                         if (extra_arg == 0 || extra_arg == 1)
2565                                                 pregpriv->rx_stbc = extra_arg;
2566                                 }
2567                                 break;
2568                                 case 0x13: /* set ampdu_enable */
2569                                 {
2570                                         struct registry_priv *pregpriv = &padapter->registrypriv;
2571                                         /*  0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
2572                                         if (extra_arg < 3)
2573                                                 pregpriv->ampdu_enable = extra_arg;
2574                                 }
2575                                 break;
2576                                 case 0x14:
2577                                 {
2578                                 }
2579                                 break;
2580                                 case 0x16:
2581                                 {
2582                                         if (arg == 0xff) {
2583                                                 rtw_odm_dbg_comp_msg(padapter);
2584                                         } else {
2585                                                 u64 dbg_comp = (u64)extra_arg;
2586                                                 rtw_odm_dbg_comp_set(padapter, dbg_comp);
2587                                         }
2588                                 }
2589                                         break;
2590 #ifdef DBG_FIXED_CHAN
2591                                 case 0x17:
2592                                         {
2593                                                 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2594                                                 printk("===>  Fixed channel to %d\n", extra_arg);
2595                                                 pmlmeext->fixed_chan = extra_arg;
2596
2597                                         }
2598                                         break;
2599 #endif
2600                                 case 0x18:
2601                                         {
2602                                                 printk("===>  Switch USB Mode %d\n", extra_arg);
2603                                                 rtw_hal_set_hwreg(padapter, HW_VAR_USB_MODE, (u8 *)&extra_arg);
2604                                         }
2605                                         break;
2606                                 case 0x19:
2607                                         {
2608                                                 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2609                                                 /*  extra_arg : */
2610                                                 /*  BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
2611                                                 /*  BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
2612                                                 if (arg == 0)
2613                                                         pregistrypriv->ldpc_cap = 0x00;
2614                                                 else if (arg == 1)
2615                                                         pregistrypriv->ldpc_cap = (u8)(extra_arg&0x33);
2616                                         }
2617                                         break;
2618                                 case 0x1a:
2619                                         {
2620                                                 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2621                                                 /*  extra_arg : */
2622                                                 /*  BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
2623                                                 /*  BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
2624                                                 if (arg == 0)
2625                                                         pregistrypriv->stbc_cap = 0x00;
2626                                                 else if (arg == 1)
2627                                                         pregistrypriv->stbc_cap = (u8)(extra_arg&0x33);
2628                                         }
2629                                         break;
2630                                 case 0x1b:
2631                                         {
2632                                                 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2633
2634                                                 if (arg == 0) {
2635                                                         init_mlme_default_rate_set(padapter);
2636                                                         pregistrypriv->ht_enable = (u8)rtw_ht_enable;
2637                                                 } else if (arg == 1) {
2638
2639                                                         int i;
2640                                                         u8 max_rx_rate;
2641
2642                                                         max_rx_rate = (u8)extra_arg;
2643
2644                                                         if (max_rx_rate < 0xc) { /*  max_rx_rate < MSC0 -> B or G -> disable HT */
2645                                                                 pregistrypriv->ht_enable = 0;
2646                                                                 for (i = 0; i < NumRates; i++) {
2647                                                                         if (pmlmeext->datarate[i] > max_rx_rate)
2648                                                                                 pmlmeext->datarate[i] = 0xff;
2649                                                                 }
2650
2651                                                         }
2652                                                         else if (max_rx_rate < 0x1c) { /*  mcs0~mcs15 */
2653                                                                 u32 mcs_bitmap = 0x0;
2654
2655                                                                 for (i = 0; i < ((max_rx_rate + 1) - 0xc); i++)
2656                                                                         mcs_bitmap |= BIT(i);
2657
2658                                                                 set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
2659                                                         }
2660                                                 }
2661                                         }
2662                                         break;
2663                                 case 0x1c: /* enable/disable driver control AMPDU Density for peer sta's rx */
2664                                         {
2665                                                 if (arg == 0) {
2666                                                         padapter->driver_ampdu_spacing = 0xFF;
2667                                                 } else if (arg == 1) {
2668
2669                                                         if (extra_arg > 0x07)
2670                                                                 padapter->driver_ampdu_spacing = 0xFF;
2671                                                         else
2672                                                                 padapter->driver_ampdu_spacing = extra_arg;
2673                                                 }
2674                                         }
2675                                         break;
2676                                 case 0x23:
2677                                         {
2678                                                 padapter->bNotifyChannelChange = extra_arg;
2679                                                 break;
2680                                         }
2681                                 case 0x24:
2682                                         {
2683                                                 break;
2684                                         }
2685                                 case 0xaa:
2686                                         {
2687                                                 if ((extra_arg & 0x7F) > 0x3F)
2688                                                         extra_arg = 0xFF;
2689                                                 padapter->fix_rate = extra_arg;
2690                                         }
2691                                         break;
2692                                 case 0xdd:/* registers dump , 0 for mac reg, 1 for bb reg, 2 for rf reg */
2693                                         {
2694                                                 if (extra_arg == 0)
2695                                                         mac_reg_dump(padapter);
2696                                                 else if (extra_arg == 1)
2697                                                         bb_reg_dump(padapter);
2698                                                 else if (extra_arg == 2)
2699                                                         rf_reg_dump(padapter);
2700                                         }
2701                                         break;
2702
2703                                 case 0xee:/* turn on/off dynamic funcs */
2704                                         {
2705                                                 u32 odm_flag;
2706
2707                                                 if (0xf == extra_arg) {
2708                                                         rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
2709                                                 } else {
2710                                                         /*extra_arg = 0  - disable all dynamic func
2711                                                                 extra_arg = 1  - disable DIG
2712                                                                 extra_arg = 2  - disable tx power tracking
2713                                                                 extra_arg = 3  - turn on all dynamic func
2714                                                         */
2715                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
2716                                                         rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
2717                                                 }
2718                                         }
2719                                         break;
2720
2721                                 case 0xfd:
2722                                         rtw_write8(padapter, 0xc50, arg);
2723                                         rtw_write8(padapter, 0xc58, arg);
2724                                         break;
2725                                 case 0xfe:
2726                                         break;
2727                                 case 0xff:
2728                                         {
2729                                         }
2730                                         break;
2731                         }
2732                         break;
2733                 default:
2734                         break;
2735         }
2736
2737
2738         return 0;
2739
2740 }
2741
2742 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2743 {
2744         uint ret = 0;
2745         struct adapter *padapter = rtw_netdev_priv(dev);
2746
2747         switch (name) {
2748         case IEEE_PARAM_WPA_ENABLED:
2749
2750                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
2751
2752                 /* ret = ieee80211_wpa_enable(ieee, value); */
2753
2754                 switch ((value)&0xff) {
2755                 case 1: /* WPA */
2756                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2757                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
2758                         break;
2759                 case 2: /* WPA2 */
2760                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2761                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
2762                         break;
2763                 }
2764
2765                 break;
2766
2767         case IEEE_PARAM_TKIP_COUNTERMEASURES:
2768                 /* ieee->tkip_countermeasures =value; */
2769                 break;
2770
2771         case IEEE_PARAM_DROP_UNENCRYPTED:
2772         {
2773                 /* HACK:
2774                  *
2775                  * wpa_supplicant calls set_wpa_enabled when the driver
2776                  * is loaded and unloaded, regardless of if WPA is being
2777                  * used.  No other calls are made which can be used to
2778                  * determine if encryption will be used or not prior to
2779                  * association being expected.  If encryption is not being
2780                  * used, drop_unencrypted is set to false, else true -- we
2781                  * can use this to determine if the CAP_PRIVACY_ON bit should
2782                  * be set.
2783                  */
2784                 break;
2785
2786         }
2787         case IEEE_PARAM_PRIVACY_INVOKED:
2788
2789                 /* ieee->privacy_invoked =value; */
2790
2791                 break;
2792
2793         case IEEE_PARAM_AUTH_ALGS:
2794
2795                 ret = wpa_set_auth_algs(dev, value);
2796
2797                 break;
2798
2799         case IEEE_PARAM_IEEE_802_1X:
2800
2801                 /* ieee->ieee802_1x =value; */
2802
2803                 break;
2804
2805         case IEEE_PARAM_WPAX_SELECT:
2806
2807                 /*  added for WPA2 mixed mode */
2808                 /*
2809                 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2810                 ieee->wpax_type_set = 1;
2811                 ieee->wpax_type_notify = value;
2812                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2813                 */
2814
2815                 break;
2816
2817         default:
2818
2819
2820
2821                 ret = -EOPNOTSUPP;
2822
2823
2824                 break;
2825
2826         }
2827
2828         return ret;
2829
2830 }
2831
2832 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2833 {
2834         int ret = 0;
2835         struct adapter *padapter = rtw_netdev_priv(dev);
2836
2837         switch (command) {
2838         case IEEE_MLME_STA_DEAUTH:
2839
2840                 if (!rtw_set_802_11_disassociate(padapter))
2841                         ret = -1;
2842
2843                 break;
2844
2845         case IEEE_MLME_STA_DISASSOC:
2846
2847                 if (!rtw_set_802_11_disassociate(padapter))
2848                         ret = -1;
2849
2850                 break;
2851
2852         default:
2853                 ret = -EOPNOTSUPP;
2854                 break;
2855         }
2856
2857         return ret;
2858
2859 }
2860
2861 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2862 {
2863         struct ieee_param *param;
2864         uint ret = 0;
2865
2866         /* down(&ieee->wx_sem); */
2867
2868         if (!p->pointer || p->length != sizeof(struct ieee_param))
2869                 return -EINVAL;
2870
2871         param = rtw_malloc(p->length);
2872         if (param == NULL)
2873                 return -ENOMEM;
2874
2875         if (copy_from_user(param, p->pointer, p->length)) {
2876                 kfree(param);
2877                 return -EFAULT;
2878         }
2879
2880         switch (param->cmd) {
2881
2882         case IEEE_CMD_SET_WPA_PARAM:
2883                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
2884                 break;
2885
2886         case IEEE_CMD_SET_WPA_IE:
2887                 /* ret = wpa_set_wpa_ie(dev, param, p->length); */
2888                 ret =  rtw_set_wpa_ie(rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
2889                 break;
2890
2891         case IEEE_CMD_SET_ENCRYPTION:
2892                 ret = wpa_set_encryption(dev, param, p->length);
2893                 break;
2894
2895         case IEEE_CMD_MLME:
2896                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
2897                 break;
2898
2899         default:
2900                 ret = -EOPNOTSUPP;
2901                 break;
2902
2903         }
2904
2905         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2906                 ret = -EFAULT;
2907
2908         kfree(param);
2909
2910         /* up(&ieee->wx_sem); */
2911         return ret;
2912 }
2913
2914 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
2915 {
2916         int ret = 0;
2917         u32 wep_key_idx, wep_key_len, wep_total_len;
2918         struct ndis_802_11_wep   *pwep = NULL;
2919         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
2920         struct adapter *padapter = rtw_netdev_priv(dev);
2921         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2922         struct security_priv *psecuritypriv = &(padapter->securitypriv);
2923         struct sta_priv *pstapriv = &padapter->stapriv;
2924         char *txkey = padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey;
2925         char *rxkey = padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey;
2926         char *grpkey = psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey;
2927
2928         param->u.crypt.err = 0;
2929         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2930
2931         /* sizeof(struct ieee_param) = 64 bytes; */
2932         /* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
2933         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
2934                 ret =  -EINVAL;
2935                 goto exit;
2936         }
2937
2938         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2939             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2940             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
2941                 if (param->u.crypt.idx >= WEP_KEYS) {
2942                         ret = -EINVAL;
2943                         goto exit;
2944                 }
2945         } else {
2946                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2947                 if (!psta)
2948                         /* ret = -EINVAL; */
2949                         goto exit;
2950         }
2951
2952         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
2953                 /* todo:clear default encryption keys */
2954
2955                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2956                 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
2957                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
2958                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2959
2960                 goto exit;
2961         }
2962
2963
2964         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
2965                 wep_key_idx = param->u.crypt.idx;
2966                 wep_key_len = param->u.crypt.key_len;
2967
2968                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
2969                         ret = -EINVAL;
2970                         goto exit;
2971                 }
2972
2973
2974                 if (wep_key_len > 0) {
2975                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
2976                         wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
2977                         pwep = kzalloc(wep_total_len, GFP_KERNEL);
2978                         if (!pwep)
2979                                 goto exit;
2980
2981                         pwep->key_length = wep_key_len;
2982                         pwep->length = wep_total_len;
2983
2984                 }
2985
2986                 pwep->key_index = wep_key_idx;
2987
2988                 memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
2989
2990                 if (param->u.crypt.set_tx) {
2991                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
2992                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
2993                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
2994                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2995
2996                         if (pwep->key_length == 13) {
2997                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
2998                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2999                         }
3000
3001
3002                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
3003
3004                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
3005
3006                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
3007
3008                         rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 1);
3009                 } else {
3010                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
3011                         /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
3012
3013                         memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
3014
3015                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
3016
3017                         rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 0);
3018                 }
3019
3020                 goto exit;
3021
3022         }
3023
3024
3025         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
3026                 if (param->u.crypt.set_tx == 1) {
3027                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3028                                 memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3029
3030                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3031                                 if (param->u.crypt.key_len == 13)
3032                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
3033
3034                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3035                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
3036
3037                                 memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3038
3039                                 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3040                                 /* set mic key */
3041                                 memcpy(txkey, &(param->u.crypt.key[16]), 8);
3042                                 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
3043
3044                                 psecuritypriv->busetkipkey = true;
3045
3046                         }
3047                         else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3048                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
3049
3050                                 memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3051                         } else {
3052                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3053                         }
3054
3055                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
3056
3057                         psecuritypriv->binstallGrpkey = true;
3058
3059                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
3060
3061                         rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
3062
3063                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
3064                         if (pbcmc_sta) {
3065                                 pbcmc_sta->ieee8021x_blocked = false;
3066                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
3067                         }
3068                 }
3069
3070                 goto exit;
3071
3072         }
3073
3074         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
3075                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3076                         if (param->u.crypt.set_tx == 1) {
3077                                 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3078
3079                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3080                                         psta->dot118021XPrivacy = _WEP40_;
3081                                         if (param->u.crypt.key_len == 13)
3082                                                 psta->dot118021XPrivacy = _WEP104_;
3083                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3084                                         psta->dot118021XPrivacy = _TKIP_;
3085
3086                                         /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3087                                         /* set mic key */
3088                                         memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
3089                                         memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
3090
3091                                         psecuritypriv->busetkipkey = true;
3092
3093                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3094
3095                                         psta->dot118021XPrivacy = _AES_;
3096                                 } else {
3097                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
3098                                 }
3099
3100                                 rtw_ap_set_pairwise_key(padapter, psta);
3101
3102                                 psta->ieee8021x_blocked = false;
3103
3104                         } else { /* group key??? */
3105                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3106                                         memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3107
3108                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3109                                         if (param->u.crypt.key_len == 13)
3110                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
3111                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3112                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
3113
3114                                         memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3115
3116                                         /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3117                                         /* set mic key */
3118                                         memcpy(txkey, &(param->u.crypt.key[16]), 8);
3119                                         memcpy(rxkey, &(param->u.crypt.key[24]), 8);
3120
3121                                         psecuritypriv->busetkipkey = true;
3122
3123                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3124                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
3125
3126                                         memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
3127                                 } else {
3128                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3129                                 }
3130
3131                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
3132
3133                                 psecuritypriv->binstallGrpkey = true;
3134
3135                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
3136
3137                                 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
3138
3139                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
3140                                 if (pbcmc_sta) {
3141                                         pbcmc_sta->ieee8021x_blocked = false;
3142                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
3143                                 }
3144                         }
3145                 }
3146         }
3147
3148 exit:
3149         kfree(pwep);
3150
3151         return ret;
3152
3153 }
3154
3155 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
3156 {
3157         int ret = 0;
3158         struct adapter *padapter = rtw_netdev_priv(dev);
3159         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3160         struct sta_priv *pstapriv = &padapter->stapriv;
3161         unsigned char *pbuf = param->u.bcn_ie.buf;
3162
3163         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3164                 return -EINVAL;
3165
3166         memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
3167
3168         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
3169                 pstapriv->max_num_sta = NUM_STA;
3170
3171
3172         if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
3173                 ret = 0;
3174         else
3175                 ret = -EINVAL;
3176
3177
3178         return ret;
3179
3180 }
3181
3182 static void rtw_hostapd_sta_flush(struct net_device *dev)
3183 {
3184         /* _irqL irqL; */
3185         /* struct list_head     *phead, *plist; */
3186         /* struct sta_info *psta = NULL; */
3187         struct adapter *padapter = rtw_netdev_priv(dev);
3188         /* struct sta_priv *pstapriv = &padapter->stapriv; */
3189
3190         flush_all_cam_entry(padapter);  /* clear CAM */
3191
3192         rtw_sta_flush(padapter);
3193 }
3194
3195 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
3196 {
3197         int ret = 0;
3198         struct sta_info *psta = NULL;
3199         struct adapter *padapter = rtw_netdev_priv(dev);
3200         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3201         struct sta_priv *pstapriv = &padapter->stapriv;
3202
3203         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3204                 return -EINVAL;
3205
3206         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3207             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3208             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3209                 return -EINVAL;
3210         }
3211
3212 /*
3213         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3214         if (psta)
3215         {
3216                 spin_lock_bh(&(pstapriv->sta_hash_lock));
3217                 rtw_free_stainfo(padapter,  psta);
3218                 spin_unlock_bh(&(pstapriv->sta_hash_lock));
3219
3220                 psta = NULL;
3221         }
3222 */
3223         /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
3224         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3225         if (psta) {
3226                 int flags = param->u.add_sta.flags;
3227
3228                 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
3229
3230                 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
3231
3232
3233                 /* check wmm cap. */
3234                 if (WLAN_STA_WME&flags)
3235                         psta->qos_option = 1;
3236                 else
3237                         psta->qos_option = 0;
3238
3239                 if (pmlmepriv->qospriv.qos_option == 0)
3240                         psta->qos_option = 0;
3241
3242                 /* chec 802.11n ht cap. */
3243                 if (WLAN_STA_HT&flags) {
3244                         psta->htpriv.ht_option = true;
3245                         psta->qos_option = 1;
3246                         memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct ieee80211_ht_cap));
3247                 } else {
3248                         psta->htpriv.ht_option = false;
3249                 }
3250
3251                 if (pmlmepriv->htpriv.ht_option == false)
3252                         psta->htpriv.ht_option = false;
3253
3254                 update_sta_info_apmode(padapter, psta);
3255
3256
3257         } else {
3258                 ret = -ENOMEM;
3259         }
3260
3261         return ret;
3262
3263 }
3264
3265 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
3266 {
3267         int ret = 0;
3268         struct sta_info *psta = NULL;
3269         struct adapter *padapter = rtw_netdev_priv(dev);
3270         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3271         struct sta_priv *pstapriv = &padapter->stapriv;
3272
3273         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3274                 return -EINVAL;
3275
3276         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3277             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3278             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3279                 return -EINVAL;
3280         }
3281
3282         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3283         if (psta) {
3284                 u8 updated = false;
3285
3286                 spin_lock_bh(&pstapriv->asoc_list_lock);
3287                 if (list_empty(&psta->asoc_list) == false) {
3288                         list_del_init(&psta->asoc_list);
3289                         pstapriv->asoc_list_cnt--;
3290                         updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
3291
3292                 }
3293                 spin_unlock_bh(&pstapriv->asoc_list_lock);
3294
3295                 associated_clients_update(padapter, updated);
3296
3297                 psta = NULL;
3298
3299         }
3300
3301         return ret;
3302
3303 }
3304
3305 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
3306 {
3307         int ret = 0;
3308         struct sta_info *psta = NULL;
3309         struct adapter *padapter = rtw_netdev_priv(dev);
3310         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3311         struct sta_priv *pstapriv = &padapter->stapriv;
3312         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
3313         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
3314
3315         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3316                 return -EINVAL;
3317
3318         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
3319             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
3320             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
3321                 return -EINVAL;
3322         }
3323
3324         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
3325         if (psta) {
3326                 psta_data->aid = (u16)psta->aid;
3327                 psta_data->capability = psta->capability;
3328                 psta_data->flags = psta->flags;
3329
3330 /*
3331                 nonerp_set : BIT(0)
3332                 no_short_slot_time_set : BIT(1)
3333                 no_short_preamble_set : BIT(2)
3334                 no_ht_gf_set : BIT(3)
3335                 no_ht_set : BIT(4)
3336                 ht_20mhz_set : BIT(5)
3337 */
3338
3339                 psta_data->sta_set = ((psta->nonerp_set) |
3340                                                          (psta->no_short_slot_time_set << 1) |
3341                                                          (psta->no_short_preamble_set << 2) |
3342                                                          (psta->no_ht_gf_set << 3) |
3343                                                          (psta->no_ht_set << 4) |
3344                                                          (psta->ht_20mhz_set << 5));
3345
3346                 psta_data->tx_supp_rates_len =  psta->bssratelen;
3347                 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
3348                 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
3349                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
3350                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
3351                 psta_data->rx_drops = psta->sta_stats.rx_drops;
3352
3353                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
3354                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
3355                 psta_data->tx_drops = psta->sta_stats.tx_drops;
3356
3357
3358         } else {
3359                 ret = -1;
3360         }
3361
3362         return ret;
3363
3364 }
3365
3366 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
3367 {
3368         int ret = 0;
3369         struct sta_info *psta = NULL;
3370         struct adapter *padapter = rtw_netdev_priv(dev);
3371         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3372         struct sta_priv *pstapriv = &padapter->stapriv;
3373
3374         if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3375                 return -EINVAL;
3376
3377         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3378             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3379             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3380                 return -EINVAL;
3381         }
3382
3383         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3384         if (psta) {
3385                 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC)) {
3386                         int wpa_ie_len;
3387                         int copy_len;
3388
3389                         wpa_ie_len = psta->wpa_ie[1];
3390
3391                         copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
3392
3393                         param->u.wpa_ie.len = copy_len;
3394
3395                         memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
3396                 }
3397         } else {
3398                 ret = -1;
3399         }
3400
3401         return ret;
3402
3403 }
3404
3405 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
3406 {
3407         int ret = 0;
3408         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
3409         struct adapter *padapter = rtw_netdev_priv(dev);
3410         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3411         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3412         int ie_len;
3413
3414         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3415                 return -EINVAL;
3416
3417         ie_len = len-12-2;/*  12 = param header, 2:no packed */
3418
3419
3420         kfree(pmlmepriv->wps_beacon_ie);
3421         pmlmepriv->wps_beacon_ie = NULL;
3422
3423         if (ie_len > 0) {
3424                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
3425                 pmlmepriv->wps_beacon_ie_len = ie_len;
3426                 if (!pmlmepriv->wps_beacon_ie)
3427                         return -EINVAL;
3428
3429                 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
3430
3431                 update_beacon(padapter, WLAN_EID_VENDOR_SPECIFIC, wps_oui, true);
3432
3433                 pmlmeext->bstart_bss = true;
3434         }
3435
3436
3437         return ret;
3438
3439 }
3440
3441 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
3442 {
3443         int ret = 0;
3444         struct adapter *padapter = rtw_netdev_priv(dev);
3445         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3446         int ie_len;
3447
3448         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3449                 return -EINVAL;
3450
3451         ie_len = len-12-2;/*  12 = param header, 2:no packed */
3452
3453
3454         kfree(pmlmepriv->wps_probe_resp_ie);
3455         pmlmepriv->wps_probe_resp_ie = NULL;
3456
3457         if (ie_len > 0) {
3458                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
3459                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
3460                 if (!pmlmepriv->wps_probe_resp_ie)
3461                         return -EINVAL;
3462
3463                 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
3464         }
3465
3466
3467         return ret;
3468
3469 }
3470
3471 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
3472 {
3473         int ret = 0;
3474         struct adapter *padapter = rtw_netdev_priv(dev);
3475         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3476         int ie_len;
3477
3478         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3479                 return -EINVAL;
3480
3481         ie_len = len-12-2;/*  12 = param header, 2:no packed */
3482
3483
3484         kfree(pmlmepriv->wps_assoc_resp_ie);
3485         pmlmepriv->wps_assoc_resp_ie = NULL;
3486
3487         if (ie_len > 0) {
3488                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
3489                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
3490                 if (!pmlmepriv->wps_assoc_resp_ie)
3491                         return -EINVAL;
3492
3493                 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
3494         }
3495
3496
3497         return ret;
3498
3499 }
3500
3501 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
3502 {
3503         int ret = 0;
3504         struct adapter *adapter = rtw_netdev_priv(dev);
3505         struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
3506         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
3507         struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
3508         int ie_len;
3509         u8 *ssid_ie;
3510         char ssid[NDIS_802_11_LENGTH_SSID + 1];
3511         signed int ssid_len;
3512         u8 ignore_broadcast_ssid;
3513
3514         if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
3515                 return -EPERM;
3516
3517         if (param->u.bcn_ie.reserved[0] != 0xea)
3518                 return -EINVAL;
3519
3520         mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
3521
3522         ie_len = len-12-2;/*  12 = param header, 2:no packed */
3523         ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
3524
3525         if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
3526                 struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network;
3527                 struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network;
3528
3529                 memcpy(ssid, ssid_ie+2, ssid_len);
3530                 ssid[ssid_len] = 0x0;
3531
3532                 memcpy(pbss_network->ssid.ssid, (void *)ssid, ssid_len);
3533                 pbss_network->ssid.ssid_length = ssid_len;
3534                 memcpy(pbss_network_ext->ssid.ssid, (void *)ssid, ssid_len);
3535                 pbss_network_ext->ssid.ssid_length = ssid_len;
3536         }
3537
3538         return ret;
3539 }
3540
3541 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
3542 {
3543         struct adapter *padapter = rtw_netdev_priv(dev);
3544         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3545
3546         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3547                 return -EINVAL;
3548
3549         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3550             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3551             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3552                 return -EINVAL;
3553         }
3554
3555         rtw_acl_remove_sta(padapter, param->sta_addr);
3556         return 0;
3557
3558 }
3559
3560 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
3561 {
3562         struct adapter *padapter = rtw_netdev_priv(dev);
3563         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3564
3565         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3566                 return -EINVAL;
3567
3568         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3569             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3570             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3571                 return -EINVAL;
3572         }
3573
3574         return rtw_acl_add_sta(padapter, param->sta_addr);
3575
3576 }
3577
3578 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
3579 {
3580         int ret = 0;
3581         struct adapter *padapter = rtw_netdev_priv(dev);
3582         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3583
3584         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3585                 return -EINVAL;
3586
3587         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
3588
3589         return ret;
3590 }
3591
3592 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
3593 {
3594         struct ieee_param *param;
3595         int ret = 0;
3596         struct adapter *padapter = rtw_netdev_priv(dev);
3597
3598         /*
3599         * this function is expect to call in master mode, which allows no power saving
3600         * so, we just check hw_init_completed
3601         */
3602
3603         if (!padapter->hw_init_completed)
3604                 return -EPERM;
3605
3606         if (!p->pointer || p->length != sizeof(*param))
3607                 return -EINVAL;
3608
3609         param = rtw_malloc(p->length);
3610         if (param == NULL)
3611                 return -ENOMEM;
3612
3613         if (copy_from_user(param, p->pointer, p->length)) {
3614                 kfree(param);
3615                 return -EFAULT;
3616         }
3617
3618         switch (param->cmd) {
3619         case RTL871X_HOSTAPD_FLUSH:
3620
3621                 rtw_hostapd_sta_flush(dev);
3622
3623                 break;
3624
3625         case RTL871X_HOSTAPD_ADD_STA:
3626
3627                 ret = rtw_add_sta(dev, param);
3628
3629                 break;
3630
3631         case RTL871X_HOSTAPD_REMOVE_STA:
3632
3633                 ret = rtw_del_sta(dev, param);
3634
3635                 break;
3636
3637         case RTL871X_HOSTAPD_SET_BEACON:
3638
3639                 ret = rtw_set_beacon(dev, param, p->length);
3640
3641                 break;
3642
3643         case RTL871X_SET_ENCRYPTION:
3644
3645                 ret = rtw_set_encryption(dev, param, p->length);
3646
3647                 break;
3648
3649         case RTL871X_HOSTAPD_GET_WPAIE_STA:
3650
3651                 ret = rtw_get_sta_wpaie(dev, param);
3652
3653                 break;
3654
3655         case RTL871X_HOSTAPD_SET_WPS_BEACON:
3656
3657                 ret = rtw_set_wps_beacon(dev, param, p->length);
3658
3659                 break;
3660
3661         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
3662
3663                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
3664
3665                 break;
3666
3667         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
3668
3669                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
3670
3671                 break;
3672
3673         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
3674
3675                 ret = rtw_set_hidden_ssid(dev, param, p->length);
3676
3677                 break;
3678
3679         case RTL871X_HOSTAPD_GET_INFO_STA:
3680
3681                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
3682
3683                 break;
3684
3685         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
3686
3687                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
3688
3689                 break;
3690
3691         case RTL871X_HOSTAPD_ACL_ADD_STA:
3692
3693                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
3694
3695                 break;
3696
3697         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
3698
3699                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
3700
3701                 break;
3702
3703         default:
3704                 ret = -EOPNOTSUPP;
3705                 break;
3706
3707         }
3708
3709         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3710                 ret = -EFAULT;
3711
3712         kfree(param);
3713         return ret;
3714 }
3715
3716 static int rtw_wx_set_priv(struct net_device *dev,
3717                                 struct iw_request_info *info,
3718                                 union iwreq_data *awrq,
3719                                 char *extra)
3720 {
3721
3722 #ifdef DEBUG_RTW_WX_SET_PRIV
3723         char *ext_dbg;
3724 #endif
3725
3726         int ret = 0;
3727         int len = 0;
3728         char *ext;
3729
3730         struct adapter *padapter = rtw_netdev_priv(dev);
3731         struct iw_point *dwrq = (struct iw_point *)awrq;
3732
3733         if (dwrq->length == 0)
3734                 return -EFAULT;
3735
3736         len = dwrq->length;
3737         ext = vmalloc(len);
3738         if (!ext)
3739                 return -ENOMEM;
3740
3741         if (copy_from_user(ext, dwrq->pointer, len)) {
3742                 vfree(ext);
3743                 return -EFAULT;
3744         }
3745
3746         #ifdef DEBUG_RTW_WX_SET_PRIV
3747         ext_dbg = vmalloc(len);
3748         if (!ext_dbg) {
3749                 vfree(ext, len);
3750                 return -ENOMEM;
3751         }
3752
3753         memcpy(ext_dbg, ext, len);
3754         #endif
3755
3756         /* added for wps2.0 @20110524 */
3757         if (dwrq->flags == 0x8766 && len > 8) {
3758                 u32 cp_sz;
3759                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3760                 u8 *probereq_wpsie = ext;
3761                 int probereq_wpsie_len = len;
3762                 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
3763
3764                 if ((WLAN_EID_VENDOR_SPECIFIC == probereq_wpsie[0]) &&
3765                         (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
3766                         cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
3767
3768                         if (pmlmepriv->wps_probe_req_ie) {
3769                                 pmlmepriv->wps_probe_req_ie_len = 0;
3770                                 kfree(pmlmepriv->wps_probe_req_ie);
3771                                 pmlmepriv->wps_probe_req_ie = NULL;
3772                         }
3773
3774                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
3775                         if (pmlmepriv->wps_probe_req_ie == NULL) {
3776                                 printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
3777                                 ret =  -EINVAL;
3778                                 goto FREE_EXT;
3779
3780                         }
3781
3782                         memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
3783                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
3784
3785                 }
3786
3787                 goto FREE_EXT;
3788
3789         }
3790
3791         if (len >= WEXT_CSCAN_HEADER_SIZE
3792                 && !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
3793                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
3794                 goto FREE_EXT;
3795         }
3796
3797 FREE_EXT:
3798
3799         vfree(ext);
3800         #ifdef DEBUG_RTW_WX_SET_PRIV
3801         vfree(ext_dbg);
3802         #endif
3803
3804         return ret;
3805
3806 }
3807
3808 static int rtw_pm_set(struct net_device *dev,
3809                       struct iw_request_info *info,
3810                       union iwreq_data *wrqu, char *extra)
3811 {
3812         int ret = 0;
3813         unsigned        mode = 0;
3814         struct adapter *padapter = rtw_netdev_priv(dev);
3815
3816         if (!memcmp(extra, "lps =", 4)) {
3817                 sscanf(extra+4, "%u", &mode);
3818                 ret = rtw_pm_set_lps(padapter, mode);
3819         } else if (!memcmp(extra, "ips =", 4)) {
3820                 sscanf(extra+4, "%u", &mode);
3821                 ret = rtw_pm_set_ips(padapter, mode);
3822         } else {
3823                 ret = -EINVAL;
3824         }
3825
3826         return ret;
3827 }
3828
3829 static int rtw_test(
3830         struct net_device *dev,
3831         struct iw_request_info *info,
3832         union iwreq_data *wrqu, char *extra)
3833 {
3834         u32 len;
3835         u8 *pbuf, *pch;
3836         char *ptmp;
3837         u8 *delim = ",";
3838         struct adapter *padapter = rtw_netdev_priv(dev);
3839
3840
3841         len = wrqu->data.length;
3842
3843         pbuf = rtw_zmalloc(len);
3844         if (!pbuf)
3845                 return -ENOMEM;
3846
3847         if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
3848                 kfree(pbuf);
3849                 return -EFAULT;
3850         }
3851
3852         ptmp = (char *)pbuf;
3853         pch = strsep(&ptmp, delim);
3854         if ((pch == NULL) || (strlen(pch) == 0)) {
3855                 kfree(pbuf);
3856                 return -EFAULT;
3857         }
3858
3859         if (strcmp(pch, "bton") == 0)
3860                 hal_btcoex_SetManualControl(padapter, false);
3861
3862         if (strcmp(pch, "btoff") == 0)
3863                 hal_btcoex_SetManualControl(padapter, true);
3864
3865         if (strcmp(pch, "h2c") == 0) {
3866                 u8 param[8];
3867                 u8 count = 0;
3868                 u32 tmp;
3869                 u8 i;
3870                 u32 pos;
3871                 s32 ret;
3872
3873
3874                 do {
3875                         pch = strsep(&ptmp, delim);
3876                         if ((pch == NULL) || (strlen(pch) == 0))
3877                                 break;
3878
3879                         sscanf(pch, "%x", &tmp);
3880                         param[count++] = (u8)tmp;
3881                 } while (count < 8);
3882
3883                 if (count == 0) {
3884                         kfree(pbuf);
3885                         return -EFAULT;
3886                 }
3887
3888                 ret = rtw_hal_fill_h2c_cmd(padapter, param[0], count-1, &param[1]);
3889
3890                 pos = sprintf(extra, "H2C ID = 0x%02x content =", param[0]);
3891                 for (i = 1; i < count; i++)
3892                         pos += sprintf(extra+pos, "%02x,", param[i]);
3893                 extra[pos] = 0;
3894                 pos--;
3895                 pos += sprintf(extra+pos, " %s", ret == _FAIL?"FAIL":"OK");
3896
3897                 wrqu->data.length = strlen(extra) + 1;
3898         }
3899
3900         kfree(pbuf);
3901         return 0;
3902 }
3903
3904 static iw_handler rtw_handlers[] = {
3905         NULL,                                   /* SIOCSIWCOMMIT */
3906         rtw_wx_get_name,                /* SIOCGIWNAME */
3907         dummy,                                  /* SIOCSIWNWID */
3908         dummy,                                  /* SIOCGIWNWID */
3909         rtw_wx_set_freq,                /* SIOCSIWFREQ */
3910         rtw_wx_get_freq,                /* SIOCGIWFREQ */
3911         rtw_wx_set_mode,                /* SIOCSIWMODE */
3912         rtw_wx_get_mode,                /* SIOCGIWMODE */
3913         dummy,                                  /* SIOCSIWSENS */
3914         rtw_wx_get_sens,                /* SIOCGIWSENS */
3915         NULL,                                   /* SIOCSIWRANGE */
3916         rtw_wx_get_range,               /* SIOCGIWRANGE */
3917         rtw_wx_set_priv,                /* SIOCSIWPRIV */
3918         NULL,                                   /* SIOCGIWPRIV */
3919         NULL,                                   /* SIOCSIWSTATS */
3920         NULL,                                   /* SIOCGIWSTATS */
3921         dummy,                                  /* SIOCSIWSPY */
3922         dummy,                                  /* SIOCGIWSPY */
3923         NULL,                                   /* SIOCGIWTHRSPY */
3924         NULL,                                   /* SIOCWIWTHRSPY */
3925         rtw_wx_set_wap,         /* SIOCSIWAP */
3926         rtw_wx_get_wap,         /* SIOCGIWAP */
3927         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
3928         dummy,                                  /* SIOCGIWAPLIST -- depricated */
3929         rtw_wx_set_scan,                /* SIOCSIWSCAN */
3930         rtw_wx_get_scan,                /* SIOCGIWSCAN */
3931         rtw_wx_set_essid,               /* SIOCSIWESSID */
3932         rtw_wx_get_essid,               /* SIOCGIWESSID */
3933         dummy,                                  /* SIOCSIWNICKN */
3934         rtw_wx_get_nick,                /* SIOCGIWNICKN */
3935         NULL,                                   /* -- hole -- */
3936         NULL,                                   /* -- hole -- */
3937         rtw_wx_set_rate,                /* SIOCSIWRATE */
3938         rtw_wx_get_rate,                /* SIOCGIWRATE */
3939         rtw_wx_set_rts,                 /* SIOCSIWRTS */
3940         rtw_wx_get_rts,                 /* SIOCGIWRTS */
3941         rtw_wx_set_frag,                /* SIOCSIWFRAG */
3942         rtw_wx_get_frag,                /* SIOCGIWFRAG */
3943         dummy,                                  /* SIOCSIWTXPOW */
3944         dummy,                                  /* SIOCGIWTXPOW */
3945         dummy,                                  /* SIOCSIWRETRY */
3946         rtw_wx_get_retry,               /* SIOCGIWRETRY */
3947         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
3948         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
3949         dummy,                                  /* SIOCSIWPOWER */
3950         rtw_wx_get_power,               /* SIOCGIWPOWER */
3951         NULL,                                   /*---hole---*/
3952         NULL,                                   /*---hole---*/
3953         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
3954         NULL,                                   /* SIOCGWGENIE */
3955         rtw_wx_set_auth,                /* SIOCSIWAUTH */
3956         NULL,                                   /* SIOCGIWAUTH */
3957         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
3958         NULL,                                   /* SIOCGIWENCODEEXT */
3959         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
3960         NULL,                                   /*---hole---*/
3961 };
3962
3963 static const struct iw_priv_args rtw_private_args[] = {
3964         {
3965                 SIOCIWFIRSTPRIV + 0x0,
3966                 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
3967         },
3968         {
3969                 SIOCIWFIRSTPRIV + 0x1,
3970                 IW_PRIV_TYPE_CHAR | 0x7FF,
3971                 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
3972         },
3973         {
3974                 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
3975         },
3976         {
3977                 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
3978         },
3979         {
3980                 SIOCIWFIRSTPRIV + 0x4,
3981                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
3982         },
3983         {
3984                 SIOCIWFIRSTPRIV + 0x5,
3985                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
3986         },
3987         {
3988                 SIOCIWFIRSTPRIV + 0x6,
3989                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
3990         },
3991 /* for PLATFORM_MT53XX */
3992         {
3993                 SIOCIWFIRSTPRIV + 0x7,
3994                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
3995         },
3996         {
3997                 SIOCIWFIRSTPRIV + 0x8,
3998                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
3999         },
4000         {
4001                 SIOCIWFIRSTPRIV + 0x9,
4002                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
4003         },
4004
4005 /* for RTK_DMP_PLATFORM */
4006         {
4007                 SIOCIWFIRSTPRIV + 0xA,
4008                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
4009         },
4010
4011         {
4012                 SIOCIWFIRSTPRIV + 0xB,
4013                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
4014         },
4015         {
4016                 SIOCIWFIRSTPRIV + 0xC,
4017                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
4018         },
4019         {
4020                 SIOCIWFIRSTPRIV + 0xD,
4021                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
4022         },
4023         {
4024                 SIOCIWFIRSTPRIV + 0x10,
4025                 IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
4026         },
4027         {
4028                 SIOCIWFIRSTPRIV + 0x11,
4029                 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "p2p_get"
4030         },
4031         {
4032                 SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
4033         },
4034         {
4035                 SIOCIWFIRSTPRIV + 0x13,
4036                 IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, "p2p_get2"
4037         },
4038         {
4039                 SIOCIWFIRSTPRIV + 0x14,
4040                 IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
4041         },
4042         {
4043                 SIOCIWFIRSTPRIV + 0x15,
4044                 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, "tdls_get"
4045         },
4046         {
4047                 SIOCIWFIRSTPRIV + 0x16,
4048                 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
4049         },
4050
4051         {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
4052         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
4053         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
4054         {
4055                 SIOCIWFIRSTPRIV + 0x1D,
4056                 IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
4057         },
4058 };
4059
4060 static iw_handler rtw_private_handler[] = {
4061         rtw_wx_write32,                                 /* 0x00 */
4062         rtw_wx_read32,                                  /* 0x01 */
4063         rtw_drvext_hdl,                                 /* 0x02 */
4064         NULL,                                           /* 0x03 */
4065
4066 /*  for MM DTV platform */
4067         rtw_get_ap_info,                                        /* 0x04 */
4068
4069         rtw_set_pid,                                            /* 0x05 */
4070         rtw_wps_start,                                  /* 0x06 */
4071
4072 /*  for PLATFORM_MT53XX */
4073         rtw_wx_get_sensitivity,                 /* 0x07 */
4074         rtw_wx_set_mtk_wps_probe_ie,    /* 0x08 */
4075         rtw_wx_set_mtk_wps_ie,                  /* 0x09 */
4076
4077 /*  for RTK_DMP_PLATFORM */
4078 /*  Set Channel depend on the country code */
4079         rtw_wx_set_channel_plan,                /* 0x0A */
4080
4081         rtw_dbg_port,                                   /* 0x0B */
4082         rtw_wx_write_rf,                                        /* 0x0C */
4083         rtw_wx_read_rf,                                 /* 0x0D */
4084         rtw_wx_priv_null,                               /* 0x0E */
4085         rtw_wx_priv_null,                               /* 0x0F */
4086         rtw_p2p_set,                                    /* 0x10 */
4087         rtw_p2p_get,                                    /* 0x11 */
4088         NULL,                                                   /* 0x12 */
4089         rtw_p2p_get2,                                   /* 0x13 */
4090
4091         NULL,                                           /* 0x14 */
4092         NULL,                                           /* 0x15 */
4093
4094         rtw_pm_set,                                             /* 0x16 */
4095         rtw_wx_priv_null,                               /* 0x17 */
4096         rtw_rereg_nd_name,                              /* 0x18 */
4097         rtw_wx_priv_null,                               /* 0x19 */
4098         NULL,                                           /* 0x1A */
4099         NULL,                                           /* 0x1B */
4100         NULL,                                                   /*  0x1C is reserved for hostapd */
4101         rtw_test,                                               /*  0x1D */
4102 };
4103
4104 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
4105 {
4106         struct adapter *padapter = rtw_netdev_priv(dev);
4107         struct iw_statistics *piwstats = &padapter->iwstats;
4108         int tmp_level = 0;
4109         int tmp_qual = 0;
4110         int tmp_noise = 0;
4111
4112         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
4113                 piwstats->qual.qual = 0;
4114                 piwstats->qual.level = 0;
4115                 piwstats->qual.noise = 0;
4116         } else {
4117                 tmp_level = padapter->recvpriv.signal_strength;
4118                 tmp_qual = padapter->recvpriv.signal_qual;
4119                 tmp_noise = padapter->recvpriv.noise;
4120
4121                 piwstats->qual.level = tmp_level;
4122                 piwstats->qual.qual = tmp_qual;
4123                 piwstats->qual.noise = tmp_noise;
4124         }
4125         piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* IW_QUAL_DBM; */
4126
4127         return &padapter->iwstats;
4128 }
4129
4130 struct iw_handler_def rtw_handlers_def = {
4131         .standard = rtw_handlers,
4132         .num_standard = ARRAY_SIZE(rtw_handlers),
4133 #if defined(CONFIG_WEXT_PRIV)
4134         .private = rtw_private_handler,
4135         .private_args = (struct iw_priv_args *)rtw_private_args,
4136         .num_private = ARRAY_SIZE(rtw_private_handler),
4137         .num_private_args = ARRAY_SIZE(rtw_private_args),
4138 #endif
4139         .get_wireless_stats = rtw_get_wireless_stats,
4140 };
4141
4142 /*  copy from net/wireless/wext.c start */
4143 /* ---------------------------------------------------------------- */
4144 /*
4145  * Calculate size of private arguments
4146  */
4147 static const char iw_priv_type_size[] = {
4148         0,                              /* IW_PRIV_TYPE_NONE */
4149         1,                              /* IW_PRIV_TYPE_BYTE */
4150         1,                              /* IW_PRIV_TYPE_CHAR */
4151         0,                              /* Not defined */
4152         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
4153         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
4154         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
4155         0,                              /* Not defined */
4156 };
4157
4158 static int get_priv_size(__u16 args)
4159 {
4160         int num = args & IW_PRIV_SIZE_MASK;
4161         int type = (args & IW_PRIV_TYPE_MASK) >> 12;
4162
4163         return num * iw_priv_type_size[type];
4164 }
4165 /*  copy from net/wireless/wext.c end */
4166
4167 static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
4168 {
4169         int err = 0;
4170         u8 *input = NULL;
4171         u32 input_len = 0;
4172         const char delim[] = " ";
4173         u8 *output = NULL;
4174         u32 output_len = 0;
4175         u32 count = 0;
4176         u8 *buffer = NULL;
4177         u32 buffer_len = 0;
4178         char *ptr = NULL;
4179         u8 cmdname[17] = {0}; /*  IFNAMSIZ+1 */
4180         u32 cmdlen;
4181         s32 len;
4182         u8 *extra = NULL;
4183         u32 extra_size = 0;
4184
4185         s32 k;
4186         const iw_handler *priv;         /* Private ioctl */
4187         const struct iw_priv_args *priv_args;   /* Private ioctl description */
4188         u32 num_priv_args;                      /* Number of descriptions */
4189         iw_handler handler;
4190         int temp;
4191         int subcmd = 0;                         /* sub-ioctl index */
4192         int offset = 0;                         /* Space for sub-ioctl index */
4193
4194         union iwreq_data wdata;
4195
4196
4197         memcpy(&wdata, wrq_data, sizeof(wdata));
4198
4199         input_len = 2048;
4200         input = rtw_zmalloc(input_len);
4201         if (NULL == input)
4202                 return -ENOMEM;
4203         if (copy_from_user(input, wdata.data.pointer, input_len)) {
4204                 err = -EFAULT;
4205                 goto exit;
4206         }
4207         ptr = input;
4208         len = strlen(input);
4209
4210         sscanf(ptr, "%16s", cmdname);
4211         cmdlen = strlen(cmdname);
4212
4213         /*  skip command string */
4214         if (cmdlen > 0)
4215                 cmdlen += 1; /*  skip one space */
4216         ptr += cmdlen;
4217         len -= cmdlen;
4218
4219         priv = rtw_private_handler;
4220         priv_args = rtw_private_args;
4221         num_priv_args = ARRAY_SIZE(rtw_private_args);
4222
4223         if (num_priv_args == 0) {
4224                 err = -EOPNOTSUPP;
4225                 goto exit;
4226         }
4227
4228         /* Search the correct ioctl */
4229         k = -1;
4230         while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
4231
4232         /* If not found... */
4233         if (k == num_priv_args) {
4234                 err = -EOPNOTSUPP;
4235                 goto exit;
4236         }
4237
4238         /* Watch out for sub-ioctls ! */
4239         if (priv_args[k].cmd < SIOCDEVPRIVATE) {
4240                 int j = -1;
4241
4242                 /* Find the matching *real* ioctl */
4243                 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
4244                         (priv_args[j].set_args != priv_args[k].set_args) ||
4245                         (priv_args[j].get_args != priv_args[k].get_args)));
4246
4247                 /* If not found... */
4248                 if (j == num_priv_args) {
4249                         err = -EINVAL;
4250                         goto exit;
4251                 }
4252
4253                 /* Save sub-ioctl number */
4254                 subcmd = priv_args[k].cmd;
4255                 /* Reserve one int (simplify alignment issues) */
4256                 offset = sizeof(__u32);
4257                 /* Use real ioctl definition from now on */
4258                 k = j;
4259         }
4260
4261         buffer = rtw_zmalloc(4096);
4262         if (NULL == buffer) {
4263                 err = -ENOMEM;
4264                 goto exit;
4265         }
4266
4267         /* If we have to set some data */
4268         if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
4269                 (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
4270                 u8 *str;
4271
4272                 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
4273                 case IW_PRIV_TYPE_BYTE:
4274                         /* Fetch args */
4275                         count = 0;
4276                         do {
4277                                 str = strsep(&ptr, delim);
4278                                 if (NULL == str)
4279                                         break;
4280                                 sscanf(str, "%i", &temp);
4281                                 buffer[count++] = (u8)temp;
4282                         } while (1);
4283                         buffer_len = count;
4284
4285                         /* Number of args to fetch */
4286                         wdata.data.length = count;
4287                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
4288                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
4289
4290                         break;
4291
4292                 case IW_PRIV_TYPE_INT:
4293                         /* Fetch args */
4294                         count = 0;
4295                         do {
4296                                 str = strsep(&ptr, delim);
4297                                 if (NULL == str)
4298                                         break;
4299                                 sscanf(str, "%i", &temp);
4300                                 ((s32 *)buffer)[count++] = (s32)temp;
4301                         } while (1);
4302                         buffer_len = count * sizeof(s32);
4303
4304                         /* Number of args to fetch */
4305                         wdata.data.length = count;
4306                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
4307                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
4308
4309                         break;
4310
4311                 case IW_PRIV_TYPE_CHAR:
4312                         if (len > 0) {
4313                                 /* Size of the string to fetch */
4314                                 wdata.data.length = len;
4315                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
4316                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
4317
4318                                 /* Fetch string */
4319                                 memcpy(buffer, ptr, wdata.data.length);
4320                         } else {
4321                                 wdata.data.length = 1;
4322                                 buffer[0] = '\0';
4323                         }
4324                         buffer_len = wdata.data.length;
4325                         break;
4326
4327                 default:
4328                         err = -1;
4329                         goto exit;
4330                 }
4331
4332                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
4333                         (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
4334                         err = -EINVAL;
4335                         goto exit;
4336                 }
4337         } else { /* if args to set */
4338                 wdata.data.length = 0L;
4339         }
4340
4341         /* Those two tests are important. They define how the driver
4342         * will have to handle the data */
4343         if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
4344                 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
4345                 /* First case : all SET args fit within wrq */
4346                 if (offset)
4347                         wdata.mode = subcmd;
4348                 memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
4349         } else {
4350                 if ((priv_args[k].set_args == 0) &&
4351                         (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
4352                         (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
4353                         /* Second case : no SET args, GET args fit within wrq */
4354                         if (offset)
4355                                 wdata.mode = subcmd;
4356                 } else {
4357                         /* Third case : args won't fit in wrq, or variable number of args */
4358                         if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
4359                                 err = -EFAULT;
4360                                 goto exit;
4361                         }
4362                         wdata.data.flags = subcmd;
4363                 }
4364         }
4365
4366         kfree(input);
4367         input = NULL;
4368
4369         extra_size = 0;
4370         if (IW_IS_SET(priv_args[k].cmd)) {
4371                 /* Size of set arguments */
4372                 extra_size = get_priv_size(priv_args[k].set_args);
4373
4374                 /* Does it fits in iwr ? */
4375                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
4376                         ((extra_size + offset) <= IFNAMSIZ))
4377                         extra_size = 0;
4378         } else {
4379                 /* Size of get arguments */
4380                 extra_size = get_priv_size(priv_args[k].get_args);
4381
4382                 /* Does it fits in iwr ? */
4383                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
4384                         (extra_size <= IFNAMSIZ))
4385                         extra_size = 0;
4386         }
4387
4388         if (extra_size == 0) {
4389                 extra = (u8 *)&wdata;
4390                 kfree(buffer);
4391                 buffer = NULL;
4392         } else
4393                 extra = buffer;
4394
4395         handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
4396         err = handler(dev, NULL, &wdata, extra);
4397
4398         /* If we have to get some data */
4399         if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
4400                 (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
4401                 int j;
4402                 int n = 0;      /* number of args */
4403                 u8 str[20] = {0};
4404
4405                 /* Check where is the returned data */
4406                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
4407                         (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
4408                         n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
4409                 else
4410                         n = wdata.data.length;
4411
4412                 output = rtw_zmalloc(4096);
4413                 if (NULL == output) {
4414                         err =  -ENOMEM;
4415                         goto exit;
4416                 }
4417
4418                 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
4419                 case IW_PRIV_TYPE_BYTE:
4420                         /* Display args */
4421                         for (j = 0; j < n; j++) {
4422                                 len = scnprintf(str, sizeof(str), "%d  ", extra[j]);
4423                                 output_len = strlen(output);
4424                                 if ((output_len + len + 1) > 4096) {
4425                                         err = -E2BIG;
4426                                         goto exit;
4427                                 }
4428                                 memcpy(output+output_len, str, len);
4429                         }
4430                         break;
4431
4432                 case IW_PRIV_TYPE_INT:
4433                         /* Display args */
4434                         for (j = 0; j < n; j++) {
4435                                 len = scnprintf(str, sizeof(str), "%d  ", ((__s32 *)extra)[j]);
4436                                 output_len = strlen(output);
4437                                 if ((output_len + len + 1) > 4096) {
4438                                         err = -E2BIG;
4439                                         goto exit;
4440                                 }
4441                                 memcpy(output+output_len, str, len);
4442                         }
4443                         break;
4444
4445                 case IW_PRIV_TYPE_CHAR:
4446                         /* Display args */
4447                         memcpy(output, extra, n);
4448                         break;
4449
4450                 default:
4451                         err = -1;
4452                         goto exit;
4453                 }
4454
4455                 output_len = strlen(output) + 1;
4456                 wrq_data->data.length = output_len;
4457                 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
4458                         err = -EFAULT;
4459                         goto exit;
4460                 }
4461         } else { /* if args to set */
4462                 wrq_data->data.length = 0;
4463         }
4464
4465 exit:
4466         kfree(input);
4467         kfree(buffer);
4468         kfree(output);
4469
4470         return err;
4471 }
4472
4473 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
4474 {
4475         struct iwreq *wrq = (struct iwreq *)rq;
4476         int ret = 0;
4477
4478         switch (cmd) {
4479         case RTL_IOCTL_WPA_SUPPLICANT:
4480                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
4481                 break;
4482         case RTL_IOCTL_HOSTAPD:
4483                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
4484                 break;
4485         case SIOCDEVPRIVATE:
4486                 ret = rtw_ioctl_wext_private(dev, &wrq->u);
4487                 break;
4488         default:
4489                 ret = -EOPNOTSUPP;
4490                 break;
4491         }
4492
4493         return ret;
4494 }