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