net: wireless: rockchip: add rtl8822be pcie wifi driver
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8822be / os_dep / linux / ioctl_linux.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _IOCTL_LINUX_C_
21
22 #include <drv_types.h>
23 #include <rtw_mp.h>
24 #include <rtw_mp_ioctl.h>
25 #include "../../hal/phydm/phydm_precomp.h"
26
27 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27))
28         #define  iwe_stream_add_event(a, b, c, d, e)  iwe_stream_add_event(b, c, d, e)
29         #define  iwe_stream_add_point(a, b, c, d, e)  iwe_stream_add_point(b, c, d, e)
30 #endif
31
32 #ifdef CONFIG_80211N_HT
33         extern int rtw_ht_enable;
34 #endif
35
36
37 #define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV+30)
38
39 #define SCAN_ITEM_SIZE 768
40 #define MAX_CUSTOM_LEN 64
41 #define RATE_COUNT 4
42
43 #ifdef CONFIG_GLOBAL_UI_PID
44         extern int ui_pid[3];
45 #endif
46
47 /* combo scan */
48 #define WEXT_CSCAN_AMOUNT 9
49 #define WEXT_CSCAN_BUF_LEN              360
50 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
51 #define WEXT_CSCAN_HEADER_SIZE          12
52 #define WEXT_CSCAN_SSID_SECTION         'S'
53 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
54 #define WEXT_CSCAN_NPROBE_SECTION       'N'
55 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
56 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
57 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
58 #define WEXT_CSCAN_TYPE_SECTION         'T'
59
60
61 extern u8 key_2char2num(u8 hch, u8 lch);
62 extern u8 str_2char2num(u8 hch, u8 lch);
63 extern void macstr2num(u8 *dst, u8 *src);
64 extern u8 convert_ip_addr(u8 hch, u8 mch, u8 lch);
65
66 u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
67         6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000
68                   };
69
70 static const char *const iw_operation_mode[] = {
71         "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater", "Secondary", "Monitor"
72 };
73
74 static int hex2num_i(char c)
75 {
76         if (c >= '0' && c <= '9')
77                 return c - '0';
78         if (c >= 'a' && c <= 'f')
79                 return c - 'a' + 10;
80         if (c >= 'A' && c <= 'F')
81                 return c - 'A' + 10;
82         return -1;
83 }
84
85 static int hex2byte_i(const char *hex)
86 {
87         int a, b;
88         a = hex2num_i(*hex++);
89         if (a < 0)
90                 return -1;
91         b = hex2num_i(*hex++);
92         if (b < 0)
93                 return -1;
94         return (a << 4) | b;
95 }
96
97 /**
98  * hwaddr_aton - Convert ASCII string to MAC address
99  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
100  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
101  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
102  */
103 static int hwaddr_aton_i(const char *txt, u8 *addr)
104 {
105         int i;
106
107         for (i = 0; i < 6; i++) {
108                 int a, b;
109
110                 a = hex2num_i(*txt++);
111                 if (a < 0)
112                         return -1;
113                 b = hex2num_i(*txt++);
114                 if (b < 0)
115                         return -1;
116                 *addr++ = (a << 4) | b;
117                 if (i < 5 && *txt++ != ':')
118                         return -1;
119         }
120
121         return 0;
122 }
123
124 static void indicate_wx_custom_event(_adapter *padapter, char *msg)
125 {
126         u8 *buff, *p;
127         union iwreq_data wrqu;
128
129         if (strlen(msg) > IW_CUSTOM_MAX) {
130                 RTW_INFO("%s strlen(msg):%zu > IW_CUSTOM_MAX:%u\n", __FUNCTION__ , strlen(msg), IW_CUSTOM_MAX);
131                 return;
132         }
133
134         buff = rtw_zmalloc(IW_CUSTOM_MAX + 1);
135         if (!buff)
136                 return;
137
138         _rtw_memcpy(buff, msg, strlen(msg));
139
140         _rtw_memset(&wrqu, 0, sizeof(wrqu));
141         wrqu.data.length = strlen(msg);
142
143         RTW_INFO("%s %s\n", __FUNCTION__, buff);
144 #ifndef CONFIG_IOCTL_CFG80211
145         wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
146 #endif
147
148         rtw_mfree(buff, IW_CUSTOM_MAX + 1);
149
150 }
151
152
153 static void request_wps_pbc_event(_adapter *padapter)
154 {
155         u8 *buff, *p;
156         union iwreq_data wrqu;
157
158
159         buff = rtw_malloc(IW_CUSTOM_MAX);
160         if (!buff)
161                 return;
162
163         _rtw_memset(buff, 0, IW_CUSTOM_MAX);
164
165         p = buff;
166
167         p += sprintf(p, "WPS_PBC_START.request=TRUE");
168
169         _rtw_memset(&wrqu, 0, sizeof(wrqu));
170
171         wrqu.data.length = p - buff;
172
173         wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? wrqu.data.length : IW_CUSTOM_MAX;
174
175         RTW_INFO("%s\n", __FUNCTION__);
176
177 #ifndef CONFIG_IOCTL_CFG80211
178         wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
179 #endif
180
181         if (buff)
182                 rtw_mfree(buff, IW_CUSTOM_MAX);
183
184 }
185
186 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
187 void rtw_request_wps_pbc_event(_adapter *padapter)
188 {
189 #ifdef RTK_DMP_PLATFORM
190 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12))
191         kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_NET_PBC);
192 #else
193         kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_NET_PBC);
194 #endif
195 #else
196
197         if (padapter->pid[0] == 0) {
198                 /*      0 is the default value and it means the application monitors the HW PBC doesn't privde its pid to driver. */
199                 return;
200         }
201
202         rtw_signal_process(padapter->pid[0], SIGUSR1);
203
204 #endif
205
206         rtw_led_control(padapter, LED_CTL_START_WPS_BOTTON);
207 }
208 #endif/* #ifdef CONFIG_SUPPORT_HW_WPS_PBC */
209
210 void indicate_wx_scan_complete_event(_adapter *padapter)
211 {
212         union iwreq_data wrqu;
213         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
214
215         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
216
217         /* RTW_INFO("+rtw_indicate_wx_scan_complete_event\n"); */
218 #ifndef CONFIG_IOCTL_CFG80211
219         wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
220 #endif
221 }
222
223
224 void rtw_indicate_wx_assoc_event(_adapter *padapter)
225 {
226         union iwreq_data wrqu;
227         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
228         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
229         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
230         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
231
232         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
233
234         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
235
236         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
237                 _rtw_memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
238         else
239                 _rtw_memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
240
241         RTW_PRINT("assoc success\n");
242 #ifndef CONFIG_IOCTL_CFG80211
243         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
244 #endif
245 }
246
247 void rtw_indicate_wx_disassoc_event(_adapter *padapter)
248 {
249         union iwreq_data wrqu;
250
251         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
252
253         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
254         _rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
255
256 #ifndef CONFIG_IOCTL_CFG80211
257         RTW_PRINT("indicate disassoc\n");
258         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
259 #endif
260 }
261
262 /*
263 uint    rtw_is_cckrates_included(u8 *rate)
264 {
265                 u32     i = 0;
266
267                 while(rate[i]!=0)
268                 {
269                         if  (  (((rate[i]) & 0x7f) == 2)        || (((rate[i]) & 0x7f) == 4) ||
270                         (((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22) )
271                         return _TRUE;
272                         i++;
273                 }
274
275                 return _FALSE;
276 }
277
278 uint    rtw_is_cckratesonly_included(u8 *rate)
279 {
280         u32 i = 0;
281
282         while(rate[i]!=0)
283         {
284                         if  (  (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
285                                 (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22) )
286                         return _FALSE;
287                         i++;
288         }
289
290         return _TRUE;
291 }
292 */
293
294 static int search_p2p_wfd_ie(_adapter *padapter,
295              struct iw_request_info *info, struct wlan_network *pnetwork,
296                              char *start, char *stop)
297 {
298 #ifdef CONFIG_P2P
299         struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
300 #ifdef CONFIG_WFD
301         if (SCAN_RESULT_ALL == pwdinfo->wfd_info->scan_result_type) {
302
303         } else if ((SCAN_RESULT_P2P_ONLY == pwdinfo->wfd_info->scan_result_type) ||
304                 (SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type))
305 #endif /* CONFIG_WFD */
306         {
307                 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
308                         u32     blnGotP2PIE = _FALSE;
309
310                         /*      User is doing the P2P device discovery */
311                         /*      The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
312                         /*      If not, the driver should ignore this AP and go to the next AP. */
313
314                         /*      Verifying the SSID */
315                         if (_rtw_memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
316                                 u32     p2pielen = 0;
317
318                                 /*      Verifying the P2P IE */
319                                 if (rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen))
320                                         blnGotP2PIE = _TRUE;
321                         }
322
323                         if (blnGotP2PIE == _FALSE)
324                                 return _FALSE;
325
326                 }
327         }
328
329 #ifdef CONFIG_WFD
330         if (SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type) {
331                 u32     blnGotWFD = _FALSE;
332                 u8 *wfd_ie;
333                 uint wfd_ielen = 0;
334
335                 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
336                 if (wfd_ie) {
337                         u8 *wfd_devinfo;
338                         uint wfd_devlen;
339
340                         wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
341                         if (wfd_devinfo) {
342                                 if (pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_PSINK) {
343                                         /*      the first two bits will indicate the WFD device type */
344                                         if ((wfd_devinfo[1] & 0x03) == WFD_DEVINFO_SOURCE) {
345                                                 /*      If this device is Miracast PSink device, the scan reuslt should just provide the Miracast source. */
346                                                 blnGotWFD = _TRUE;
347                                         }
348                                 } else if (pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_SOURCE) {
349                                         /*      the first two bits will indicate the WFD device type */
350                                         if ((wfd_devinfo[1] & 0x03) == WFD_DEVINFO_PSINK) {
351                                                 /*      If this device is Miracast source device, the scan reuslt should just provide the Miracast PSink. */
352                                                 /*      Todo: How about the SSink?! */
353                                                 blnGotWFD = _TRUE;
354                                         }
355                                 }
356                         }
357                 }
358
359                 if (blnGotWFD == _FALSE)
360                         return _FALSE;
361         }
362 #endif /* CONFIG_WFD */
363
364 #endif /* CONFIG_P2P */
365         return _TRUE;
366 }
367 static inline char *iwe_stream_mac_addr_proess(_adapter *padapter,
368                 struct iw_request_info *info, struct wlan_network *pnetwork,
369                 char *start, char *stop, struct iw_event *iwe)
370 {
371         /*  AP MAC address */
372         iwe->cmd = SIOCGIWAP;
373         iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
374
375         _rtw_memcpy(iwe->u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
376         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_ADDR_LEN);
377         return start;
378 }
379 static inline char *iwe_stream_essid_proess(_adapter *padapter,
380                 struct iw_request_info *info, struct wlan_network *pnetwork,
381                 char *start, char *stop, struct iw_event *iwe)
382 {
383
384         /* Add the ESSID */
385         iwe->cmd = SIOCGIWESSID;
386         iwe->u.data.flags = 1;
387         iwe->u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
388         start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
389         return start;
390 }
391
392 static inline char *iwe_stream_chan_process(_adapter *padapter,
393                 struct iw_request_info *info, struct wlan_network *pnetwork,
394                 char *start, char *stop, struct iw_event *iwe)
395 {
396         if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
397                 pnetwork->network.Configuration.DSConfig = 1;
398
399         /* Add frequency/channel */
400         iwe->cmd = SIOCGIWFREQ;
401         iwe->u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
402         iwe->u.freq.e = 1;
403         iwe->u.freq.i = pnetwork->network.Configuration.DSConfig;
404         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_FREQ_LEN);
405         return start;
406 }
407 static inline char *iwe_stream_mode_process(_adapter *padapter,
408                 struct iw_request_info *info, struct wlan_network *pnetwork,
409                 char *start, char *stop, struct iw_event *iwe, u16 cap)
410 {
411         /* Add mode */
412         if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
413                 iwe->cmd = SIOCGIWMODE;
414                 if (cap & WLAN_CAPABILITY_BSS)
415                         iwe->u.mode = IW_MODE_MASTER;
416                 else
417                         iwe->u.mode = IW_MODE_ADHOC;
418
419                 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_UINT_LEN);
420         }
421         return start;
422 }
423 static inline char *iwe_stream_encryption_process(_adapter *padapter,
424                 struct iw_request_info *info, struct wlan_network *pnetwork,
425                 char *start, char *stop, struct iw_event *iwe, u16 cap)
426 {
427
428         /* Add encryption capability */
429         iwe->cmd = SIOCGIWENCODE;
430         if (cap & WLAN_CAPABILITY_PRIVACY)
431                 iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
432         else
433                 iwe->u.data.flags = IW_ENCODE_DISABLED;
434         iwe->u.data.length = 0;
435         start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
436         return start;
437
438 }
439
440 static inline char *iwe_stream_protocol_process(_adapter *padapter,
441                 struct iw_request_info *info, struct wlan_network *pnetwork,
442                 char *start, char *stop, struct iw_event *iwe)
443 {
444         u16 ht_cap = _FALSE, vht_cap = _FALSE;
445         u32 ht_ielen = 0, vht_ielen = 0;
446         char *p;
447         u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12); /* Probe Request   */
448
449         /* parsing HT_CAP_IE     */
450         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - ie_offset);
451         if (p && ht_ielen > 0)
452                 ht_cap = _TRUE;
453
454 #ifdef CONFIG_80211AC_VHT
455         /* parsing VHT_CAP_IE */
456         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength - ie_offset);
457         if (p && vht_ielen > 0)
458                 vht_cap = _TRUE;
459 #endif
460         /* Add the protocol name */
461         iwe->cmd = SIOCGIWNAME;
462         if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) == _TRUE) {
463                 if (ht_cap == _TRUE)
464                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bn");
465                 else
466                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11b");
467         } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) == _TRUE) {
468                 if (ht_cap == _TRUE)
469                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bgn");
470                 else
471                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bg");
472         } else {
473                 if (pnetwork->network.Configuration.DSConfig > 14) {
474 #ifdef CONFIG_80211AC_VHT
475                         if (vht_cap == _TRUE)
476                                 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11AC");
477                         else
478 #endif
479                         {
480                                 if (ht_cap == _TRUE)
481                                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11an");
482                                 else
483                                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11a");
484                         }
485                 } else {
486                         if (ht_cap == _TRUE)
487                                 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11gn");
488                         else
489                                 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11g");
490                 }
491         }
492         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_CHAR_LEN);
493         return start;
494 }
495
496 static inline char *iwe_stream_rate_process(_adapter *padapter,
497                 struct iw_request_info *info, struct wlan_network *pnetwork,
498                 char *start, char *stop, struct iw_event *iwe)
499 {
500         u32 ht_ielen = 0, vht_ielen = 0;
501         char *p;
502         u16 max_rate = 0, rate, ht_cap = _FALSE, vht_cap = _FALSE;
503         u32 i = 0;
504         u8 bw_40MHz = 0, short_GI = 0, bw_160MHz = 0, vht_highest_rate = 0;
505         u16 mcs_rate = 0, vht_data_rate = 0;
506         char custom[MAX_CUSTOM_LEN] = {0};
507         u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12); /* Probe Request   */
508
509         /* parsing HT_CAP_IE     */
510         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - ie_offset);
511         if (p && ht_ielen > 0) {
512                 struct rtw_ieee80211_ht_cap *pht_capie;
513                 ht_cap = _TRUE;
514                 pht_capie = (struct rtw_ieee80211_ht_cap *)(p + 2);
515                 _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
516                 bw_40MHz = (pht_capie->cap_info & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
517                 short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
518         }
519
520 #ifdef CONFIG_80211AC_VHT
521         /* parsing VHT_CAP_IE */
522         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength - ie_offset);
523         if (p && vht_ielen > 0) {
524                 u8      mcs_map[2];
525
526                 vht_cap = _TRUE;
527                 bw_160MHz = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p + 2);
528                 if (bw_160MHz)
529                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI160M(p + 2);
530                 else
531                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI80M(p + 2);
532
533                 _rtw_memcpy(mcs_map, GET_VHT_CAPABILITY_ELE_TX_MCS(p + 2), 2);
534
535                 vht_highest_rate = rtw_get_vht_highest_rate(mcs_map);
536                 vht_data_rate = rtw_vht_mcs_to_data_rate(CHANNEL_WIDTH_80, short_GI, vht_highest_rate);
537         }
538 #endif
539
540         /*Add basic and extended rates */
541         p = custom;
542         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
543         while (pnetwork->network.SupportedRates[i] != 0) {
544                 rate = pnetwork->network.SupportedRates[i] & 0x7F;
545                 if (rate > max_rate)
546                         max_rate = rate;
547                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
548                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
549                 i++;
550         }
551 #ifdef CONFIG_80211AC_VHT
552         if (vht_cap == _TRUE)
553                 max_rate = vht_data_rate;
554         else
555 #endif
556                 if (ht_cap == _TRUE) {
557                         if (mcs_rate & 0x8000) /* MCS15 */
558                                 max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
559
560                         else if (mcs_rate & 0x0080) /* MCS7 */
561                                 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
562                         else { /* default MCS7 */
563                                 /* RTW_INFO("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate); */
564                                 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
565                         }
566
567                         max_rate = max_rate * 2; /* Mbps/2;              */
568                 }
569
570         iwe->cmd = SIOCGIWRATE;
571         iwe->u.bitrate.fixed = iwe->u.bitrate.disabled = 0;
572         iwe->u.bitrate.value = max_rate * 500000;
573         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_PARAM_LEN);
574         return start ;
575 }
576
577 static inline char *iwe_stream_wpa_wpa2_process(_adapter *padapter,
578                 struct iw_request_info *info, struct wlan_network *pnetwork,
579                 char *start, char *stop, struct iw_event *iwe)
580 {
581         int buf_size = MAX_WPA_IE_LEN * 2;
582         /* u8 pbuf[buf_size]={0};        */
583         u8 *pbuf = rtw_zmalloc(buf_size);
584
585         u8 wpa_ie[255] = {0}, rsn_ie[255] = {0};
586         u16 i, wpa_len = 0, rsn_len = 0;
587         u8 *p;
588         sint out_len = 0;
589
590
591         if (pbuf) {
592                 p = pbuf;
593
594                 /* parsing WPA/WPA2 IE */
595                 if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
596                         out_len = rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
597                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid=%s\n", pnetwork->network.Ssid.Ssid));
598                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len=%d rsn_len=%d\n", wpa_len, rsn_len));
599
600                         if (wpa_len > 0) {
601
602                                 _rtw_memset(pbuf, 0, buf_size);
603                                 p += sprintf(p, "wpa_ie=");
604                                 for (i = 0; i < wpa_len; i++)
605                                         p += sprintf(p, "%02x", wpa_ie[i]);
606
607                                 if (wpa_len > 100) {
608                                         printk("-----------------Len %d----------------\n", wpa_len);
609                                         for (i = 0; i < wpa_len; i++)
610                                                 printk("%02x ", wpa_ie[i]);
611                                         printk("\n");
612                                         printk("-----------------Len %d----------------\n", wpa_len);
613                                 }
614
615                                 _rtw_memset(iwe, 0, sizeof(*iwe));
616                                 iwe->cmd = IWEVCUSTOM;
617                                 iwe->u.data.length = strlen(pbuf);
618                                 start = iwe_stream_add_point(info, start, stop, iwe, pbuf);
619
620                                 _rtw_memset(iwe, 0, sizeof(*iwe));
621                                 iwe->cmd = IWEVGENIE;
622                                 iwe->u.data.length = wpa_len;
623                                 start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie);
624                         }
625                         if (rsn_len > 0) {
626
627                                 _rtw_memset(pbuf, 0, buf_size);
628                                 p += sprintf(p, "rsn_ie=");
629                                 for (i = 0; i < rsn_len; i++)
630                                         p += sprintf(p, "%02x", rsn_ie[i]);
631                                 _rtw_memset(iwe, 0, sizeof(*iwe));
632                                 iwe->cmd = IWEVCUSTOM;
633                                 iwe->u.data.length = strlen(pbuf);
634                                 start = iwe_stream_add_point(info, start, stop, iwe, pbuf);
635
636                                 _rtw_memset(iwe, 0, sizeof(*iwe));
637                                 iwe->cmd = IWEVGENIE;
638                                 iwe->u.data.length = rsn_len;
639                                 start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie);
640                         }
641                 }
642
643                 rtw_mfree(pbuf, buf_size);
644         }
645         return start;
646 }
647
648 static inline char *iwe_stream_wps_process(_adapter *padapter,
649                 struct iw_request_info *info, struct wlan_network *pnetwork,
650                 char *start, char *stop, struct iw_event *iwe)
651 {
652         /* parsing WPS IE */
653         uint cnt = 0, total_ielen;
654         u8 *wpsie_ptr = NULL;
655         uint wps_ielen = 0;
656         u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12);
657
658         u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
659         total_ielen = pnetwork->network.IELength - ie_offset;
660
661         if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
662                 ie_ptr = pnetwork->network.IEs;
663                 total_ielen = pnetwork->network.IELength;
664         } else { /* Beacon or Probe Respones */
665                 ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
666                 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
667         }
668         while (cnt < total_ielen) {
669                 if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
670                         wpsie_ptr = &ie_ptr[cnt];
671                         iwe->cmd = IWEVGENIE;
672                         iwe->u.data.length = (u16)wps_ielen;
673                         start = iwe_stream_add_point(info, start, stop, iwe, wpsie_ptr);
674                 }
675                 cnt += ie_ptr[cnt + 1] + 2; /* goto next */
676         }
677         return start;
678 }
679
680 static inline char *iwe_stream_wapi_process(_adapter *padapter,
681                 struct iw_request_info *info, struct wlan_network *pnetwork,
682                 char *start, char *stop, struct iw_event *iwe)
683 {
684 #ifdef CONFIG_WAPI_SUPPORT
685         char *p;
686
687         if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
688                 sint out_len_wapi = 0;
689                 /* here use static for stack size */
690                 static u8 buf_wapi[MAX_WAPI_IE_LEN * 2] = {0};
691                 static u8 wapi_ie[MAX_WAPI_IE_LEN] = {0};
692                 u16 wapi_len = 0;
693                 u16  i;
694
695                 out_len_wapi = rtw_get_wapi_ie(pnetwork->network.IEs , pnetwork->network.IELength, wapi_ie, &wapi_len);
696                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid=%s\n", pnetwork->network.Ssid.Ssid));
697                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wapi_len=%d\n", wapi_len));
698
699                 RTW_INFO("rtw_wx_get_scan: %s ", pnetwork->network.Ssid.Ssid);
700                 RTW_INFO("rtw_wx_get_scan: ssid = %d ", wapi_len);
701
702
703                 if (wapi_len > 0) {
704                         p = buf_wapi;
705                         /* _rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN*2); */
706                         p += sprintf(p, "wapi_ie=");
707                         for (i = 0; i < wapi_len; i++)
708                                 p += sprintf(p, "%02x", wapi_ie[i]);
709
710                         _rtw_memset(iwe, 0, sizeof(*iwe));
711                         iwe->cmd = IWEVCUSTOM;
712                         iwe->u.data.length = strlen(buf_wapi);
713                         start = iwe_stream_add_point(info, start, stop, iwe, buf_wapi);
714
715                         _rtw_memset(iwe, 0, sizeof(*iwe));
716                         iwe->cmd = IWEVGENIE;
717                         iwe->u.data.length = wapi_len;
718                         start = iwe_stream_add_point(info, start, stop, iwe, wapi_ie);
719                 }
720         }
721 #endif/* #ifdef CONFIG_WAPI_SUPPORT */
722         return start;
723 }
724
725 static inline char   *iwe_stream_rssi_process(_adapter *padapter,
726                 struct iw_request_info *info, struct wlan_network *pnetwork,
727                 char *start, char *stop, struct iw_event *iwe)
728 {
729         u8 ss, sq;
730         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
731
732         /* Add quality statistics */
733         iwe->cmd = IWEVQUAL;
734         iwe->u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
735 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
736                               | IW_QUAL_NOISE_UPDATED
737 #else
738                               | IW_QUAL_NOISE_INVALID
739 #endif
740 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
741                               | IW_QUAL_DBM
742 #endif
743                               ;
744
745         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
746             is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
747                 ss = padapter->recvpriv.signal_strength;
748                 sq = padapter->recvpriv.signal_qual;
749         } else {
750                 ss = pnetwork->network.PhyInfo.SignalStrength;
751                 sq = pnetwork->network.PhyInfo.SignalQuality;
752         }
753
754
755 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
756         iwe->u.qual.level = (u8) translate_percentage_to_dbm(ss); /* dbm */
757 #else
758 #ifdef CONFIG_SIGNAL_SCALE_MAPPING
759         iwe->u.qual.level = (u8)ss; /* % */
760 #else
761         {
762                 /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
763
764                 HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
765
766                 iwe->u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss);
767         }
768 #endif
769 #endif
770
771         iwe->u.qual.qual = (u8)sq;   /* signal quality */
772
773 #ifdef CONFIG_PLATFORM_ROCKCHIPS
774         iwe->u.qual.noise = -100; /* noise level suggest by zhf@rockchips */
775 #else
776 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
777         {
778                 s16 tmp_noise = 0;
779                 rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
780                 iwe->u.qual.noise = tmp_noise ;
781         }
782 #else
783         iwe->u.qual.noise = 0; /* noise level */
784 #endif
785 #endif /* CONFIG_PLATFORM_ROCKCHIPS */
786
787         /* RTW_INFO("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); */
788
789         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_QUAL_LEN);
790         return start;
791 }
792
793 static inline char   *iwe_stream_net_rsv_process(_adapter *padapter,
794                 struct iw_request_info *info, struct wlan_network *pnetwork,
795                 char *start, char *stop, struct iw_event *iwe)
796 {
797         u8 buf[32] = {0};
798         u8 *p, *pos;
799         int len;
800         p = buf;
801         pos = pnetwork->network.Reserved;
802
803         p += sprintf(p, "fm=%02X%02X", pos[1], pos[0]);
804         _rtw_memset(iwe, 0, sizeof(*iwe));
805         iwe->cmd = IWEVCUSTOM;
806         iwe->u.data.length = strlen(buf);
807         start = iwe_stream_add_point(info, start, stop, iwe, buf);
808         return start;
809 }
810
811 #if 1
812 static char *translate_scan(_adapter *padapter,
813                     struct iw_request_info *info, struct wlan_network *pnetwork,
814                             char *start, char *stop)
815 {
816         struct iw_event iwe;
817         u16 cap = 0;
818         _rtw_memset(&iwe, 0, sizeof(iwe));
819
820         if (_FALSE == search_p2p_wfd_ie(padapter, info, pnetwork, start, stop))
821                 return start;
822
823         start = iwe_stream_mac_addr_proess(padapter, info, pnetwork, start, stop, &iwe);
824         start = iwe_stream_essid_proess(padapter, info, pnetwork, start, stop, &iwe);
825         start = iwe_stream_protocol_process(padapter, info, pnetwork, start, stop, &iwe);
826         if (pnetwork->network.Reserved[0] == 2) /* Probe Request */
827                 cap = 0;
828         else {
829                 _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
830                 cap = le16_to_cpu(cap);
831         }
832
833         start = iwe_stream_mode_process(padapter, info, pnetwork, start, stop, &iwe, cap);
834         start = iwe_stream_chan_process(padapter, info, pnetwork, start, stop, &iwe);
835         start = iwe_stream_encryption_process(padapter, info, pnetwork, start, stop, &iwe, cap);
836         start = iwe_stream_rate_process(padapter, info, pnetwork, start, stop, &iwe);
837         start = iwe_stream_wpa_wpa2_process(padapter, info, pnetwork, start, stop, &iwe);
838         start = iwe_stream_wps_process(padapter, info, pnetwork, start, stop, &iwe);
839         start = iwe_stream_wapi_process(padapter, info, pnetwork, start, stop, &iwe);
840         start = iwe_stream_rssi_process(padapter, info, pnetwork, start, stop, &iwe);
841         start = iwe_stream_net_rsv_process(padapter, info, pnetwork, start, stop, &iwe);
842
843         return start;
844 }
845 #else
846 static char *translate_scan(_adapter *padapter,
847                     struct iw_request_info *info, struct wlan_network *pnetwork,
848                             char *start, char *stop)
849 {
850         struct iw_event iwe;
851         u16 cap;
852         u32 ht_ielen = 0, vht_ielen = 0;
853         char custom[MAX_CUSTOM_LEN];
854         char *p;
855         u16 max_rate = 0, rate, ht_cap = _FALSE, vht_cap = _FALSE;
856         u32 i = 0;
857         char    *current_val;
858         long rssi;
859         u8 bw_40MHz = 0, short_GI = 0, bw_160MHz = 0, vht_highest_rate = 0;
860         u16 mcs_rate = 0, vht_data_rate = 0;
861         u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12);
862         struct registry_priv *pregpriv = &padapter->registrypriv;
863
864         if (_FALSE == search_p2p_wfd_ie(padapter, info, pnetwork, start, stop))
865                 return start;
866
867         /*  AP MAC address */
868         iwe.cmd = SIOCGIWAP;
869         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
870
871         _rtw_memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
872         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
873
874         /* Add the ESSID */
875         iwe.cmd = SIOCGIWESSID;
876         iwe.u.data.flags = 1;
877         iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
878         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
879
880         /* parsing HT_CAP_IE */
881         if (pnetwork->network.Reserved[0] == 2) /* Probe Request */
882                 p = rtw_get_ie(&pnetwork->network.IEs[0], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength);
883         else
884                 p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - 12);
885         if (p && ht_ielen > 0) {
886                 struct rtw_ieee80211_ht_cap *pht_capie;
887                 ht_cap = _TRUE;
888                 pht_capie = (struct rtw_ieee80211_ht_cap *)(p + 2);
889                 _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
890                 bw_40MHz = (pht_capie->cap_info & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
891                 short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
892         }
893
894 #ifdef CONFIG_80211AC_VHT
895         /* parsing VHT_CAP_IE */
896         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength - ie_offset);
897         if (p && vht_ielen > 0) {
898                 u8      mcs_map[2];
899
900                 vht_cap = _TRUE;
901                 bw_160MHz = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p + 2);
902                 if (bw_160MHz)
903                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI160M(p + 2);
904                 else
905                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI80M(p + 2);
906
907                 _rtw_memcpy(mcs_map, GET_VHT_CAPABILITY_ELE_TX_MCS(p + 2), 2);
908
909                 vht_highest_rate = rtw_get_vht_highest_rate(mcs_map);
910                 vht_data_rate = rtw_vht_mcs_to_data_rate(CHANNEL_WIDTH_80, short_GI, vht_highest_rate);
911         }
912 #endif
913
914         /* Add the protocol name */
915         iwe.cmd = SIOCGIWNAME;
916         if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) == _TRUE) {
917                 if (ht_cap == _TRUE)
918                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
919                 else
920                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
921         } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) == _TRUE) {
922                 if (ht_cap == _TRUE)
923                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
924                 else
925                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
926         } else {
927                 if (pnetwork->network.Configuration.DSConfig > 14) {
928                         if (vht_cap == _TRUE)
929                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC");
930                         else if (ht_cap == _TRUE)
931                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
932                         else
933                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
934                 } else {
935                         if (ht_cap == _TRUE)
936                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
937                         else
938                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
939                 }
940         }
941
942         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
943
944         /* Add mode */
945         if (pnetwork->network.Reserved[0] == 2) /* Probe Request */
946                 cap = 0;
947         else {
948                 iwe.cmd = SIOCGIWMODE;
949                 _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
950                 cap = le16_to_cpu(cap);
951         }
952
953         if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
954                 if (cap & WLAN_CAPABILITY_BSS)
955                         iwe.u.mode = IW_MODE_MASTER;
956                 else
957                         iwe.u.mode = IW_MODE_ADHOC;
958
959                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
960         }
961
962         if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
963                 pnetwork->network.Configuration.DSConfig = 1;
964
965         /* Add frequency/channel */
966         iwe.cmd = SIOCGIWFREQ;
967         iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
968         iwe.u.freq.e = 1;
969         iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
970         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
971
972         /* Add encryption capability */
973         iwe.cmd = SIOCGIWENCODE;
974         if (cap & WLAN_CAPABILITY_PRIVACY)
975                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
976         else
977                 iwe.u.data.flags = IW_ENCODE_DISABLED;
978         iwe.u.data.length = 0;
979         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
980
981         /*Add basic and extended rates */
982         max_rate = 0;
983         p = custom;
984         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
985         while (pnetwork->network.SupportedRates[i] != 0) {
986                 rate = pnetwork->network.SupportedRates[i] & 0x7F;
987                 if (rate > max_rate)
988                         max_rate = rate;
989                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
990                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
991                 i++;
992         }
993
994         if (vht_cap == _TRUE)
995                 max_rate = vht_data_rate;
996         else if (ht_cap == _TRUE) {
997                 if (mcs_rate & 0x8000) /* MCS15 */
998                         max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
999
1000                 else if (mcs_rate & 0x0080) /* MCS7 */
1001                         max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
1002                 else { /* default MCS7 */
1003                         /* RTW_INFO("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate); */
1004                         max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
1005                 }
1006
1007                 max_rate = max_rate * 2; /* Mbps/2;              */
1008         }
1009
1010         iwe.cmd = SIOCGIWRATE;
1011         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1012         iwe.u.bitrate.value = max_rate * 500000;
1013         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
1014
1015         /* parsing WPA/WPA2 IE */
1016         if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
1017                 u8 buf[MAX_WPA_IE_LEN * 2];
1018                 u8 wpa_ie[255], rsn_ie[255];
1019                 u16 wpa_len = 0, rsn_len = 0;
1020                 u8 *p;
1021                 sint out_len = 0;
1022                 out_len = rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
1023                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid=%s\n", pnetwork->network.Ssid.Ssid));
1024                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len=%d rsn_len=%d\n", wpa_len, rsn_len));
1025
1026                 if (wpa_len > 0) {
1027                         p = buf;
1028                         _rtw_memset(buf, 0, MAX_WPA_IE_LEN * 2);
1029                         p += sprintf(p, "wpa_ie=");
1030                         for (i = 0; i < wpa_len; i++)
1031                                 p += sprintf(p, "%02x", wpa_ie[i]);
1032
1033                         if (wpa_len > 100) {
1034                                 printk("-----------------Len %d----------------\n", wpa_len);
1035                                 for (i = 0; i < wpa_len; i++)
1036                                         printk("%02x ", wpa_ie[i]);
1037                                 printk("\n");
1038                                 printk("-----------------Len %d----------------\n", wpa_len);
1039                         }
1040
1041                         _rtw_memset(&iwe, 0, sizeof(iwe));
1042                         iwe.cmd = IWEVCUSTOM;
1043                         iwe.u.data.length = strlen(buf);
1044                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1045
1046                         _rtw_memset(&iwe, 0, sizeof(iwe));
1047                         iwe.cmd = IWEVGENIE;
1048                         iwe.u.data.length = wpa_len;
1049                         start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
1050                 }
1051                 if (rsn_len > 0) {
1052                         p = buf;
1053                         _rtw_memset(buf, 0, MAX_WPA_IE_LEN * 2);
1054                         p += sprintf(p, "rsn_ie=");
1055                         for (i = 0; i < rsn_len; i++)
1056                                 p += sprintf(p, "%02x", rsn_ie[i]);
1057                         _rtw_memset(&iwe, 0, sizeof(iwe));
1058                         iwe.cmd = IWEVCUSTOM;
1059                         iwe.u.data.length = strlen(buf);
1060                         start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1061
1062                         _rtw_memset(&iwe, 0, sizeof(iwe));
1063                         iwe.cmd = IWEVGENIE;
1064                         iwe.u.data.length = rsn_len;
1065                         start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
1066                 }
1067         }
1068
1069         { /* parsing WPS IE */
1070                 uint cnt = 0, total_ielen;
1071                 u8 *wpsie_ptr = NULL;
1072                 uint wps_ielen = 0;
1073
1074                 u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
1075                 total_ielen = pnetwork->network.IELength - ie_offset;
1076
1077                 if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
1078                         ie_ptr = pnetwork->network.IEs;
1079                         total_ielen = pnetwork->network.IELength;
1080                 } else { /* Beacon or Probe Respones */
1081                         ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
1082                         total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
1083                 }
1084
1085                 while (cnt < total_ielen) {
1086                         if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
1087                                 wpsie_ptr = &ie_ptr[cnt];
1088                                 iwe.cmd = IWEVGENIE;
1089                                 iwe.u.data.length = (u16)wps_ielen;
1090                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
1091                         }
1092                         cnt += ie_ptr[cnt + 1] + 2; /* goto next */
1093                 }
1094         }
1095
1096 #ifdef CONFIG_WAPI_SUPPORT
1097         if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
1098                 sint out_len_wapi = 0;
1099                 /* here use static for stack size */
1100                 static u8 buf_wapi[MAX_WAPI_IE_LEN * 2];
1101                 static u8 wapi_ie[MAX_WAPI_IE_LEN];
1102                 u16 wapi_len = 0;
1103                 u16  i;
1104
1105                 _rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN);
1106                 _rtw_memset(wapi_ie, 0, MAX_WAPI_IE_LEN);
1107
1108                 out_len_wapi = rtw_get_wapi_ie(pnetwork->network.IEs , pnetwork->network.IELength, wapi_ie, &wapi_len);
1109                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid=%s\n", pnetwork->network.Ssid.Ssid));
1110                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wapi_len=%d\n", wapi_len));
1111
1112                 RTW_INFO("rtw_wx_get_scan: %s ", pnetwork->network.Ssid.Ssid);
1113                 RTW_INFO("rtw_wx_get_scan: ssid = %d ", wapi_len);
1114
1115
1116                 if (wapi_len > 0) {
1117                         p = buf_wapi;
1118                         _rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN * 2);
1119                         p += sprintf(p, "wapi_ie=");
1120                         for (i = 0; i < wapi_len; i++)
1121                                 p += sprintf(p, "%02x", wapi_ie[i]);
1122
1123                         _rtw_memset(&iwe, 0, sizeof(iwe));
1124                         iwe.cmd = IWEVCUSTOM;
1125                         iwe.u.data.length = strlen(buf_wapi);
1126                         start = iwe_stream_add_point(info, start, stop, &iwe, buf_wapi);
1127
1128                         _rtw_memset(&iwe, 0, sizeof(iwe));
1129                         iwe.cmd = IWEVGENIE;
1130                         iwe.u.data.length = wapi_len;
1131                         start = iwe_stream_add_point(info, start, stop, &iwe, wapi_ie);
1132                 }
1133         }
1134 #endif
1135
1136         {
1137                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1138                 u8 ss, sq;
1139
1140                 /* Add quality statistics */
1141                 iwe.cmd = IWEVQUAL;
1142                 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
1143 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
1144                                      | IW_QUAL_NOISE_UPDATED
1145 #else
1146                                      | IW_QUAL_NOISE_INVALID
1147 #endif
1148 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
1149                                      | IW_QUAL_DBM
1150 #endif
1151                                      ;
1152
1153                 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
1154                     is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
1155                         ss = padapter->recvpriv.signal_strength;
1156                         sq = padapter->recvpriv.signal_qual;
1157                 } else {
1158                         ss = pnetwork->network.PhyInfo.SignalStrength;
1159                         sq = pnetwork->network.PhyInfo.SignalQuality;
1160                 }
1161
1162
1163 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
1164                 iwe.u.qual.level = (u8) translate_percentage_to_dbm(ss); /* dbm */
1165 #else
1166 #ifdef CONFIG_SIGNAL_SCALE_MAPPING
1167                 iwe.u.qual.level = (u8)ss; /* % */
1168 #else
1169                 {
1170                         /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
1171
1172                         HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
1173
1174                         iwe.u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss);
1175                 }
1176 #endif
1177 #endif
1178
1179                 iwe.u.qual.qual = (u8)sq;   /* signal quality */
1180
1181 #ifdef CONFIG_PLATFORM_ROCKCHIPS
1182                 iwe.u.qual.noise = -100; /* noise level suggest by zhf@rockchips */
1183 #else
1184 #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
1185                 {
1186                         s16 tmp_noise = 0;
1187                         rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
1188                         iwe.u.qual.noise = tmp_noise ;
1189                 }
1190 #else
1191                 iwe.u.qual.noise = 0; /* noise level */
1192 #endif
1193 #endif /* CONFIG_PLATFORM_ROCKCHIPS */
1194
1195                 /* RTW_INFO("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); */
1196
1197                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
1198         }
1199
1200         {
1201                 u8 buf[MAX_WPA_IE_LEN];
1202                 u8 *p, *pos;
1203                 int len;
1204                 p = buf;
1205                 pos = pnetwork->network.Reserved;
1206                 _rtw_memset(buf, 0, MAX_WPA_IE_LEN);
1207                 p += sprintf(p, "fm=%02X%02X", pos[1], pos[0]);
1208                 _rtw_memset(&iwe, 0, sizeof(iwe));
1209                 iwe.cmd = IWEVCUSTOM;
1210                 iwe.u.data.length = strlen(buf);
1211                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1212         }
1213
1214         return start;
1215 }
1216 #endif
1217
1218 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
1219 {
1220         _adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
1221         int ret = 0;
1222
1223         if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
1224                 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
1225                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1226                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
1227                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1228         } else if (value & AUTH_ALG_SHARED_KEY) {
1229                 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n", value);
1230                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1231
1232 #ifdef CONFIG_PLATFORM_MT53XX
1233                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
1234                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1235 #else
1236                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
1237                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1238 #endif
1239         } else if (value & AUTH_ALG_OPEN_SYSTEM) {
1240                 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
1241                 /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
1242                 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
1243 #ifdef CONFIG_PLATFORM_MT53XX
1244                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
1245                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1246 #else
1247                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1248                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1249 #endif
1250                 }
1251
1252         } else if (value & AUTH_ALG_LEAP)
1253                 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
1254         else {
1255                 RTW_INFO("wpa_set_auth_algs, error!\n");
1256                 ret = -EINVAL;
1257         }
1258
1259         return ret;
1260
1261 }
1262
1263 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
1264 {
1265         int ret = 0;
1266         u32 wep_key_idx, wep_key_len, wep_total_len;
1267         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1268         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1269         struct security_priv *psecuritypriv = &padapter->securitypriv;
1270 #ifdef CONFIG_P2P
1271         struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1272 #endif /* CONFIG_P2P */
1273
1274         _func_enter_;
1275
1276         param->u.crypt.err = 0;
1277         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
1278
1279         if (param_len < (u32)((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) {
1280                 ret =  -EINVAL;
1281                 goto exit;
1282         }
1283
1284         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1285             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1286             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1287
1288                 if (param->u.crypt.idx >= WEP_KEYS
1289 #ifdef CONFIG_IEEE80211W
1290                     && param->u.crypt.idx > BIP_MAX_KEYID
1291 #endif /* CONFIG_IEEE80211W */
1292                    ) {
1293                         ret = -EINVAL;
1294                         goto exit;
1295                 }
1296         } else {
1297 #ifdef CONFIG_WAPI_SUPPORT
1298                 if (strcmp(param->u.crypt.alg, "SMS4"))
1299 #endif
1300                 {
1301                         ret = -EINVAL;
1302                         goto exit;
1303                 }
1304         }
1305
1306         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
1307                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
1308                 RTW_INFO("wpa_set_encryption, crypt.alg = WEP\n");
1309
1310                 wep_key_idx = param->u.crypt.idx;
1311                 wep_key_len = param->u.crypt.key_len;
1312
1313                 if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
1314                         ret = -EINVAL;
1315                         goto exit;
1316                 }
1317
1318                 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
1319                         /* wep default key has not been set, so use this key index as default key.*/
1320
1321                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
1322
1323                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1324                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
1325                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
1326
1327                         if (wep_key_len == 13) {
1328                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
1329                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
1330                         }
1331
1332                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
1333                 }
1334
1335                 _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
1336
1337                 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
1338
1339                 psecuritypriv->key_mask |= BIT(wep_key_idx);
1340
1341                 goto exit;
1342         }
1343
1344         if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
1345                 struct sta_info *psta, *pbcmc_sta;
1346                 struct sta_priv *pstapriv = &padapter->stapriv;
1347
1348                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) { /* sta mode */
1349                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
1350                         if (psta == NULL) {
1351                                 /* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
1352                         } else {
1353                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
1354                                 if (strcmp(param->u.crypt.alg, "none") != 0)
1355                                         psta->ieee8021x_blocked = _FALSE;
1356
1357                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
1358                                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
1359                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1360
1361                                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
1362                                         _rtw_memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1363
1364                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
1365                                                 /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
1366                                                 _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
1367                                                 _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
1368
1369                                                 padapter->securitypriv.busetkipkey = _FALSE;
1370                                                 /* _set_timer(&padapter->securitypriv.tkip_timer, 50);                                           */
1371                                         }
1372
1373                                         /* DEBUG_ERR((" param->u.crypt.key_len=%d\n",param->u.crypt.key_len)); */
1374                                         RTW_INFO(" ~~~~set sta key:unicastkey\n");
1375
1376                                         rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _TRUE);
1377
1378                                         psta->bpairwise_key_installed = _TRUE;
1379
1380                                 } else { /* group key */
1381                                         if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
1382                                                 _rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key,
1383                                                         (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1384                                                 /* only TKIP group key need to install this */
1385                                                 if (param->u.crypt.key_len > 16) {
1386                                                         _rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
1387                                                         _rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
1388                                                 }
1389                                                 padapter->securitypriv.binstallGrpkey = _TRUE;
1390                                                 /* DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
1391                                                 RTW_INFO(" ~~~~set sta key:groupkey\n");
1392
1393                                                 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
1394
1395                                                 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, _TRUE);
1396                                         }
1397 #ifdef CONFIG_IEEE80211W
1398                                         else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
1399                                                 int no;
1400                                                 /* printk("BIP key_len=%d , index=%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
1401                                                 /* save the IGTK key, length 16 bytes */
1402                                                 _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,  param->u.crypt.key,
1403                                                         (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1404                                                 /*printk("IGTK key below:\n");
1405                                                 for(no=0;no<16;no++)
1406                                                         printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
1407                                                 printk("\n");*/
1408                                                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
1409                                                 padapter->securitypriv.binstallBIPkey = _TRUE;
1410                                                 RTW_INFO(" ~~~~set sta key:IGKT\n");
1411                                         }
1412 #endif /* CONFIG_IEEE80211W */
1413
1414 #ifdef CONFIG_P2P
1415                                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1416                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
1417 #endif /* CONFIG_P2P */
1418
1419                                 }
1420                         }
1421
1422                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
1423                         if (pbcmc_sta == NULL) {
1424                                 /* DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
1425                         } else {
1426                                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
1427                                 if (strcmp(param->u.crypt.alg, "none") != 0)
1428                                         pbcmc_sta->ieee8021x_blocked = _FALSE;
1429
1430                                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
1431                                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
1432                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1433                         }
1434                 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
1435                 }
1436         }
1437
1438 #ifdef CONFIG_WAPI_SUPPORT
1439         if (strcmp(param->u.crypt.alg, "SMS4") == 0) {
1440                 PRT_WAPI_T                      pWapiInfo = &padapter->wapiInfo;
1441                 PRT_WAPI_STA_INFO       pWapiSta;
1442                 u8                                      WapiASUEPNInitialValueSrc[16] = {0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C} ;
1443                 u8                                      WapiAEPNInitialValueSrc[16] = {0x37, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C} ;
1444                 u8                                      WapiAEMultiCastPNInitialValueSrc[16] = {0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C} ;
1445
1446                 if (param->u.crypt.set_tx == 1) {
1447                         list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
1448                                 if (_rtw_memcmp(pWapiSta->PeerMacAddr, param->sta_addr, 6)) {
1449                                         _rtw_memcpy(pWapiSta->lastTxUnicastPN, WapiASUEPNInitialValueSrc, 16);
1450
1451                                         pWapiSta->wapiUsk.bSet = true;
1452                                         _rtw_memcpy(pWapiSta->wapiUsk.dataKey, param->u.crypt.key, 16);
1453                                         _rtw_memcpy(pWapiSta->wapiUsk.micKey, param->u.crypt.key + 16, 16);
1454                                         pWapiSta->wapiUsk.keyId = param->u.crypt.idx ;
1455                                         pWapiSta->wapiUsk.bTxEnable = true;
1456
1457                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNBEQueue, WapiAEPNInitialValueSrc, 16);
1458                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNBKQueue, WapiAEPNInitialValueSrc, 16);
1459                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNVIQueue, WapiAEPNInitialValueSrc, 16);
1460                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNVOQueue, WapiAEPNInitialValueSrc, 16);
1461                                         _rtw_memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
1462                                         pWapiSta->wapiUskUpdate.bTxEnable = false;
1463                                         pWapiSta->wapiUskUpdate.bSet = false;
1464
1465                                         if (psecuritypriv->sw_encrypt == false || psecuritypriv->sw_decrypt == false) {
1466                                                 /* set unicast key for ASUE */
1467                                                 rtw_wapi_set_key(padapter, &pWapiSta->wapiUsk, pWapiSta, false, false);
1468                                         }
1469                                 }
1470                         }
1471                 } else {
1472                         list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
1473                                 if (_rtw_memcmp(pWapiSta->PeerMacAddr, get_bssid(pmlmepriv), 6)) {
1474                                         pWapiSta->wapiMsk.bSet = true;
1475                                         _rtw_memcpy(pWapiSta->wapiMsk.dataKey, param->u.crypt.key, 16);
1476                                         _rtw_memcpy(pWapiSta->wapiMsk.micKey, param->u.crypt.key + 16, 16);
1477                                         pWapiSta->wapiMsk.keyId = param->u.crypt.idx ;
1478                                         pWapiSta->wapiMsk.bTxEnable = false;
1479                                         if (!pWapiSta->bSetkeyOk)
1480                                                 pWapiSta->bSetkeyOk = true;
1481                                         pWapiSta->bAuthenticateInProgress = false;
1482
1483                                         _rtw_memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
1484
1485                                         if (psecuritypriv->sw_decrypt == false) {
1486                                                 /* set rx broadcast key for ASUE */
1487                                                 rtw_wapi_set_key(padapter, &pWapiSta->wapiMsk, pWapiSta, true, false);
1488                                         }
1489                                 }
1490
1491                         }
1492                 }
1493         }
1494 #endif
1495
1496 exit:
1497
1498         _func_exit_;
1499
1500         return ret;
1501 }
1502
1503 static int rtw_set_wpa_ie(_adapter *padapter, char *pie, unsigned short ielen)
1504 {
1505         u8 *buf = NULL, *pos = NULL;
1506         u32 left;
1507         int group_cipher = 0, pairwise_cipher = 0;
1508         int ret = 0;
1509         u8 null_addr[] = {0, 0, 0, 0, 0, 0};
1510 #ifdef CONFIG_P2P
1511         struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1512 #endif /* CONFIG_P2P */
1513
1514         if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
1515                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1516                 if (pie == NULL)
1517                         return ret;
1518                 else
1519                         return -EINVAL;
1520         }
1521
1522         if (ielen) {
1523                 buf = rtw_zmalloc(ielen);
1524                 if (buf == NULL) {
1525                         ret =  -ENOMEM;
1526                         goto exit;
1527                 }
1528
1529                 _rtw_memcpy(buf, pie , ielen);
1530
1531                 /* dump */
1532                 {
1533                         int i;
1534                         RTW_INFO("\n wpa_ie(length:%d):\n", ielen);
1535                         for (i = 0; i < ielen; i = i + 8)
1536                                 RTW_INFO("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]);
1537                 }
1538
1539                 pos = buf;
1540                 if (ielen < RSN_HEADER_LEN) {
1541                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
1542                         ret  = -1;
1543                         goto exit;
1544                 }
1545
1546 #if 0
1547                 pos += RSN_HEADER_LEN;
1548                 left  = ielen - RSN_HEADER_LEN;
1549
1550                 if (left >= RSN_SELECTOR_LEN) {
1551                         pos += RSN_SELECTOR_LEN;
1552                         left -= RSN_SELECTOR_LEN;
1553                 } else if (left > 0) {
1554                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie length mismatch, %u too much\n", left));
1555                         ret = -1;
1556                         goto exit;
1557                 }
1558 #endif
1559
1560                 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1561                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1562                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
1563                         _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
1564                 }
1565
1566                 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1567                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1568                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1569                         _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
1570                 }
1571
1572                 if (group_cipher == 0)
1573                         group_cipher = WPA_CIPHER_NONE;
1574                 if (pairwise_cipher == 0)
1575                         pairwise_cipher = WPA_CIPHER_NONE;
1576
1577                 switch (group_cipher) {
1578                 case WPA_CIPHER_NONE:
1579                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1580                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1581                         break;
1582                 case WPA_CIPHER_WEP40:
1583                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1584                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1585                         break;
1586                 case WPA_CIPHER_TKIP:
1587                         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
1588                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1589                         break;
1590                 case WPA_CIPHER_CCMP:
1591                         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
1592                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1593                         break;
1594                 case WPA_CIPHER_WEP104:
1595                         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
1596                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1597                         break;
1598                 }
1599
1600                 switch (pairwise_cipher) {
1601                 case WPA_CIPHER_NONE:
1602                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1603                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1604                         break;
1605                 case WPA_CIPHER_WEP40:
1606                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1607                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1608                         break;
1609                 case WPA_CIPHER_TKIP:
1610                         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
1611                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1612                         break;
1613                 case WPA_CIPHER_CCMP:
1614                         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
1615                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1616                         break;
1617                 case WPA_CIPHER_WEP104:
1618                         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1619                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1620                         break;
1621                 }
1622
1623                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1624                 {/* set wps_ie   */
1625                         u16 cnt = 0;
1626                         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
1627
1628                         while (cnt < ielen) {
1629                                 eid = buf[cnt];
1630
1631                                 if ((eid == _VENDOR_SPECIFIC_IE_) && (_rtw_memcmp(&buf[cnt + 2], wps_oui, 4) == _TRUE)) {
1632                                         RTW_INFO("SET WPS_IE\n");
1633
1634                                         padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < MAX_WPS_IE_LEN) ? (buf[cnt + 1] + 2) : MAX_WPS_IE_LEN;
1635
1636                                         _rtw_memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
1637
1638                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1639
1640 #ifdef CONFIG_P2P
1641                                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
1642                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
1643 #endif /* CONFIG_P2P */
1644                                         cnt += buf[cnt + 1] + 2;
1645
1646                                         break;
1647                                 } else {
1648                                         cnt += buf[cnt + 1] + 2; /* goto next    */
1649                                 }
1650                         }
1651                 }
1652         }
1653
1654         /* TKIP and AES disallow multicast packets until installing group key */
1655         if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
1656             || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
1657             || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
1658                 /* WPS open need to enable multicast
1659                  * || check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE) */
1660                 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
1661
1662         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1663                 ("rtw_set_wpa_ie: pairwise_cipher=0x%08x padapter->securitypriv.ndisencryptstatus=%d padapter->securitypriv.ndisauthtype=%d\n",
1664                 pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
1665
1666 exit:
1667
1668         if (buf)
1669                 rtw_mfree(buf, ielen);
1670
1671         return ret;
1672 }
1673
1674 static int rtw_wx_get_name(struct net_device *dev,
1675                            struct iw_request_info *info,
1676                            union iwreq_data *wrqu, char *extra)
1677 {
1678         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1679         u16 cap;
1680         u32 ht_ielen = 0;
1681         char *p;
1682         u8 ht_cap = _FALSE, vht_cap = _FALSE;
1683         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1684         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
1685         NDIS_802_11_RATES_EX *prates = NULL;
1686
1687         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code=%x\n", info->cmd));
1688
1689         _func_enter_;
1690
1691         if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
1692                 /* parsing HT_CAP_IE */
1693                 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
1694                 if (p && ht_ielen > 0)
1695                         ht_cap = _TRUE;
1696
1697 #ifdef CONFIG_80211AC_VHT
1698                 if (pmlmepriv->vhtpriv.vht_option == _TRUE)
1699                         vht_cap = _TRUE;
1700 #endif
1701
1702                 prates = &pcur_bss->SupportedRates;
1703
1704                 if (rtw_is_cckratesonly_included((u8 *)prates) == _TRUE) {
1705                         if (ht_cap == _TRUE)
1706                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
1707                         else
1708                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
1709                 } else if ((rtw_is_cckrates_included((u8 *)prates)) == _TRUE) {
1710                         if (ht_cap == _TRUE)
1711                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
1712                         else
1713                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
1714                 } else {
1715                         if (pcur_bss->Configuration.DSConfig > 14) {
1716 #ifdef CONFIG_80211AC_VHT
1717                                 if (vht_cap == _TRUE)
1718                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC");
1719                                 else
1720 #endif
1721                                 {
1722                                         if (ht_cap == _TRUE)
1723                                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
1724                                         else
1725                                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
1726                                 }
1727                         } else {
1728                                 if (ht_cap == _TRUE)
1729                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
1730                                 else
1731                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
1732                         }
1733                 }
1734         } else {
1735                 /* prates = &padapter->registrypriv.dev_network.SupportedRates; */
1736                 /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
1737                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
1738         }
1739
1740         _func_exit_;
1741
1742         return 0;
1743 }
1744
1745 static int rtw_wx_set_freq(struct net_device *dev,
1746                            struct iw_request_info *info,
1747                            union iwreq_data *wrqu, char *extra)
1748 {
1749
1750         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1751         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
1752         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1753         struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
1754         int exp = 1, freq = 0, div = 0;
1755
1756         _func_enter_;
1757
1758         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
1759
1760         if (wrqu->freq.m <= 1000) {
1761                 if (wrqu->freq.flags == IW_FREQ_AUTO) {
1762                         if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, wrqu->freq.m) > 0) {
1763                                 padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
1764                                 RTW_INFO("%s: channel is auto, set to channel %d\n", __func__, wrqu->freq.m);
1765                         } else {
1766                                 padapter->mlmeextpriv.cur_channel = 1;
1767                                 RTW_INFO("%s: channel is auto, Channel Plan don't match just set to channel 1\n", __func__);
1768                         }
1769                 } else {
1770                         padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
1771                         RTW_INFO("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
1772                 }
1773         } else {
1774                 while (wrqu->freq.e) {
1775                         exp *= 10;
1776                         wrqu->freq.e--;
1777                 }
1778
1779                 freq = wrqu->freq.m;
1780
1781                 while (!(freq % 10)) {
1782                         freq /= 10;
1783                         exp *= 10;
1784                 }
1785
1786                 /* freq unit is MHz here */
1787                 div = 1000000 / exp;
1788
1789                 if (div)
1790                         freq /= div;
1791                 else {
1792                         div = exp / 1000000;
1793                         freq *= div;
1794                 }
1795
1796                 /* If freq is invalid, rtw_freq2ch() will return channel 1 */
1797                 padapter->mlmeextpriv.cur_channel = rtw_freq2ch(freq);
1798                 RTW_INFO("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
1799         }
1800
1801         set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
1802
1803         _func_exit_;
1804
1805         return 0;
1806 }
1807
1808 static int rtw_wx_get_freq(struct net_device *dev,
1809                            struct iw_request_info *info,
1810                            union iwreq_data *wrqu, char *extra)
1811 {
1812         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1813         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1814         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
1815
1816         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE) {
1817
1818                 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
1819                 wrqu->freq.e = 1;
1820                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
1821
1822         } else {
1823                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
1824                 wrqu->freq.e = 1;
1825                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
1826         }
1827
1828         return 0;
1829 }
1830
1831 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
1832                            union iwreq_data *wrqu, char *b)
1833 {
1834         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1835         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1836         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
1837         int ret = 0;
1838
1839         _func_enter_;
1840
1841         if (_FAIL == rtw_pwr_wakeup(padapter)) {
1842                 ret = -EPERM;
1843                 goto exit;
1844         }
1845
1846         if (!rtw_is_hw_init_completed(padapter)) {
1847                 ret = -EPERM;
1848                 goto exit;
1849         }
1850
1851         /* initial default type */
1852         dev->type = ARPHRD_ETHER;
1853
1854         switch (wrqu->mode) {
1855         case IW_MODE_MONITOR:
1856                 networkType = Ndis802_11Monitor;
1857 #if 0
1858                 dev->type = ARPHRD_IEEE80211; /* IEEE 802.11 : 801 */
1859 #endif
1860                 dev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */
1861                 RTW_INFO("set_mode = IW_MODE_MONITOR\n");
1862                 break;
1863
1864         case IW_MODE_AUTO:
1865                 networkType = Ndis802_11AutoUnknown;
1866                 RTW_INFO("set_mode = IW_MODE_AUTO\n");
1867                 break;
1868         case IW_MODE_ADHOC:
1869                 networkType = Ndis802_11IBSS;
1870                 RTW_INFO("set_mode = IW_MODE_ADHOC\n");
1871                 break;
1872         case IW_MODE_MASTER:
1873                 networkType = Ndis802_11APMode;
1874                 RTW_INFO("set_mode = IW_MODE_MASTER\n");
1875                 /* rtw_setopmode_cmd(padapter, networkType,_TRUE);       */
1876                 break;
1877         case IW_MODE_INFRA:
1878                 networkType = Ndis802_11Infrastructure;
1879                 RTW_INFO("set_mode = IW_MODE_INFRA\n");
1880                 break;
1881
1882         default:
1883                 ret = -EINVAL;;
1884                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
1885                 goto exit;
1886         }
1887
1888         /*
1889                 if(Ndis802_11APMode == networkType)
1890                 {
1891                         rtw_setopmode_cmd(padapter, networkType,_TRUE);
1892                 }
1893                 else
1894                 {
1895                         rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown,_TRUE);
1896                 }
1897         */
1898
1899         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == _FALSE) {
1900
1901                 ret = -EPERM;
1902                 goto exit;
1903
1904         }
1905
1906         rtw_setopmode_cmd(padapter, networkType, _TRUE);
1907
1908         if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) == _TRUE)
1909                 rtw_indicate_connect(padapter);
1910
1911 exit:
1912
1913         _func_exit_;
1914
1915         return ret;
1916
1917 }
1918
1919 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
1920                            union iwreq_data *wrqu, char *b)
1921 {
1922         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1923         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1924
1925         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
1926
1927         _func_enter_;
1928
1929         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
1930                 wrqu->mode = IW_MODE_INFRA;
1931         else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) ||
1932                  (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
1933
1934                 wrqu->mode = IW_MODE_ADHOC;
1935         else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
1936                 wrqu->mode = IW_MODE_MASTER;
1937         else if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) == _TRUE)
1938                 wrqu->mode = IW_MODE_MONITOR;
1939         else
1940                 wrqu->mode = IW_MODE_AUTO;
1941
1942         _func_exit_;
1943
1944         return 0;
1945
1946 }
1947
1948
1949 static int rtw_wx_set_pmkid(struct net_device *dev,
1950                             struct iw_request_info *a,
1951                             union iwreq_data *wrqu, char *extra)
1952 {
1953         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1954         u8          j, blInserted = _FALSE;
1955         int         intReturn = _FALSE;
1956         struct mlme_priv  *pmlmepriv = &padapter->mlmepriv;
1957         struct security_priv *psecuritypriv = &padapter->securitypriv;
1958         struct iw_pmksa  *pPMK = (struct iw_pmksa *) extra;
1959         u8     strZeroMacAddress[ETH_ALEN] = { 0x00 };
1960         u8     strIssueBssid[ETH_ALEN] = { 0x00 };
1961
1962 #if 0
1963         struct iw_pmksa {
1964                 __u32   cmd;
1965                 struct sockaddr bssid;
1966                 __u8    pmkid[IW_PMKID_LEN];   /* IW_PMKID_LEN=16 */
1967         }
1968         There are the BSSID information in the bssid.sa_data array.
1969         If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
1970         If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID / BSSID to driver.
1971         If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID / BSSID from driver.
1972 #endif
1973
1974         _rtw_memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
1975         if (pPMK->cmd == IW_PMKSA_ADD) {
1976                 RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
1977                 if (_rtw_memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN) == _TRUE)
1978                         return intReturn ;
1979                 else
1980                         intReturn = _TRUE;
1981                 blInserted = _FALSE;
1982
1983                 /* overwrite PMKID */
1984                 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
1985                         if (_rtw_memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) == _TRUE) {
1986                                 /* BSSID is matched, the same AP => rewrite with new PMKID. */
1987
1988                                 RTW_INFO("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
1989
1990                                 _rtw_memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1991                                 psecuritypriv->PMKIDList[j].bUsed = _TRUE;
1992                                 psecuritypriv->PMKIDIndex = j + 1;
1993                                 blInserted = _TRUE;
1994                                 break;
1995                         }
1996                 }
1997
1998                 if (!blInserted) {
1999                         /* Find a new entry */
2000                         RTW_INFO("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
2001                                  psecuritypriv->PMKIDIndex);
2002
2003                         _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
2004                         _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
2005
2006                         psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = _TRUE;
2007                         psecuritypriv->PMKIDIndex++ ;
2008                         if (psecuritypriv->PMKIDIndex == 16)
2009                                 psecuritypriv->PMKIDIndex = 0;
2010                 }
2011         } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
2012                 RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
2013                 intReturn = _TRUE;
2014                 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
2015                         if (_rtw_memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) == _TRUE) {
2016                                 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
2017                                 _rtw_memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
2018                                 psecuritypriv->PMKIDList[j].bUsed = _FALSE;
2019                                 break;
2020                         }
2021                 }
2022         } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
2023                 RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
2024                 _rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
2025                 psecuritypriv->PMKIDIndex = 0;
2026                 intReturn = _TRUE;
2027         }
2028         return intReturn ;
2029 }
2030
2031 static int rtw_wx_get_sens(struct net_device *dev,
2032                            struct iw_request_info *info,
2033                            union iwreq_data *wrqu, char *extra)
2034 {
2035 #ifdef CONFIG_PLATFORM_ROCKCHIPS
2036         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2037         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2038
2039         /*
2040         *  20110311 Commented by Jeff
2041         *  For rockchip platform's wpa_driver_wext_get_rssi
2042         */
2043         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
2044                 /* wrqu->sens.value=-padapter->recvpriv.signal_strength; */
2045                 wrqu->sens.value = -padapter->recvpriv.rssi;
2046                 /* RTW_INFO("%s: %d\n", __FUNCTION__, wrqu->sens.value); */
2047                 wrqu->sens.fixed = 0; /* no auto select */
2048         } else
2049 #endif
2050         {
2051                 wrqu->sens.value = 0;
2052                 wrqu->sens.fixed = 0;   /* no auto select */
2053                 wrqu->sens.disabled = 1;
2054         }
2055         return 0;
2056 }
2057
2058 static int rtw_wx_get_range(struct net_device *dev,
2059                             struct iw_request_info *info,
2060                             union iwreq_data *wrqu, char *extra)
2061 {
2062         struct iw_range *range = (struct iw_range *)extra;
2063         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2064         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2065
2066         u16 val;
2067         int i;
2068
2069         _func_enter_;
2070
2071         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code=%x\n", info->cmd));
2072
2073         wrqu->data.length = sizeof(*range);
2074         _rtw_memset(range, 0, sizeof(*range));
2075
2076         /* Let's try to keep this struct in the same order as in
2077          * linux/include/wireless.h
2078          */
2079
2080         /* TODO: See what values we can set, and remove the ones we can't
2081          * set, or fill them with some default data.
2082          */
2083
2084         /* ~5 Mb/s real (802.11b) */
2085         range->throughput = 5 * 1000 * 1000;
2086
2087         /* TODO: Not used in 802.11b?
2088         *       range->min_nwid;         Minimal NWID we are able to set  */
2089         /* TODO: Not used in 802.11b?
2090         *       range->max_nwid;         Maximal NWID we are able to set  */
2091
2092         /* Old Frequency (backward compat - moved lower ) */
2093         /*      range->old_num_channels;
2094          *      range->old_num_frequency;
2095          *      range->old_freq[6];  Filler to keep "version" at the same offset  */
2096
2097         /* signal level threshold range */
2098
2099         /* Quality of link & SNR stuff */
2100         /* Quality range (link, level, noise)
2101          * If the quality is absolute, it will be in the range [0 ; max_qual],
2102          * if the quality is dBm, it will be in the range [max_qual ; 0].
2103          * Don't forget that we use 8 bit arithmetics...
2104          *
2105          * If percentage range is 0~100
2106          * Signal strength dbm range logical is -100 ~ 0
2107          * but usually value is -90 ~ -20
2108          * When CONFIG_SIGNAL_SCALE_MAPPING is defined, dbm range is -95 ~ -45
2109          */
2110         range->max_qual.qual = 100;
2111 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
2112         range->max_qual.level = (u8)-100;
2113         range->max_qual.noise = (u8)-100;
2114         range->max_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
2115         range->max_qual.updated |= IW_QUAL_DBM;
2116 #else /* !CONFIG_SIGNAL_DISPLAY_DBM */
2117         /* percent values between 0 and 100. */
2118         range->max_qual.level = 100;
2119         range->max_qual.noise = 100;
2120         range->max_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
2121 #endif /* !CONFIG_SIGNAL_DISPLAY_DBM */
2122
2123         /* This should contain the average/typical values of the quality
2124          * indicator. This should be the threshold between a "good" and
2125          * a "bad" link (example : monitor going from green to orange).
2126          * Currently, user space apps like quality monitors don't have any
2127          * way to calibrate the measurement. With this, they can split
2128          * the range between 0 and max_qual in different quality level
2129          * (using a geometric subdivision centered on the average).
2130          * I expect that people doing the user space apps will feedback
2131          * us on which value we need to put in each driver... */
2132         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
2133 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
2134         /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
2135         range->avg_qual.level = (u8)-70;
2136         range->avg_qual.noise = 0;
2137         range->avg_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
2138         range->avg_qual.updated |= IW_QUAL_DBM;
2139 #else /* !CONFIG_SIGNAL_DISPLAY_DBM */
2140         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
2141         range->avg_qual.level = 30;
2142         range->avg_qual.noise = 100;
2143         range->avg_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
2144 #endif /* !CONFIG_SIGNAL_DISPLAY_DBM */
2145
2146         range->num_bitrates = RATE_COUNT;
2147
2148         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
2149                 range->bitrate[i] = rtw_rates[i];
2150
2151         range->min_frag = MIN_FRAG_THRESHOLD;
2152         range->max_frag = MAX_FRAG_THRESHOLD;
2153
2154         range->pm_capa = 0;
2155
2156         range->we_version_compiled = WIRELESS_EXT;
2157         range->we_version_source = 16;
2158
2159         /*      range->retry_capa;       What retry options are supported
2160          *      range->retry_flags;      How to decode max/min retry limit
2161          *      range->r_time_flags;     How to decode max/min retry life
2162          *      range->min_retry;        Minimal number of retries
2163          *      range->max_retry;        Maximal number of retries
2164          *      range->min_r_time;       Minimal retry lifetime
2165          *      range->max_r_time;       Maximal retry lifetime  */
2166
2167         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
2168
2169                 /* Include only legal frequencies for some countries */
2170                 if (pmlmeext->channel_set[i].ChannelNum != 0) {
2171                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
2172                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
2173                         range->freq[val].e = 1;
2174                         val++;
2175                 }
2176
2177                 if (val == IW_MAX_FREQUENCIES)
2178                         break;
2179         }
2180
2181         range->num_channels = val;
2182         range->num_frequency = val;
2183
2184         /* Commented by Albert 2009/10/13
2185          * The following code will proivde the security capability to network manager.
2186          * If the driver doesn't provide this capability to network manager,
2187          * the WPA/WPA2 routers can't be choosen in the network manager. */
2188
2189         /*
2190         #define IW_SCAN_CAPA_NONE               0x00
2191         #define IW_SCAN_CAPA_ESSID              0x01
2192         #define IW_SCAN_CAPA_BSSID              0x02
2193         #define IW_SCAN_CAPA_CHANNEL    0x04
2194         #define IW_SCAN_CAPA_MODE               0x08
2195         #define IW_SCAN_CAPA_RATE               0x10
2196         #define IW_SCAN_CAPA_TYPE               0x20
2197         #define IW_SCAN_CAPA_TIME               0x40
2198         */
2199
2200 #if WIRELESS_EXT > 17
2201         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
2202                           IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
2203 #endif
2204
2205 #ifdef IW_SCAN_CAPA_ESSID /* WIRELESS_EXT > 21 */
2206         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_BSSID |
2207                    IW_SCAN_CAPA_CHANNEL | IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
2208 #endif
2209
2210
2211         _func_exit_;
2212
2213         return 0;
2214
2215 }
2216
2217 /* set bssid flow
2218  * s1. rtw_set_802_11_infrastructure_mode()
2219  * s2. rtw_set_802_11_authentication_mode()
2220  * s3. set_802_11_encryption_mode()
2221  * s4. rtw_set_802_11_bssid() */
2222 static int rtw_wx_set_wap(struct net_device *dev,
2223                           struct iw_request_info *info,
2224                           union iwreq_data *awrq,
2225                           char *extra)
2226 {
2227         _irqL   irqL;
2228         uint ret = 0;
2229         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2230         struct sockaddr *temp = (struct sockaddr *)awrq;
2231         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2232         _list   *phead;
2233         u8 *dst_bssid, *src_bssid;
2234         _queue  *queue  = &(pmlmepriv->scanned_queue);
2235         struct  wlan_network    *pnetwork = NULL;
2236         NDIS_802_11_AUTHENTICATION_MODE authmode;
2237
2238         _func_enter_;
2239         /*
2240         #ifdef CONFIG_CONCURRENT_MODE
2241                 if(padapter->adapter_type > PRIMARY_IFACE)
2242                 {
2243                         ret = -EINVAL;
2244                         goto exit;
2245                 }
2246         #endif
2247         */
2248
2249 #ifdef CONFIG_CONCURRENT_MODE
2250         if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == _TRUE) {
2251                 RTW_INFO("set bssid, but buddy_intf is under scanning or linking\n");
2252
2253                 ret = -EINVAL;
2254
2255                 goto exit;
2256         }
2257 #endif
2258
2259         rtw_ps_deny(padapter, PS_DENY_JOIN);
2260         if (_FAIL == rtw_pwr_wakeup(padapter)) {
2261                 ret = -1;
2262                 goto exit;
2263         }
2264
2265         if (!padapter->bup) {
2266                 ret = -1;
2267                 goto exit;
2268         }
2269
2270
2271         if (temp->sa_family != ARPHRD_ETHER) {
2272                 ret = -EINVAL;
2273                 goto exit;
2274         }
2275
2276         authmode = padapter->securitypriv.ndisauthtype;
2277         _enter_critical_bh(&queue->lock, &irqL);
2278         phead = get_list_head(queue);
2279         pmlmepriv->pscanned = get_next(phead);
2280
2281         while (1) {
2282
2283                 if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == _TRUE) {
2284 #if 0
2285                         ret = -EINVAL;
2286                         goto exit;
2287
2288                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
2289                                 rtw_set_802_11_bssid(padapter, temp->sa_data);
2290                                 goto exit;
2291                         } else {
2292                                 ret = -EINVAL;
2293                                 goto exit;
2294                         }
2295 #endif
2296
2297                         break;
2298                 }
2299
2300                 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
2301
2302                 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
2303
2304                 dst_bssid = pnetwork->network.MacAddress;
2305
2306                 src_bssid = temp->sa_data;
2307
2308                 if ((_rtw_memcmp(dst_bssid, src_bssid, ETH_ALEN)) == _TRUE) {
2309                         if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
2310                                 ret = -1;
2311                                 _exit_critical_bh(&queue->lock, &irqL);
2312                                 goto exit;
2313                         }
2314
2315                         break;
2316                 }
2317
2318         }
2319         _exit_critical_bh(&queue->lock, &irqL);
2320
2321         rtw_set_802_11_authentication_mode(padapter, authmode);
2322         /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
2323         if (rtw_set_802_11_bssid(padapter, temp->sa_data) == _FALSE) {
2324                 ret = -1;
2325                 goto exit;
2326         }
2327
2328 exit:
2329
2330         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
2331
2332         _func_exit_;
2333
2334         return ret;
2335 }
2336
2337 static int rtw_wx_get_wap(struct net_device *dev,
2338                           struct iw_request_info *info,
2339                           union iwreq_data *wrqu, char *extra)
2340 {
2341
2342         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2343         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2344         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
2345
2346         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
2347
2348         _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
2349
2350         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
2351
2352         _func_enter_;
2353
2354         if (((check_fwstate(pmlmepriv, _FW_LINKED)) == _TRUE) ||
2355             ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE) ||
2356             ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == _TRUE))
2357
2358                 _rtw_memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
2359         else
2360                 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
2361
2362         _func_exit_;
2363
2364         return 0;
2365
2366 }
2367
2368 static int rtw_wx_set_mlme(struct net_device *dev,
2369                            struct iw_request_info *info,
2370                            union iwreq_data *wrqu, char *extra)
2371 {
2372 #if 0
2373         /* SIOCSIWMLME data */
2374         struct  iw_mlme {
2375                 __u16           cmd; /* IW_MLME_* */
2376                 __u16           reason_code;
2377                 struct sockaddr addr;
2378         };
2379 #endif
2380
2381         int ret = 0;
2382         u16 reason;
2383         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2384         struct iw_mlme *mlme = (struct iw_mlme *) extra;
2385
2386
2387         if (mlme == NULL)
2388                 return -1;
2389
2390         RTW_INFO("%s\n", __FUNCTION__);
2391
2392         reason = cpu_to_le16(mlme->reason_code);
2393
2394
2395         RTW_INFO("%s, cmd=%d, reason=%d\n", __FUNCTION__, mlme->cmd, reason);
2396
2397
2398         switch (mlme->cmd) {
2399         case IW_MLME_DEAUTH:
2400                 if (!rtw_set_802_11_disassociate(padapter))
2401                         ret = -1;
2402                 break;
2403
2404         case IW_MLME_DISASSOC:
2405                 if (!rtw_set_802_11_disassociate(padapter))
2406                         ret = -1;
2407
2408                 break;
2409
2410         default:
2411                 return -EOPNOTSUPP;
2412         }
2413
2414         return ret;
2415 }
2416
2417 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
2418                            union iwreq_data *wrqu, char *extra)
2419 {
2420         u8 _status = _FALSE;
2421         int ret = 0;
2422         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2423         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2424         NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
2425
2426 #ifdef CONFIG_P2P
2427         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2428 #endif /* CONFIG_P2P */
2429         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
2430
2431         _func_enter_;
2432
2433 #ifdef DBG_IOCTL
2434         RTW_INFO("DBG_IOCTL %s:%d\n", __FUNCTION__, __LINE__);
2435 #endif
2436
2437 #ifdef CONFIG_MP_INCLUDED
2438         if (rtw_mi_mp_mode_check(padapter)) {
2439                 RTW_INFO("MP mode block Scan request\n");
2440                 ret = -EPERM;
2441                 goto exit;
2442         }
2443 #endif
2444         if (rtw_is_scan_deny(padapter)) {
2445                 indicate_wx_scan_complete_event(padapter);
2446                 goto exit;
2447         }
2448
2449         rtw_ps_deny(padapter, PS_DENY_SCAN);
2450         if (_FAIL == rtw_pwr_wakeup(padapter)) {
2451                 ret = -1;
2452                 goto exit;
2453         }
2454
2455         if (!rtw_is_adapter_up(padapter)) {
2456                 ret = -1;
2457                 goto exit;
2458         }
2459
2460 #ifndef CONFIG_DOSCAN_IN_BUSYTRAFFIC
2461         /* When Busy Traffic, driver do not site survey. So driver return success. */
2462         /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
2463         /* modify by thomas 2011-02-22. */
2464         if (rtw_mi_busy_traffic_check(padapter, _FALSE)) {
2465                 indicate_wx_scan_complete_event(padapter);
2466                 goto exit;
2467         }
2468 #endif
2469
2470         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2471                 RTW_INFO("AP mode process WPS\n");
2472                 indicate_wx_scan_complete_event(padapter);
2473                 goto exit;
2474         }
2475
2476         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == _TRUE) {
2477                 indicate_wx_scan_complete_event(padapter);
2478                 goto exit;
2479         }
2480
2481 #ifdef CONFIG_CONCURRENT_MODE
2482         if (rtw_mi_buddy_check_fwstate(padapter,
2483                        _FW_UNDER_SURVEY | _FW_UNDER_LINKING | WIFI_UNDER_WPS)) {
2484
2485                 indicate_wx_scan_complete_event(padapter);
2486                 goto exit;
2487         }
2488 #endif
2489
2490 #ifdef CONFIG_P2P
2491         if (pwdinfo->p2p_state != P2P_STATE_NONE) {
2492                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
2493                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
2494                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
2495                 rtw_free_network_queue(padapter, _TRUE);
2496         }
2497 #endif /* CONFIG_P2P */
2498
2499         _rtw_memset(ssid, 0, sizeof(NDIS_802_11_SSID) * RTW_SSID_SCAN_AMOUNT);
2500
2501 #if WIRELESS_EXT >= 17
2502         if (wrqu->data.length == sizeof(struct iw_scan_req)) {
2503                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
2504
2505                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
2506                         int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
2507
2508                         _rtw_memcpy(ssid[0].Ssid, req->essid, len);
2509                         ssid[0].SsidLength = len;
2510
2511                         RTW_INFO("IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
2512
2513                         _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, 1, NULL, 0);
2514
2515                 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
2516                         RTW_INFO("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
2517
2518         } else
2519 #endif
2520
2521                 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
2522                     && _rtw_memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
2523                    ) {
2524                         int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
2525                         char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
2526                         char section;
2527                         char sec_len;
2528                         int ssid_index = 0;
2529
2530                         /* RTW_INFO("%s COMBO_SCAN header is recognized\n", __FUNCTION__); */
2531
2532                         while (len >= 1) {
2533                                 section = *(pos++);
2534                                 len -= 1;
2535
2536                                 switch (section) {
2537                                 case WEXT_CSCAN_SSID_SECTION:
2538                                         /* RTW_INFO("WEXT_CSCAN_SSID_SECTION\n"); */
2539                                         if (len < 1) {
2540                                                 len = 0;
2541                                                 break;
2542                                         }
2543
2544                                         sec_len = *(pos++);
2545                                         len -= 1;
2546
2547                                         if (sec_len > 0 && sec_len <= len) {
2548                                                 ssid[ssid_index].SsidLength = sec_len;
2549                                                 _rtw_memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
2550                                                 /* RTW_INFO("%s COMBO_SCAN with specific ssid:%s, %d\n", __FUNCTION__ */
2551                                                 /*      , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength); */
2552                                                 ssid_index++;
2553                                         }
2554
2555                                         pos += sec_len;
2556                                         len -= sec_len;
2557                                         break;
2558
2559
2560                                 case WEXT_CSCAN_CHANNEL_SECTION:
2561                                         /* RTW_INFO("WEXT_CSCAN_CHANNEL_SECTION\n"); */
2562                                         pos += 1;
2563                                         len -= 1;
2564                                         break;
2565                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
2566                                         /* RTW_INFO("WEXT_CSCAN_ACTV_DWELL_SECTION\n"); */
2567                                         pos += 2;
2568                                         len -= 2;
2569                                         break;
2570                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
2571                                         /* RTW_INFO("WEXT_CSCAN_PASV_DWELL_SECTION\n"); */
2572                                         pos += 2;
2573                                         len -= 2;
2574                                         break;
2575                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
2576                                         /* RTW_INFO("WEXT_CSCAN_HOME_DWELL_SECTION\n"); */
2577                                         pos += 2;
2578                                         len -= 2;
2579                                         break;
2580                                 case WEXT_CSCAN_TYPE_SECTION:
2581                                         /* RTW_INFO("WEXT_CSCAN_TYPE_SECTION\n"); */
2582                                         pos += 1;
2583                                         len -= 1;
2584                                         break;
2585 #if 0
2586                                 case WEXT_CSCAN_NPROBE_SECTION:
2587                                         RTW_INFO("WEXT_CSCAN_NPROBE_SECTION\n");
2588                                         break;
2589 #endif
2590
2591                                 default:
2592                                         /* RTW_INFO("Unknown CSCAN section %c\n", section); */
2593                                         len = 0; /* stop parsing */
2594                                 }
2595                                 /* RTW_INFO("len:%d\n", len); */
2596
2597                         }
2598
2599                         /* jeff: it has still some scan paramater to parse, we only do this now... */
2600                         _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT, NULL, 0);
2601
2602                 } else
2603
2604                         _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0, NULL, 0);
2605
2606         if (_status == _FALSE)
2607                 ret = -1;
2608
2609 exit:
2610
2611         rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
2612
2613 #ifdef DBG_IOCTL
2614         RTW_INFO("DBG_IOCTL %s:%d return %d\n", __FUNCTION__, __LINE__, ret);
2615 #endif
2616
2617         _func_exit_;
2618
2619         return ret;
2620 }
2621
2622 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
2623                            union iwreq_data *wrqu, char *extra)
2624 {
2625         _irqL   irqL;
2626         _list                                   *plist, *phead;
2627         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2628         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2629         _queue                          *queue  = &(pmlmepriv->scanned_queue);
2630         struct  wlan_network    *pnetwork = NULL;
2631         char *ev = extra;
2632         char *stop = ev + wrqu->data.length;
2633         u32 ret = 0;
2634         u32 cnt = 0;
2635         u32 wait_for_surveydone;
2636         sint wait_status;
2637
2638 #ifdef CONFIG_P2P
2639         struct  wifidirect_info *pwdinfo = &padapter->wdinfo;
2640 #endif /* CONFIG_P2P */
2641         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
2642         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
2643
2644         _func_enter_;
2645
2646 #ifdef DBG_IOCTL
2647         RTW_INFO("DBG_IOCTL %s:%d\n", __FUNCTION__, __LINE__);
2648 #endif
2649
2650         if (adapter_to_pwrctl(padapter)->brfoffbyhw && rtw_is_drv_stopped(padapter)) {
2651                 ret = -EINVAL;
2652                 goto exit;
2653         }
2654
2655 #ifdef CONFIG_P2P
2656         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
2657                 wait_for_surveydone = 200;
2658         else {
2659                 /*      P2P is disabled */
2660                 wait_for_surveydone = 100;
2661         }
2662 #else
2663         {
2664                 wait_for_surveydone = 100;
2665         }
2666 #endif /* CONFIG_P2P */
2667
2668 #if 1 /* Wireless Extension use EAGAIN to try */
2669         wait_status = _FW_UNDER_SURVEY
2670 #ifndef CONFIG_ANDROID
2671                       | _FW_UNDER_LINKING
2672 #endif
2673                       ;
2674
2675         while (check_fwstate(pmlmepriv, wait_status) == _TRUE)
2676                 return -EAGAIN;
2677 #else
2678         wait_status = _FW_UNDER_SURVEY
2679 #ifndef CONFIG_ANDROID
2680                       | _FW_UNDER_LINKING
2681 #endif
2682                       ;
2683
2684         while (check_fwstate(pmlmepriv, wait_status) == _TRUE) {
2685                 rtw_msleep_os(30);
2686                 cnt++;
2687                 if (cnt > wait_for_surveydone)
2688                         break;
2689         }
2690 #endif
2691         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2692
2693         phead = get_list_head(queue);
2694         plist = get_next(phead);
2695
2696         while (1) {
2697                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
2698                         break;
2699
2700                 if ((stop - ev) < SCAN_ITEM_SIZE) {
2701                         ret = -E2BIG;
2702                         break;
2703                 }
2704
2705                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2706
2707                 /* report network only if the current channel set contains the channel to which this network belongs */
2708                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
2709                     && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE
2710                     && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
2711                    )
2712                         ev = translate_scan(padapter, a, pnetwork, ev, stop);
2713
2714                 plist = get_next(plist);
2715
2716         }
2717
2718         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2719
2720         wrqu->data.length = ev - extra;
2721         wrqu->data.flags = 0;
2722
2723 exit:
2724
2725         _func_exit_;
2726
2727 #ifdef DBG_IOCTL
2728         RTW_INFO("DBG_IOCTL %s:%d return %d\n", __FUNCTION__, __LINE__, ret);
2729 #endif
2730
2731         return ret ;
2732
2733 }
2734
2735 /* set ssid flow
2736  * s1. rtw_set_802_11_infrastructure_mode()
2737  * s2. set_802_11_authenticaion_mode()
2738  * s3. set_802_11_encryption_mode()
2739  * s4. rtw_set_802_11_ssid() */
2740 static int rtw_wx_set_essid(struct net_device *dev,
2741                             struct iw_request_info *a,
2742                             union iwreq_data *wrqu, char *extra)
2743 {
2744         _irqL irqL;
2745         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2746         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2747         _queue *queue = &pmlmepriv->scanned_queue;
2748         _list *phead;
2749         s8 status = _TRUE;
2750         struct wlan_network *pnetwork = NULL;
2751         NDIS_802_11_AUTHENTICATION_MODE authmode;
2752         NDIS_802_11_SSID ndis_ssid;
2753         u8 *dst_ssid, *src_ssid;
2754
2755         uint ret = 0, len;
2756
2757         _func_enter_;
2758
2759 #ifdef DBG_IOCTL
2760         RTW_INFO("DBG_IOCTL %s:%d\n", __FUNCTION__, __LINE__);
2761 #endif
2762 #ifdef CONFIG_WEXT_DONT_JOIN_BYSSID
2763         RTW_INFO("%s: CONFIG_WEXT_DONT_JOIN_BYSSID be defined!! only allow bssid joining\n", __func__);
2764         return -EPERM;
2765 #endif
2766
2767 #if WIRELESS_EXT <= 20
2768         if ((wrqu->essid.length - 1) > IW_ESSID_MAX_SIZE) {
2769 #else
2770         if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
2771 #endif
2772                 ret = -E2BIG;
2773                 goto exit;
2774         }
2775
2776
2777         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2778                 ("+rtw_wx_set_essid: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
2779
2780         rtw_ps_deny(padapter, PS_DENY_JOIN);
2781         if (_FAIL == rtw_pwr_wakeup(padapter)) {
2782                 ret = -1;
2783                 goto exit;
2784         }
2785
2786         if (!padapter->bup) {
2787                 ret = -1;
2788                 goto exit;
2789         }
2790
2791         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2792                 ret = -1;
2793                 goto exit;
2794         }
2795
2796 #ifdef CONFIG_CONCURRENT_MODE
2797         if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
2798                 RTW_INFO("set ssid, but buddy_intf is under scanning or linking\n");
2799                 ret = -EINVAL;
2800                 goto exit;
2801         }
2802 #endif
2803         authmode = padapter->securitypriv.ndisauthtype;
2804         RTW_INFO("=>%s\n", __FUNCTION__);
2805         if (wrqu->essid.flags && wrqu->essid.length) {
2806                 /* Commented by Albert 20100519 */
2807                 /* We got the codes in "set_info" function of iwconfig source code. */
2808                 /*      ========================================= */
2809                 /*      wrq.u.essid.length = strlen(essid) + 1; */
2810                 /*      if(we_kernel_version > 20) */
2811                 /*              wrq.u.essid.length--; */
2812                 /*      ========================================= */
2813                 /*      That means, if the WIRELESS_EXT less than or equal to 20, the correct ssid len should subtract 1. */
2814 #if WIRELESS_EXT <= 20
2815                 len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE;
2816 #else
2817                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
2818 #endif
2819
2820                 if (wrqu->essid.length != 33)
2821                         RTW_INFO("ssid=%s, len=%d\n", extra, wrqu->essid.length);
2822
2823                 _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
2824                 ndis_ssid.SsidLength = len;
2825                 _rtw_memcpy(ndis_ssid.Ssid, extra, len);
2826                 src_ssid = ndis_ssid.Ssid;
2827
2828                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid=[%s]\n", src_ssid));
2829                 _enter_critical_bh(&queue->lock, &irqL);
2830                 phead = get_list_head(queue);
2831                 pmlmepriv->pscanned = get_next(phead);
2832
2833                 while (1) {
2834                         if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == _TRUE) {
2835 #if 0
2836                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
2837                                         rtw_set_802_11_ssid(padapter, &ndis_ssid);
2838
2839                                         goto exit;
2840                                 } else {
2841                                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_ssid(): scanned_queue is empty\n"));
2842                                         ret = -EINVAL;
2843                                         goto exit;
2844                                 }
2845 #endif
2846                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
2847                                         ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
2848
2849                                 break;
2850                         }
2851
2852                         pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
2853
2854                         pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
2855
2856                         dst_ssid = pnetwork->network.Ssid.Ssid;
2857
2858                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2859                                  ("rtw_wx_set_essid: dst_ssid=%s\n",
2860                                   pnetwork->network.Ssid.Ssid));
2861
2862                         if ((_rtw_memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength) == _TRUE) &&
2863                             (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
2864                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2865                                         ("rtw_wx_set_essid: find match, set infra mode\n"));
2866
2867                                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
2868                                         if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
2869                                                 continue;
2870                                 }
2871
2872                                 if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == _FALSE) {
2873                                         ret = -1;
2874                                         _exit_critical_bh(&queue->lock, &irqL);
2875                                         goto exit;
2876                                 }
2877
2878                                 break;
2879                         }
2880                 }
2881                 _exit_critical_bh(&queue->lock, &irqL);
2882                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2883                          ("set ssid: set_802_11_auth. mode=%d\n", authmode));
2884                 rtw_set_802_11_authentication_mode(padapter, authmode);
2885                 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
2886                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
2887                         ret = -1;
2888                         goto exit;
2889                 }
2890         }
2891
2892 exit:
2893
2894         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
2895
2896         RTW_INFO("<=%s, ret %d\n", __FUNCTION__, ret);
2897
2898 #ifdef DBG_IOCTL
2899         RTW_INFO("DBG_IOCTL %s:%d return %d\n", __FUNCTION__, __LINE__, ret);
2900 #endif
2901
2902         _func_exit_;
2903
2904         return ret;
2905 }
2906
2907 static int rtw_wx_get_essid(struct net_device *dev,
2908                             struct iw_request_info *a,
2909                             union iwreq_data *wrqu, char *extra)
2910 {
2911         u32 len, ret = 0;
2912         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2913         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2914         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
2915
2916         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
2917
2918         _func_enter_;
2919
2920         if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
2921             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
2922                 len = pcur_bss->Ssid.SsidLength;
2923
2924                 wrqu->essid.length = len;
2925
2926                 _rtw_memcpy(extra, pcur_bss->Ssid.Ssid, len);
2927
2928                 wrqu->essid.flags = 1;
2929         } else {
2930                 ret = -1;
2931                 goto exit;
2932         }
2933
2934 exit:
2935
2936         _func_exit_;
2937
2938         return ret;
2939
2940 }
2941
2942 static int rtw_wx_set_rate(struct net_device *dev,
2943                            struct iw_request_info *a,
2944                            union iwreq_data *wrqu, char *extra)
2945 {
2946         int     i, ret = 0;
2947         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2948         u8      datarates[NumRates];
2949         u32     target_rate = wrqu->bitrate.value;
2950         u32     fixed = wrqu->bitrate.fixed;
2951         u32     ratevalue = 0;
2952         u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
2953
2954         _func_enter_;
2955
2956         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
2957         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
2958
2959         if (target_rate == -1) {
2960                 ratevalue = 11;
2961                 goto set_rate;
2962         }
2963         target_rate = target_rate / 100000;
2964
2965         switch (target_rate) {
2966         case 10:
2967                 ratevalue = 0;
2968                 break;
2969         case 20:
2970                 ratevalue = 1;
2971                 break;
2972         case 55:
2973                 ratevalue = 2;
2974                 break;
2975         case 60:
2976                 ratevalue = 3;
2977                 break;
2978         case 90:
2979                 ratevalue = 4;
2980                 break;
2981         case 110:
2982                 ratevalue = 5;
2983                 break;
2984         case 120:
2985                 ratevalue = 6;
2986                 break;
2987         case 180:
2988                 ratevalue = 7;
2989                 break;
2990         case 240:
2991                 ratevalue = 8;
2992                 break;
2993         case 360:
2994                 ratevalue = 9;
2995                 break;
2996         case 480:
2997                 ratevalue = 10;
2998                 break;
2999         case 540:
3000                 ratevalue = 11;
3001                 break;
3002         default:
3003                 ratevalue = 11;
3004                 break;
3005         }
3006
3007 set_rate:
3008
3009         for (i = 0; i < NumRates; i++) {
3010                 if (ratevalue == mpdatarate[i]) {
3011                         datarates[i] = mpdatarate[i];
3012                         if (fixed == 0)
3013                                 break;
3014                 } else
3015                         datarates[i] = 0xff;
3016
3017                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx=%d\n", datarates[i]));
3018         }
3019
3020         if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
3021                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n"));
3022                 ret = -1;
3023         }
3024
3025         _func_exit_;
3026
3027         return ret;
3028 }
3029
3030 static int rtw_wx_get_rate(struct net_device *dev,
3031                            struct iw_request_info *info,
3032                            union iwreq_data *wrqu, char *extra)
3033 {
3034         u16 max_rate = 0;
3035
3036         max_rate = rtw_get_cur_max_rate((_adapter *)rtw_netdev_priv(dev));
3037
3038         if (max_rate == 0)
3039                 return -EPERM;
3040
3041         wrqu->bitrate.fixed = 0;        /* no auto select */
3042         wrqu->bitrate.value = max_rate * 100000;
3043
3044         return 0;
3045 }
3046
3047 static int rtw_wx_set_rts(struct net_device *dev,
3048                           struct iw_request_info *info,
3049                           union iwreq_data *wrqu, char *extra)
3050 {
3051         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3052
3053         _func_enter_;
3054
3055         if (wrqu->rts.disabled)
3056                 padapter->registrypriv.rts_thresh = 2347;
3057         else {
3058                 if (wrqu->rts.value < 0 ||
3059                     wrqu->rts.value > 2347)
3060                         return -EINVAL;
3061
3062                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
3063         }
3064
3065         RTW_INFO("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
3066
3067         _func_exit_;
3068
3069         return 0;
3070
3071 }
3072
3073 static int rtw_wx_get_rts(struct net_device *dev,
3074                           struct iw_request_info *info,
3075                           union iwreq_data *wrqu, char *extra)
3076 {
3077         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3078
3079         _func_enter_;
3080
3081         RTW_INFO("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
3082
3083         wrqu->rts.value = padapter->registrypriv.rts_thresh;
3084         wrqu->rts.fixed = 0;    /* no auto select */
3085         /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
3086
3087         _func_exit_;
3088
3089         return 0;
3090 }
3091
3092 static int rtw_wx_set_frag(struct net_device *dev,
3093                            struct iw_request_info *info,
3094                            union iwreq_data *wrqu, char *extra)
3095 {
3096         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3097
3098         _func_enter_;
3099
3100         if (wrqu->frag.disabled)
3101                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
3102         else {
3103                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
3104                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
3105                         return -EINVAL;
3106
3107                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
3108         }
3109
3110         RTW_INFO("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
3111
3112         _func_exit_;
3113
3114         return 0;
3115
3116 }
3117
3118 static int rtw_wx_get_frag(struct net_device *dev,
3119                            struct iw_request_info *info,
3120                            union iwreq_data *wrqu, char *extra)
3121 {
3122         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3123
3124         _func_enter_;
3125
3126         RTW_INFO("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
3127
3128         wrqu->frag.value = padapter->xmitpriv.frag_len;
3129         wrqu->frag.fixed = 0;   /* no auto select */
3130         /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
3131
3132         _func_exit_;
3133
3134         return 0;
3135 }
3136
3137 static int rtw_wx_get_retry(struct net_device *dev,
3138                             struct iw_request_info *info,
3139                             union iwreq_data *wrqu, char *extra)
3140 {
3141         /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
3142
3143
3144         wrqu->retry.value = 7;
3145         wrqu->retry.fixed = 0;  /* no auto select */
3146         wrqu->retry.disabled = 1;
3147
3148         return 0;
3149
3150 }
3151
3152 #if 0
3153         #define IW_ENCODE_INDEX         0x00FF  /* Token index (if needed) */
3154         #define IW_ENCODE_FLAGS         0xFF00  /* Flags defined below */
3155         #define IW_ENCODE_MODE          0xF000  /* Modes defined below */
3156         #define IW_ENCODE_DISABLED      0x8000  /* Encoding disabled */
3157         #define IW_ENCODE_ENABLED       0x0000  /* Encoding enabled */
3158         #define IW_ENCODE_RESTRICTED    0x4000  /* Refuse non-encoded packets */
3159         #define IW_ENCODE_OPEN          0x2000  /* Accept non-encoded packets */
3160         #define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
3161         #define IW_ENCODE_TEMP          0x0400  /* Temporary key */
3162         /*
3163         iwconfig wlan0 key on->flags = 0x6001->maybe it means auto
3164         iwconfig wlan0 key off->flags = 0x8800
3165         iwconfig wlan0 key open->flags = 0x2800
3166         iwconfig wlan0 key open 1234567890->flags = 0x2000
3167         iwconfig wlan0 key restricted->flags = 0x4800
3168         iwconfig wlan0 key open [3] 1234567890->flags = 0x2003
3169         iwconfig wlan0 key restricted [2] 1234567890->flags = 0x4002
3170         iwconfig wlan0 key open [3] -> flags = 0x2803
3171         iwconfig wlan0 key restricted [2] -> flags = 0x4802
3172         */
3173 #endif
3174
3175 static int rtw_wx_set_enc(struct net_device *dev,
3176                           struct iw_request_info *info,
3177                           union iwreq_data *wrqu, char *keybuf)
3178 {
3179         u32 key, ret = 0;
3180         u32 keyindex_provided;
3181         NDIS_802_11_WEP  wep;
3182         NDIS_802_11_AUTHENTICATION_MODE authmode;
3183
3184         struct iw_point *erq = &(wrqu->encoding);
3185         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3186         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3187         RTW_INFO("+rtw_wx_set_enc, flags=0x%x\n", erq->flags);
3188
3189         _rtw_memset(&wep, 0, sizeof(NDIS_802_11_WEP));
3190
3191         key = erq->flags & IW_ENCODE_INDEX;
3192
3193         _func_enter_;
3194
3195         if (erq->flags & IW_ENCODE_DISABLED) {
3196                 RTW_INFO("EncryptionDisabled\n");
3197                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
3198                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
3199                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
3200                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
3201                 authmode = Ndis802_11AuthModeOpen;
3202                 padapter->securitypriv.ndisauthtype = authmode;
3203
3204                 goto exit;
3205         }
3206
3207         if (key) {
3208                 if (key > WEP_KEYS)
3209                         return -EINVAL;
3210                 key--;
3211                 keyindex_provided = 1;
3212         } else {
3213                 keyindex_provided = 0;
3214                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
3215                 RTW_INFO("rtw_wx_set_enc, key=%d\n", key);
3216         }
3217
3218         /* set authentication mode       */
3219         if (erq->flags & IW_ENCODE_OPEN) {
3220                 RTW_INFO("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
3221                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
3222
3223 #ifdef CONFIG_PLATFORM_MT53XX
3224                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3225 #else
3226                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
3227 #endif
3228
3229                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
3230                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
3231                 authmode = Ndis802_11AuthModeOpen;
3232                 padapter->securitypriv.ndisauthtype = authmode;
3233         } else if (erq->flags & IW_ENCODE_RESTRICTED) {
3234                 RTW_INFO("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
3235                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
3236
3237 #ifdef CONFIG_PLATFORM_MT53XX
3238                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3239 #else
3240                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
3241 #endif
3242
3243                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
3244                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
3245                 authmode = Ndis802_11AuthModeShared;
3246                 padapter->securitypriv.ndisauthtype = authmode;
3247         } else {
3248                 RTW_INFO("rtw_wx_set_enc():erq->flags=0x%x\n", erq->flags);
3249
3250                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
3251                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
3252                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
3253                 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
3254                 authmode = Ndis802_11AuthModeOpen;
3255                 padapter->securitypriv.ndisauthtype = authmode;
3256         }
3257
3258         wep.KeyIndex = key;
3259         if (erq->length > 0) {
3260                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
3261
3262                 wep.Length = wep.KeyLength + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
3263         } else {
3264                 wep.KeyLength = 0 ;
3265
3266                 if (keyindex_provided == 1) { /* set key_id only, no given KeyMaterial(erq->length==0). */
3267                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
3268
3269                         RTW_INFO("(keyindex_provided == 1), keyid=%d, key_len=%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
3270
3271                         switch (padapter->securitypriv.dot11DefKeylen[key]) {
3272                         case 5:
3273                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
3274                                 break;
3275                         case 13:
3276                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
3277                                 break;
3278                         default:
3279                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
3280                                 break;
3281                         }
3282
3283                         goto exit;
3284
3285                 }
3286
3287         }
3288
3289         wep.KeyIndex |= 0x80000000;
3290
3291         _rtw_memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
3292
3293         if (rtw_set_802_11_add_wep(padapter, &wep) == _FALSE) {
3294                 if (rf_on == pwrpriv->rf_pwrstate)
3295                         ret = -EOPNOTSUPP;
3296                 goto exit;
3297         }
3298
3299 exit:
3300
3301         _func_exit_;
3302
3303         return ret;
3304
3305 }
3306
3307 static int rtw_wx_get_enc(struct net_device *dev,
3308                           struct iw_request_info *info,
3309                           union iwreq_data *wrqu, char *keybuf)
3310 {
3311         uint key, ret = 0;
3312         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3313         struct iw_point *erq = &(wrqu->encoding);
3314         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
3315
3316         _func_enter_;
3317
3318         if (check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE) {
3319                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE) {
3320                         erq->length = 0;
3321                         erq->flags |= IW_ENCODE_DISABLED;
3322                         return 0;
3323                 }
3324         }
3325
3326
3327         key = erq->flags & IW_ENCODE_INDEX;
3328
3329         if (key) {
3330                 if (key > WEP_KEYS)
3331                         return -EINVAL;
3332                 key--;
3333         } else
3334                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
3335
3336         erq->flags = key + 1;
3337
3338         /* if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
3339         /* { */
3340         /* erq->flags |= IW_ENCODE_OPEN; */
3341         /* }      */
3342
3343         switch (padapter->securitypriv.ndisencryptstatus) {
3344         case Ndis802_11EncryptionNotSupported:
3345         case Ndis802_11EncryptionDisabled:
3346
3347                 erq->length = 0;
3348                 erq->flags |= IW_ENCODE_DISABLED;
3349
3350                 break;
3351
3352         case Ndis802_11Encryption1Enabled:
3353
3354                 erq->length = padapter->securitypriv.dot11DefKeylen[key];
3355
3356                 if (erq->length) {
3357                         _rtw_memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
3358
3359                         erq->flags |= IW_ENCODE_ENABLED;
3360
3361                         if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
3362                                 erq->flags |= IW_ENCODE_OPEN;
3363                         else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
3364                                 erq->flags |= IW_ENCODE_RESTRICTED;
3365                 } else {
3366                         erq->length = 0;
3367                         erq->flags |= IW_ENCODE_DISABLED;
3368                 }
3369
3370                 break;
3371
3372         case Ndis802_11Encryption2Enabled:
3373         case Ndis802_11Encryption3Enabled:
3374
3375                 erq->length = 16;
3376                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
3377
3378                 break;
3379
3380         default:
3381                 erq->length = 0;
3382                 erq->flags |= IW_ENCODE_DISABLED;
3383
3384                 break;
3385
3386         }
3387
3388         _func_exit_;
3389
3390         return ret;
3391
3392 }
3393
3394 static int rtw_wx_get_power(struct net_device *dev,
3395                             struct iw_request_info *info,
3396                             union iwreq_data *wrqu, char *extra)
3397 {
3398         /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
3399
3400         wrqu->power.value = 0;
3401         wrqu->power.fixed = 0;  /* no auto select */
3402         wrqu->power.disabled = 1;
3403
3404         return 0;
3405
3406 }
3407
3408 static int rtw_wx_set_gen_ie(struct net_device *dev,
3409                              struct iw_request_info *info,
3410                              union iwreq_data *wrqu, char *extra)
3411 {
3412         int ret;
3413         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3414
3415         ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
3416
3417         return ret;
3418 }
3419
3420 static int rtw_wx_set_auth(struct net_device *dev,
3421                            struct iw_request_info *info,
3422                            union iwreq_data *wrqu, char *extra)
3423 {
3424         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3425         struct iw_param *param = (struct iw_param *)&(wrqu->param);
3426         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
3427         struct security_priv *psecuritypriv = &padapter->securitypriv;
3428         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3429         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3430         u32 value = param->value;
3431         int ret = 0;
3432
3433         switch (param->flags & IW_AUTH_INDEX) {
3434
3435         case IW_AUTH_WPA_VERSION:
3436 #ifdef CONFIG_WAPI_SUPPORT
3437 #ifndef CONFIG_IOCTL_CFG80211
3438                 padapter->wapiInfo.bWapiEnable = false;
3439                 if (value == IW_AUTH_WAPI_VERSION_1) {
3440                         padapter->wapiInfo.bWapiEnable = true;
3441                         psecuritypriv->dot11PrivacyAlgrthm = _SMS4_;
3442                         psecuritypriv->dot118021XGrpPrivacy = _SMS4_;
3443                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
3444                         pmlmeinfo->auth_algo = psecuritypriv->dot11AuthAlgrthm;
3445                         padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
3446                         padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
3447                 }
3448 #endif
3449 #endif
3450                 break;
3451         case IW_AUTH_CIPHER_PAIRWISE:
3452
3453                 break;
3454         case IW_AUTH_CIPHER_GROUP:
3455
3456                 break;
3457         case IW_AUTH_KEY_MGMT:
3458 #ifdef CONFIG_WAPI_SUPPORT
3459 #ifndef CONFIG_IOCTL_CFG80211
3460                 RTW_INFO("rtw_wx_set_auth: IW_AUTH_KEY_MGMT case\n");
3461                 if (value == IW_AUTH_KEY_MGMT_WAPI_PSK)
3462                         padapter->wapiInfo.bWapiPSK = true;
3463                 else
3464                         padapter->wapiInfo.bWapiPSK = false;
3465                 RTW_INFO("rtw_wx_set_auth: IW_AUTH_KEY_MGMT bwapipsk %d\n", padapter->wapiInfo.bWapiPSK);
3466 #endif
3467 #endif
3468                 /*
3469                  *  ??? does not use these parameters
3470                  */
3471                 break;
3472
3473         case IW_AUTH_TKIP_COUNTERMEASURES: {
3474                 if (param->value) {
3475                         /* wpa_supplicant is enabling the tkip countermeasure. */
3476                         padapter->securitypriv.btkip_countermeasure = _TRUE;
3477                 } else {
3478                         /* wpa_supplicant is disabling the tkip countermeasure. */
3479                         padapter->securitypriv.btkip_countermeasure = _FALSE;
3480                 }
3481                 break;
3482         }
3483         case IW_AUTH_DROP_UNENCRYPTED: {
3484                 /* HACK:
3485                  *
3486                  * wpa_supplicant calls set_wpa_enabled when the driver
3487                  * is loaded and unloaded, regardless of if WPA is being
3488                  * used.  No other calls are made which can be used to
3489                  * determine if encryption will be used or not prior to
3490                  * association being expected.  If encryption is not being
3491                  * used, drop_unencrypted is set to false, else true -- we
3492                  * can use this to determine if the CAP_PRIVACY_ON bit should
3493                  * be set.
3494                  */
3495
3496                 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled) {
3497                         break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
3498                         /* then it needn't reset it; */
3499                 }
3500
3501                 if (param->value) {
3502                         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
3503                         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
3504                         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
3505                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
3506                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
3507                 }
3508
3509                 break;
3510         }
3511
3512         case IW_AUTH_80211_AUTH_ALG:
3513
3514 #if defined(CONFIG_ANDROID) || 1
3515                 /*
3516                  *  It's the starting point of a link layer connection using wpa_supplicant
3517                 */
3518                 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3519                         LeaveAllPowerSaveMode(padapter);
3520                         rtw_disassoc_cmd(padapter, 500, _FALSE);
3521                         RTW_INFO("%s...call rtw_indicate_disconnect\n ", __FUNCTION__);
3522                         rtw_indicate_disconnect(padapter, 0, _FALSE);
3523                         rtw_free_assoc_resources(padapter, 1);
3524                 }
3525 #endif
3526
3527
3528                 ret = wpa_set_auth_algs(dev, (u32)param->value);
3529
3530                 break;
3531
3532         case IW_AUTH_WPA_ENABLED:
3533
3534                 /* if(param->value) */
3535                 /* padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; */ /* 802.1x */
3536                 /* else */
3537                 /* padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; */ /* open system */
3538
3539                 /* _disassociate(priv); */
3540
3541                 break;
3542
3543         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3544                 /* ieee->ieee802_1x = param->value; */
3545                 break;
3546
3547         case IW_AUTH_PRIVACY_INVOKED:
3548                 /* ieee->privacy_invoked = param->value; */
3549                 break;
3550
3551 #ifdef CONFIG_WAPI_SUPPORT
3552 #ifndef CONFIG_IOCTL_CFG80211
3553         case IW_AUTH_WAPI_ENABLED:
3554                 break;
3555 #endif
3556 #endif
3557
3558         default:
3559                 return -EOPNOTSUPP;
3560
3561         }
3562
3563         return ret;
3564
3565 }
3566
3567 static int rtw_wx_set_enc_ext(struct net_device *dev,
3568                               struct iw_request_info *info,
3569                               union iwreq_data *wrqu, char *extra)
3570 {
3571         char *alg_name;
3572         u32 param_len;
3573         struct ieee_param *param = NULL;
3574         struct iw_point *pencoding = &wrqu->encoding;
3575         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
3576         int ret = 0;
3577
3578         param_len = sizeof(struct ieee_param) + pext->key_len;
3579         param = (struct ieee_param *)rtw_malloc(param_len);
3580         if (param == NULL)
3581                 return -1;
3582
3583         _rtw_memset(param, 0, param_len);
3584
3585         param->cmd = IEEE_CMD_SET_ENCRYPTION;
3586         _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
3587
3588
3589         switch (pext->alg) {
3590         case IW_ENCODE_ALG_NONE:
3591                 /* todo: remove key */
3592                 /* remove = 1;   */
3593                 alg_name = "none";
3594                 break;
3595         case IW_ENCODE_ALG_WEP:
3596                 alg_name = "WEP";
3597                 break;
3598         case IW_ENCODE_ALG_TKIP:
3599                 alg_name = "TKIP";
3600                 break;
3601         case IW_ENCODE_ALG_CCMP:
3602                 alg_name = "CCMP";
3603                 break;
3604 #ifdef CONFIG_IEEE80211W
3605         case IW_ENCODE_ALG_AES_CMAC:
3606                 alg_name = "BIP";
3607                 break;
3608 #endif /* CONFIG_IEEE80211W */
3609 #ifdef CONFIG_WAPI_SUPPORT
3610 #ifndef CONFIG_IOCTL_CFG80211
3611         case IW_ENCODE_ALG_SM4:
3612                 alg_name = "SMS4";
3613                 _rtw_memcpy(param->sta_addr, pext->addr.sa_data, ETH_ALEN);
3614                 RTW_INFO("rtw_wx_set_enc_ext: SMS4 case\n");
3615                 break;
3616 #endif
3617 #endif
3618         default:
3619                 ret = -1;
3620                 goto exit;
3621         }
3622
3623         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
3624
3625         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3626                 param->u.crypt.set_tx = 1;
3627
3628         /* cliW: WEP does not have group key
3629          * just not checking GROUP key setting
3630          */
3631         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
3632             ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
3633 #ifdef CONFIG_IEEE80211W
3634              || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC)
3635 #endif /* CONFIG_IEEE80211W */
3636             ))
3637                 param->u.crypt.set_tx = 0;
3638
3639         param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1 ;
3640
3641         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
3642 #ifdef CONFIG_WAPI_SUPPORT
3643 #ifndef CONFIG_IOCTL_CFG80211
3644                 if (pext->alg == IW_ENCODE_ALG_SM4)
3645                         _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 16);
3646                 else
3647 #endif /* CONFIG_IOCTL_CFG80211 */
3648 #endif /* CONFIG_WAPI_SUPPORT */
3649                         _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 8);
3650         }
3651
3652         if (pext->key_len) {
3653                 param->u.crypt.key_len = pext->key_len;
3654                 /* _rtw_memcpy(param + 1, pext + 1, pext->key_len); */
3655                 _rtw_memcpy(param->u.crypt.key, pext + 1, pext->key_len);
3656         }
3657
3658         if (pencoding->flags & IW_ENCODE_DISABLED) {
3659                 /* todo: remove key */
3660                 /* remove = 1; */
3661         }
3662
3663         ret =  wpa_set_encryption(dev, param, param_len);
3664
3665 exit:
3666         if (param)
3667                 rtw_mfree((u8 *)param, param_len);
3668
3669         return ret;
3670 }
3671
3672
3673 static int rtw_wx_get_nick(struct net_device *dev,
3674                            struct iw_request_info *info,
3675                            union iwreq_data *wrqu, char *extra)
3676 {
3677         /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
3678         /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
3679         /* struct security_priv *psecuritypriv = &padapter->securitypriv; */
3680
3681         if (extra) {
3682                 wrqu->data.length = 14;
3683                 wrqu->data.flags = 1;
3684                 _rtw_memcpy(extra, "<WIFI@REALTEK>", 14);
3685         }
3686
3687         /* rtw_signal_process(pid, SIGUSR1); */ /* for test */
3688
3689         /* dump debug info here  */
3690 #if 0
3691         u32 dot11AuthAlgrthm;           /*  802.11 auth, could be open, shared, and 8021x */
3692         u32 dot11PrivacyAlgrthm;        /*  This specify the privacy for shared auth. algorithm. */
3693         u32 dot118021XGrpPrivacy;       /*  This specify the privacy algthm. used for Grp key */
3694         u32 ndisauthtype;
3695         u32 ndisencryptstatus;
3696 #endif
3697
3698         /* RTW_INFO("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",  */
3699         /*              psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, */
3700         /*              psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus); */
3701
3702         /* RTW_INFO("enc_alg=0x%x\n", psecuritypriv->dot11PrivacyAlgrthm); */
3703         /* RTW_INFO("auth_type=0x%x\n", psecuritypriv->ndisauthtype); */
3704         /* RTW_INFO("enc_type=0x%x\n", psecuritypriv->ndisencryptstatus); */
3705
3706 #if 0
3707         RTW_INFO("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
3708         RTW_INFO("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
3709         RTW_INFO("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
3710         RTW_INFO("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
3711         RTW_INFO("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
3712
3713         RTW_INFO("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
3714
3715
3716         RTW_INFO("\n");
3717
3718         RTW_INFO("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
3719         RTW_INFO("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
3720
3721         RTW_INFO("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
3722
3723         RTW_INFO("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
3724
3725         RTW_INFO("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
3726         RTW_INFO("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
3727
3728         RTW_INFO("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
3729         RTW_INFO("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
3730         RTW_INFO("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
3731         RTW_INFO("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
3732 #endif
3733
3734         return 0;
3735
3736 }
3737
3738 static int rtw_wx_read32(struct net_device *dev,
3739                          struct iw_request_info *info,
3740                          union iwreq_data *wrqu, char *extra)
3741 {
3742         PADAPTER padapter;
3743         struct iw_point *p;
3744         u16 len;
3745         u32 addr;
3746         u32 data32;
3747         u32 bytes;
3748         u8 *ptmp;
3749         int ret;
3750
3751
3752         ret = 0;
3753         padapter = (PADAPTER)rtw_netdev_priv(dev);
3754         p = &wrqu->data;
3755         len = p->length;
3756         if (0 == len)
3757                 return -EINVAL;
3758
3759         ptmp = (u8 *)rtw_malloc(len);
3760         if (NULL == ptmp)
3761                 return -ENOMEM;
3762
3763         if (copy_from_user(ptmp, p->pointer, len)) {
3764                 ret = -EFAULT;
3765                 goto exit;
3766         }
3767
3768         bytes = 0;
3769         addr = 0;
3770         sscanf(ptmp, "%d,%x", &bytes, &addr);
3771
3772         switch (bytes) {
3773         case 1:
3774                 data32 = rtw_read8(padapter, addr);
3775                 sprintf(extra, "0x%02X", data32);
3776                 break;
3777         case 2:
3778                 data32 = rtw_read16(padapter, addr);
3779                 sprintf(extra, "0x%04X", data32);
3780                 break;
3781         case 4:
3782                 data32 = rtw_read32(padapter, addr);
3783                 sprintf(extra, "0x%08X", data32);
3784                 break;
3785         default:
3786                 RTW_INFO("%s: usage> read [bytes],[address(hex)]\n", __func__);
3787                 ret = -EINVAL;
3788                 goto exit;
3789         }
3790         RTW_INFO("%s: addr=0x%08X data=%s\n", __func__, addr, extra);
3791
3792 exit:
3793         rtw_mfree(ptmp, len);
3794
3795         return 0;
3796 }
3797
3798 static int rtw_wx_write32(struct net_device *dev,
3799                           struct iw_request_info *info,
3800                           union iwreq_data *wrqu, char *extra)
3801 {
3802         PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
3803
3804         u32 addr;
3805         u32 data32;
3806         u32 bytes;
3807
3808
3809         bytes = 0;
3810         addr = 0;
3811         data32 = 0;
3812         sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
3813
3814         switch (bytes) {
3815         case 1:
3816                 rtw_write8(padapter, addr, (u8)data32);
3817                 RTW_INFO("%s: addr=0x%08X data=0x%02X\n", __func__, addr, (u8)data32);
3818                 break;
3819         case 2:
3820                 rtw_write16(padapter, addr, (u16)data32);
3821                 RTW_INFO("%s: addr=0x%08X data=0x%04X\n", __func__, addr, (u16)data32);
3822                 break;
3823         case 4:
3824                 rtw_write32(padapter, addr, data32);
3825                 RTW_INFO("%s: addr=0x%08X data=0x%08X\n", __func__, addr, data32);
3826                 break;
3827         default:
3828                 RTW_INFO("%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
3829                 return -EINVAL;
3830         }
3831
3832         return 0;
3833 }
3834
3835 static int rtw_wx_read_rf(struct net_device *dev,
3836                           struct iw_request_info *info,
3837                           union iwreq_data *wrqu, char *extra)
3838 {
3839         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3840         u32 path, addr, data32;
3841
3842
3843         path = *(u32 *)extra;
3844         addr = *((u32 *)extra + 1);
3845         data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
3846         /*      RTW_INFO("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32); */
3847         /*
3848          * IMPORTANT!!
3849          * Only when wireless private ioctl is at odd order,
3850          * "extra" would be copied to user space.
3851          */
3852         sprintf(extra, "0x%05x", data32);
3853
3854         return 0;
3855 }
3856
3857 static int rtw_wx_write_rf(struct net_device *dev,
3858                            struct iw_request_info *info,
3859                            union iwreq_data *wrqu, char *extra)
3860 {
3861         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3862         u32 path, addr, data32;
3863
3864
3865         path = *(u32 *)extra;
3866         addr = *((u32 *)extra + 1);
3867         data32 = *((u32 *)extra + 2);
3868         /*      RTW_INFO("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32); */
3869         rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
3870
3871         return 0;
3872 }
3873
3874 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
3875                             union iwreq_data *wrqu, char *b)
3876 {
3877         return -1;
3878 }
3879
3880 static int dummy(struct net_device *dev, struct iw_request_info *a,
3881                  union iwreq_data *wrqu, char *b)
3882 {
3883         /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);        */
3884         /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
3885
3886         /* RTW_INFO("cmd_code=%x, fwstate=0x%x\n", a->cmd, get_fwstate(pmlmepriv)); */
3887
3888         return -1;
3889
3890 }
3891
3892 static int rtw_wx_set_channel_plan(struct net_device *dev,
3893                                    struct iw_request_info *info,
3894                                    union iwreq_data *wrqu, char *extra)
3895 {
3896         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3897         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3898         u8 channel_plan_req = (u8)(*((int *)wrqu));
3899
3900         if (_SUCCESS != rtw_set_channel_plan(padapter, channel_plan_req))
3901                 return -EPERM;
3902
3903         return 0;
3904 }
3905
3906 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
3907                                        struct iw_request_info *a,
3908                                        union iwreq_data *wrqu, char *b)
3909 {
3910 #ifdef CONFIG_PLATFORM_MT53XX
3911         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3912         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3913
3914         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_,
3915                  ("WLAN IOCTL: cmd_code=%x, fwstate=0x%x\n",
3916                   a->cmd, get_fwstate(pmlmepriv)));
3917 #endif
3918         return 0;
3919 }
3920
3921 static int rtw_wx_get_sensitivity(struct net_device *dev,
3922                                   struct iw_request_info *info,
3923                                   union iwreq_data *wrqu, char *buf)
3924 {
3925 #ifdef CONFIG_PLATFORM_MT53XX
3926         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3927
3928         /*      Modified by Albert 20110914 */
3929         /*      This is in dbm format for MTK platform. */
3930         wrqu->qual.level = padapter->recvpriv.rssi;
3931         RTW_INFO(" level = %u\n",  wrqu->qual.level);
3932 #endif
3933         return 0;
3934 }
3935
3936 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
3937                                  struct iw_request_info *info,
3938                                  union iwreq_data *wrqu, char *extra)
3939 {
3940 #ifdef CONFIG_PLATFORM_MT53XX
3941         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3942
3943         return rtw_set_wpa_ie(padapter, wrqu->data.pointer, wrqu->data.length);
3944 #else
3945         return 0;
3946 #endif
3947 }
3948
3949 /*
3950 typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
3951                           union iwreq_data *wrqu, char *extra);
3952 */
3953 /*
3954  *      For all data larger than 16 octets, we need to use a
3955  *      pointer to memory allocated in user space.
3956  */
3957 static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
3958                            union iwreq_data *wrqu, char *extra)
3959 {
3960
3961 #if 0
3962         struct  iw_point {
3963                 void __user     *pointer;       /* Pointer to the data  (in user space) */
3964                 __u16           length;         /* number of fields or size in bytes */
3965                 __u16           flags;          /* Optional params */
3966         };
3967 #endif
3968
3969 #ifdef CONFIG_DRVEXT_MODULE
3970         u8 res;
3971         struct drvext_handler *phandler;
3972         struct drvext_oidparam *poidparam;
3973         int ret;
3974         u16 len;
3975         u8 *pparmbuf, bset;
3976         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3977         struct iw_point *p = &wrqu->data;
3978
3979         if ((!p->length) || (!p->pointer)) {
3980                 ret = -EINVAL;
3981                 goto _rtw_drvext_hdl_exit;
3982         }
3983
3984
3985         bset = (u8)(p->flags & 0xFFFF);
3986         len = p->length;
3987         pparmbuf = (u8 *)rtw_malloc(len);
3988         if (pparmbuf == NULL) {
3989                 ret = -ENOMEM;
3990                 goto _rtw_drvext_hdl_exit;
3991         }
3992
3993         if (bset) { /* set info */
3994                 if (copy_from_user(pparmbuf, p->pointer, len)) {
3995                         rtw_mfree(pparmbuf, len);
3996                         ret = -EFAULT;
3997                         goto _rtw_drvext_hdl_exit;
3998                 }
3999         } else { /* query info */
4000
4001         }
4002
4003
4004         /*  */
4005         poidparam = (struct drvext_oidparam *)pparmbuf;
4006
4007         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("drvext set oid subcode [%d], len[%d], InformationBufferLength[%d]\r\n",
4008                         poidparam->subcode, poidparam->len, len));
4009
4010
4011         /* check subcode         */
4012         if (poidparam->subcode >= MAX_DRVEXT_HANDLERS) {
4013                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext handlers\r\n"));
4014                 ret = -EINVAL;
4015                 goto _rtw_drvext_hdl_exit;
4016         }
4017
4018
4019         if (poidparam->subcode >= MAX_DRVEXT_OID_SUBCODES) {
4020                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
4021                 ret = -EINVAL;
4022                 goto _rtw_drvext_hdl_exit;
4023         }
4024
4025
4026         phandler = drvextoidhandlers + poidparam->subcode;
4027
4028         if (poidparam->len != phandler->parmsize) {
4029                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext param size %d vs %d\r\n",
4030                                 poidparam->len , phandler->parmsize));
4031                 ret = -EINVAL;
4032                 goto _rtw_drvext_hdl_exit;
4033         }
4034
4035
4036         res = phandler->handler(&padapter->drvextpriv, bset, poidparam->data);
4037
4038         if (res == 0) {
4039                 ret = 0;
4040
4041                 if (bset == 0x00) {/* query info */
4042                         /* _rtw_memcpy(p->pointer, pparmbuf, len); */
4043                         if (copy_to_user(p->pointer, pparmbuf, len))
4044                                 ret = -EFAULT;
4045                 }
4046         } else
4047                 ret = -EFAULT;
4048
4049
4050 _rtw_drvext_hdl_exit:
4051
4052         return ret;
4053
4054 #endif
4055
4056         return 0;
4057
4058 }
4059
4060 static void rtw_dbg_mode_hdl(_adapter *padapter, u32 id, u8 *pdata, u32 len)
4061 {
4062         pRW_Reg RegRWStruct;
4063         struct rf_reg_param *prfreg;
4064         u8 path;
4065         u8 offset;
4066         u32 value;
4067
4068         RTW_INFO("%s\n", __FUNCTION__);
4069
4070         switch (id) {
4071         case GEN_MP_IOCTL_SUBCODE(MP_START):
4072                 RTW_INFO("871x_driver is only for normal mode, can't enter mp mode\n");
4073                 break;
4074         case GEN_MP_IOCTL_SUBCODE(READ_REG):
4075                 RegRWStruct = (pRW_Reg)pdata;
4076                 switch (RegRWStruct->width) {
4077                 case 1:
4078                         RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
4079                         break;
4080                 case 2:
4081                         RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
4082                         break;
4083                 case 4:
4084                         RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
4085                         break;
4086                 default:
4087                         break;
4088                 }
4089
4090                 break;
4091         case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
4092                 RegRWStruct = (pRW_Reg)pdata;
4093                 switch (RegRWStruct->width) {
4094                 case 1:
4095                         rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
4096                         break;
4097                 case 2:
4098                         rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
4099                         break;
4100                 case 4:
4101                         rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
4102                         break;
4103                 default:
4104                         break;
4105                 }
4106
4107                 break;
4108         case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
4109
4110                 prfreg = (struct rf_reg_param *)pdata;
4111
4112                 path = (u8)prfreg->path;
4113                 offset = (u8)prfreg->offset;
4114
4115                 value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
4116
4117                 prfreg->value = value;
4118
4119                 break;
4120         case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
4121
4122                 prfreg = (struct rf_reg_param *)pdata;
4123
4124                 path = (u8)prfreg->path;
4125                 offset = (u8)prfreg->offset;
4126                 value = prfreg->value;
4127
4128                 rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
4129
4130                 break;
4131         case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
4132                 RTW_INFO("==> trigger gpio 0\n");
4133                 rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, 0);
4134                 break;
4135 #ifdef CONFIG_BT_COEXIST
4136         case GEN_MP_IOCTL_SUBCODE(SET_DM_BT):
4137                 RTW_INFO("==> set dm_bt_coexist:%x\n", *(u8 *)pdata);
4138                 rtw_hal_set_hwreg(padapter, HW_VAR_BT_SET_COEXIST, pdata);
4139                 break;
4140         case GEN_MP_IOCTL_SUBCODE(DEL_BA):
4141                 RTW_INFO("==> delete ba:%x\n", *(u8 *)pdata);
4142                 rtw_hal_set_hwreg(padapter, HW_VAR_BT_ISSUE_DELBA, pdata);
4143                 break;
4144 #endif
4145 #ifdef DBG_CONFIG_ERROR_DETECT
4146         case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
4147                 *pdata = rtw_hal_sreset_get_wifi_status(padapter);
4148                 break;
4149 #endif
4150
4151         default:
4152                 break;
4153         }
4154
4155 }
4156
4157 static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
4158                             union iwreq_data *wrqu, char *extra)
4159 {
4160         int ret = 0;
4161         u32 BytesRead, BytesWritten, BytesNeeded;
4162         struct oid_par_priv     oid_par;
4163         struct mp_ioctl_handler *phandler;
4164         struct mp_ioctl_param   *poidparam;
4165         uint status = 0;
4166         u16 len;
4167         u8 *pparmbuf = NULL, bset;
4168         PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
4169         struct iw_point *p = &wrqu->data;
4170
4171         /* RTW_INFO("+rtw_mp_ioctl_hdl\n"); */
4172
4173         /* mutex_lock(&ioctl_mutex); */
4174
4175         if ((!p->length) || (!p->pointer)) {
4176                 ret = -EINVAL;
4177                 goto _rtw_mp_ioctl_hdl_exit;
4178         }
4179
4180         pparmbuf = NULL;
4181         bset = (u8)(p->flags & 0xFFFF);
4182         len = p->length;
4183         pparmbuf = (u8 *)rtw_malloc(len);
4184         if (pparmbuf == NULL) {
4185                 ret = -ENOMEM;
4186                 goto _rtw_mp_ioctl_hdl_exit;
4187         }
4188
4189         if (copy_from_user(pparmbuf, p->pointer, len)) {
4190                 ret = -EFAULT;
4191                 goto _rtw_mp_ioctl_hdl_exit;
4192         }
4193
4194         poidparam = (struct mp_ioctl_param *)pparmbuf;
4195         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
4196                  ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
4197                   poidparam->subcode, poidparam->len, len));
4198
4199         if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
4200                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
4201                 ret = -EINVAL;
4202                 goto _rtw_mp_ioctl_hdl_exit;
4203         }
4204
4205         /* RTW_INFO("%s: %d\n", __func__, poidparam->subcode); */
4206 #ifdef CONFIG_MP_INCLUDED
4207         if (padapter->registrypriv.mp_mode == 1) {
4208                 phandler = mp_ioctl_hdl + poidparam->subcode;
4209
4210                 if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
4211                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
4212                                  ("no matching drvext param size %d vs %d\r\n",
4213                                   poidparam->len, phandler->paramsize));
4214                         ret = -EINVAL;
4215                         goto _rtw_mp_ioctl_hdl_exit;
4216                 }
4217
4218                 if (phandler->handler) {
4219                         oid_par.adapter_context = padapter;
4220                         oid_par.oid = phandler->oid;
4221                         oid_par.information_buf = poidparam->data;
4222                         oid_par.information_buf_len = poidparam->len;
4223                         oid_par.dbg = 0;
4224
4225                         BytesWritten = 0;
4226                         BytesNeeded = 0;
4227
4228                         if (bset) {
4229                                 oid_par.bytes_rw = &BytesRead;
4230                                 oid_par.bytes_needed = &BytesNeeded;
4231                                 oid_par.type_of_oid = SET_OID;
4232                         } else {
4233                                 oid_par.bytes_rw = &BytesWritten;
4234                                 oid_par.bytes_needed = &BytesNeeded;
4235                                 oid_par.type_of_oid = QUERY_OID;
4236                         }
4237
4238                         status = phandler->handler(&oid_par);
4239
4240                         /* todo:check status, BytesNeeded, etc. */
4241                 } else {
4242                         RTW_INFO("rtw_mp_ioctl_hdl(): err!, subcode=%d, oid=%d, handler=%p\n",
4243                                 poidparam->subcode, phandler->oid, phandler->handler);
4244                         ret = -EFAULT;
4245                         goto _rtw_mp_ioctl_hdl_exit;
4246                 }
4247         } else
4248 #endif
4249         {
4250                 rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
4251         }
4252
4253         if (bset == 0x00) {/* query info */
4254                 if (copy_to_user(p->pointer, pparmbuf, len))
4255                         ret = -EFAULT;
4256         }
4257
4258         if (status) {
4259                 ret = -EFAULT;
4260                 goto _rtw_mp_ioctl_hdl_exit;
4261         }
4262
4263 _rtw_mp_ioctl_hdl_exit:
4264
4265         if (pparmbuf)
4266                 rtw_mfree(pparmbuf, len);
4267
4268         /* mutex_unlock(&ioctl_mutex); */
4269
4270         return ret;
4271 }
4272
4273 static int rtw_get_ap_info(struct net_device *dev,
4274                            struct iw_request_info *info,
4275                            union iwreq_data *wrqu, char *extra)
4276 {
4277         int bssid_match, ret = 0;
4278         u32 cnt = 0, wpa_ielen;
4279         _irqL   irqL;
4280         _list   *plist, *phead;
4281         unsigned char *pbuf;
4282         u8 bssid[ETH_ALEN];
4283         char data[32];
4284         struct wlan_network *pnetwork = NULL;
4285         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4286         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4287         _queue *queue = &(pmlmepriv->scanned_queue);
4288         struct iw_point *pdata = &wrqu->data;
4289
4290         RTW_INFO("+rtw_get_aplist_info\n");
4291
4292         if (rtw_is_drv_stopped(padapter) || (pdata == NULL)) {
4293                 ret = -EINVAL;
4294                 goto exit;
4295         }
4296
4297         while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING))) == _TRUE) {
4298                 rtw_msleep_os(30);
4299                 cnt++;
4300                 if (cnt > 100)
4301                         break;
4302         }
4303
4304
4305         /* pdata->length = 0; */ /* ?    */
4306         pdata->flags = 0;
4307         if (pdata->length >= 32) {
4308                 if (copy_from_user(data, pdata->pointer, 32)) {
4309                         ret = -EINVAL;
4310                         goto exit;
4311                 }
4312         } else {
4313                 ret = -EINVAL;
4314                 goto exit;
4315         }
4316
4317         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4318
4319         phead = get_list_head(queue);
4320         plist = get_next(phead);
4321
4322         while (1) {
4323                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4324                         break;
4325
4326
4327                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4328
4329                 /* if(hwaddr_aton_i(pdata->pointer, bssid)) */
4330                 if (hwaddr_aton_i(data, bssid)) {
4331                         RTW_INFO("Invalid BSSID '%s'.\n", (u8 *)data);
4332                         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4333                         return -EINVAL;
4334                 }
4335
4336
4337                 if (_rtw_memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) == _TRUE) { /* BSSID match, then check if supporting wpa/wpa2 */
4338                         RTW_INFO("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
4339
4340                         pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
4341                         if (pbuf && (wpa_ielen > 0)) {
4342                                 pdata->flags = 1;
4343                                 break;
4344                         }
4345
4346                         pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
4347                         if (pbuf && (wpa_ielen > 0)) {
4348                                 pdata->flags = 2;
4349                                 break;
4350                         }
4351
4352                 }
4353
4354                 plist = get_next(plist);
4355
4356         }
4357
4358         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4359
4360         if (pdata->length >= 34) {
4361                 if (copy_to_user((u8 *)pdata->pointer + 32, (u8 *)&pdata->flags, 1)) {
4362                         ret = -EINVAL;
4363                         goto exit;
4364                 }
4365         }
4366
4367 exit:
4368
4369         return ret;
4370
4371 }
4372
4373 static int rtw_set_pid(struct net_device *dev,
4374                        struct iw_request_info *info,
4375                        union iwreq_data *wrqu, char *extra)
4376 {
4377
4378         int ret = 0;
4379         _adapter *padapter = rtw_netdev_priv(dev);
4380         int *pdata = (int *)wrqu;
4381         int selector;
4382
4383         if (rtw_is_drv_stopped(padapter) || (pdata == NULL)) {
4384                 ret = -EINVAL;
4385                 goto exit;
4386         }
4387
4388         selector = *pdata;
4389         if (selector < 3 && selector >= 0) {
4390                 padapter->pid[selector] = *(pdata + 1);
4391 #ifdef CONFIG_GLOBAL_UI_PID
4392                 ui_pid[selector] = *(pdata + 1);
4393 #endif
4394                 RTW_INFO("%s set pid[%d]=%d\n", __FUNCTION__, selector , padapter->pid[selector]);
4395         } else
4396                 RTW_INFO("%s selector %d error\n", __FUNCTION__, selector);
4397
4398 exit:
4399
4400         return ret;
4401
4402 }
4403
4404 static int rtw_wps_start(struct net_device *dev,
4405                          struct iw_request_info *info,
4406                          union iwreq_data *wrqu, char *extra)
4407 {
4408
4409         int ret = 0;
4410         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4411         struct iw_point *pdata = &wrqu->data;
4412         u32   u32wps_start = 0;
4413         unsigned int uintRet = 0;
4414
4415         if (RTW_CANNOT_RUN(padapter) || (NULL == pdata)) {
4416                 ret = -EINVAL;
4417                 goto exit;
4418         }
4419
4420         uintRet = copy_from_user((void *) &u32wps_start, pdata->pointer, 4);
4421         if (u32wps_start == 0)
4422                 u32wps_start = *extra;
4423
4424         RTW_INFO("[%s] wps_start = %d\n", __FUNCTION__, u32wps_start);
4425
4426         if (u32wps_start == 1)   /* WPS Start */
4427                 rtw_led_control(padapter, LED_CTL_START_WPS);
4428         else if (u32wps_start == 2)   /* WPS Stop because of wps success */
4429                 rtw_led_control(padapter, LED_CTL_STOP_WPS);
4430         else if (u32wps_start == 3)   /* WPS Stop because of wps fail */
4431                 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
4432
4433 #ifdef CONFIG_INTEL_WIDI
4434         process_intel_widi_wps_status(padapter, u32wps_start);
4435 #endif /* CONFIG_INTEL_WIDI */
4436
4437 exit:
4438
4439         return ret;
4440
4441 }
4442
4443 #ifdef CONFIG_P2P
4444 static int rtw_wext_p2p_enable(struct net_device *dev,
4445                                struct iw_request_info *info,
4446                                union iwreq_data *wrqu, char *extra)
4447 {
4448
4449         int ret = 0;
4450         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4451         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4452         struct iw_point *pdata = &wrqu->data;
4453         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4454         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4455         enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
4456
4457         if (*extra == '0')
4458                 init_role = P2P_ROLE_DISABLE;
4459         else if (*extra == '1')
4460                 init_role = P2P_ROLE_DEVICE;
4461         else if (*extra == '2')
4462                 init_role = P2P_ROLE_CLIENT;
4463         else if (*extra == '3')
4464                 init_role = P2P_ROLE_GO;
4465
4466         if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
4467                 ret = -EFAULT;
4468                 goto exit;
4469         }
4470
4471         /* set channel/bandwidth */
4472         if (init_role != P2P_ROLE_DISABLE) {
4473                 u8 channel, ch_offset;
4474                 u16 bwmode;
4475
4476                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
4477                         /*      Stay at the listen state and wait for discovery. */
4478                         channel = pwdinfo->listen_channel;
4479                         pwdinfo->operating_channel = pwdinfo->listen_channel;
4480                         ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4481                         bwmode = CHANNEL_WIDTH_20;
4482                 }
4483 #ifdef CONFIG_CONCURRENT_MODE
4484                 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
4485
4486                         _set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval);
4487
4488                         channel = rtw_mi_get_union_chan(padapter);
4489                         ch_offset = rtw_mi_get_union_offset(padapter);
4490                         bwmode = rtw_mi_get_union_bw(padapter);
4491
4492                         pwdinfo->operating_channel = channel;
4493                 }
4494 #endif
4495                 else {
4496                         pwdinfo->operating_channel = pmlmeext->cur_channel;
4497
4498                         channel = pwdinfo->operating_channel;
4499                         ch_offset = pmlmeext->cur_ch_offset;
4500                         bwmode = pmlmeext->cur_bwmode;
4501                 }
4502
4503                 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
4504         }
4505
4506 exit:
4507         return ret;
4508
4509 }
4510
4511 static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
4512                                     struct iw_request_info *info,
4513                                     union iwreq_data *wrqu, char *extra)
4514 {
4515
4516         int ret = 0;
4517         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4518         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4519         struct iw_point *pdata = &wrqu->data;
4520         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4521
4522         RTW_INFO("[%s] ssid = %s, len = %zu\n", __FUNCTION__, extra, strlen(extra));
4523         _rtw_memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
4524         pwdinfo->nego_ssidlen = strlen(extra);
4525
4526         return ret;
4527
4528 }
4529
4530
4531 static int rtw_p2p_set_intent(struct net_device *dev,
4532                               struct iw_request_info *info,
4533                               union iwreq_data *wrqu, char *extra)
4534 {
4535         int                                                     ret = 0;
4536         _adapter                                                *padapter = (_adapter *)rtw_netdev_priv(dev);
4537         struct wifidirect_info                  *pwdinfo = &(padapter->wdinfo);
4538         u8                                                      intent = pwdinfo->intent;
4539
4540         extra[wrqu->data.length] = 0x00;
4541
4542         intent = rtw_atoi(extra);
4543
4544         if (intent <= 15)
4545                 pwdinfo->intent = intent;
4546         else
4547                 ret = -1;
4548
4549         RTW_INFO("[%s] intent = %d\n", __FUNCTION__, intent);
4550
4551         return ret;
4552
4553 }
4554
4555 static int rtw_p2p_set_listen_ch(struct net_device *dev,
4556                                  struct iw_request_info *info,
4557                                  union iwreq_data *wrqu, char *extra)
4558 {
4559
4560         int ret = 0;
4561         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4562         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4563         u8      listen_ch = pwdinfo->listen_channel;    /*      Listen channel number */
4564
4565         extra[wrqu->data.length] = 0x00;
4566         listen_ch = rtw_atoi(extra);
4567
4568         if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
4569                 pwdinfo->listen_channel = listen_ch;
4570                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4571         } else
4572                 ret = -1;
4573
4574         RTW_INFO("[%s] listen_ch = %d\n", __FUNCTION__, pwdinfo->listen_channel);
4575
4576         return ret;
4577
4578 }
4579
4580 static int rtw_p2p_set_op_ch(struct net_device *dev,
4581                              struct iw_request_info *info,
4582                              union iwreq_data *wrqu, char *extra)
4583 {
4584         /*      Commented by Albert 20110524
4585          *      This function is used to set the operating channel if the driver will become the group owner */
4586
4587         int ret = 0;
4588         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4589         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4590         u8      op_ch = pwdinfo->operating_channel;     /*      Operating channel number */
4591
4592         extra[wrqu->data.length] = 0x00;
4593
4594         op_ch = (u8) rtw_atoi(extra);
4595         if (op_ch > 0)
4596                 pwdinfo->operating_channel = op_ch;
4597         else
4598                 ret = -1;
4599
4600         RTW_INFO("[%s] op_ch = %d\n", __FUNCTION__, pwdinfo->operating_channel);
4601
4602         return ret;
4603
4604 }
4605
4606
4607 static int rtw_p2p_profilefound(struct net_device *dev,
4608                                 struct iw_request_info *info,
4609                                 union iwreq_data *wrqu, char *extra)
4610 {
4611
4612         int ret = 0;
4613         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4614         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4615
4616         /*      Comment by Albert 2010/10/13 */
4617         /*      Input data format: */
4618         /*      Ex:  0 */
4619         /*      Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
4620         /*      0 => Reflush the profile record list. */
4621         /*      1 => Add the profile list */
4622         /*      XX:XX:XX:XX:XX:XX => peer's MAC Address ( ex: 00:E0:4C:00:00:01 ) */
4623         /*      YY => SSID Length */
4624         /*      SSID => SSID for persistence group */
4625
4626         RTW_INFO("[%s] In value = %s, len = %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
4627
4628
4629         /*      The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
4630         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
4631                 if (extra[0] == '0') {
4632                         /*      Remove all the profile information of wifidirect_info structure. */
4633                         _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
4634                         pwdinfo->profileindex = 0;
4635                 } else {
4636                         if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM)
4637                                 ret = -1;
4638                         else {
4639                                 int jj, kk;
4640
4641                                 /*      Add this profile information into pwdinfo->profileinfo */
4642                                 /*      Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
4643                                 for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
4644                                         pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
4645
4646                                 /* pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = ( extra[18] - '0' ) * 10 + ( extra[19] - '0' ); */
4647                                 /* _rtw_memcpy( pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen ); */
4648                                 pwdinfo->profileindex++;
4649                         }
4650                 }
4651         }
4652
4653         return ret;
4654
4655 }
4656
4657 static int rtw_p2p_setDN(struct net_device *dev,
4658                          struct iw_request_info *info,
4659                          union iwreq_data *wrqu, char *extra)
4660 {
4661
4662         int ret = 0;
4663         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4664         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4665
4666
4667         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
4668         _rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
4669         _rtw_memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
4670         pwdinfo->device_name_len = wrqu->data.length - 1;
4671
4672         return ret;
4673
4674 }
4675
4676
4677 static int rtw_p2p_get_status(struct net_device *dev,
4678                               struct iw_request_info *info,
4679                               union iwreq_data *wrqu, char *extra)
4680 {
4681
4682         int ret = 0;
4683         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4684         struct iw_point *pdata = &wrqu->data;
4685         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4686
4687         if (padapter->bShowGetP2PState) {
4688                 RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4689                         pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4690                         pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4691         }
4692
4693         /*      Commented by Albert 2010/10/12 */
4694         /*      Because of the output size limitation, I had removed the "Role" information. */
4695         /*      About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
4696         sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
4697         wrqu->data.length = strlen(extra);
4698
4699         return ret;
4700
4701 }
4702
4703 /*      Commented by Albert 20110520
4704  *      This function will return the config method description
4705  *      This config method description will show us which config method the remote P2P device is intented to use
4706  *      by sending the provisioning discovery request frame. */
4707
4708 static int rtw_p2p_get_req_cm(struct net_device *dev,
4709                               struct iw_request_info *info,
4710                               union iwreq_data *wrqu, char *extra)
4711 {
4712
4713         int ret = 0;
4714         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4715         struct iw_point *pdata = &wrqu->data;
4716         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4717
4718         sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
4719         wrqu->data.length = strlen(extra);
4720         return ret;
4721
4722 }
4723
4724
4725 static int rtw_p2p_get_role(struct net_device *dev,
4726                             struct iw_request_info *info,
4727                             union iwreq_data *wrqu, char *extra)
4728 {
4729
4730         int ret = 0;
4731         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4732         struct iw_point *pdata = &wrqu->data;
4733         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4734
4735
4736         RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4737                 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4738                 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4739
4740         sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
4741         wrqu->data.length = strlen(extra);
4742         return ret;
4743
4744 }
4745
4746
4747 static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
4748                                    struct iw_request_info *info,
4749                                    union iwreq_data *wrqu, char *extra)
4750 {
4751
4752         int ret = 0;
4753         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4754         struct iw_point *pdata = &wrqu->data;
4755         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4756
4757
4758         RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4759                 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4760                 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4761
4762         sprintf(extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
4763                 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4764                 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4765         wrqu->data.length = strlen(extra);
4766         return ret;
4767
4768 }
4769
4770 static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
4771                                     struct iw_request_info *info,
4772                                     union iwreq_data *wrqu, char *extra)
4773
4774 {
4775
4776         int ret = 0;
4777         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4778         struct iw_point *pdata = &wrqu->data;
4779         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4780
4781         RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4782                 pwdinfo->rx_prov_disc_info.peerDevAddr[0], pwdinfo->rx_prov_disc_info.peerDevAddr[1],
4783                 pwdinfo->rx_prov_disc_info.peerDevAddr[2], pwdinfo->rx_prov_disc_info.peerDevAddr[3],
4784                 pwdinfo->rx_prov_disc_info.peerDevAddr[4], pwdinfo->rx_prov_disc_info.peerDevAddr[5]);
4785         sprintf(extra, "\n%.2X%.2X%.2X%.2X%.2X%.2X",
4786                 pwdinfo->rx_prov_disc_info.peerDevAddr[0], pwdinfo->rx_prov_disc_info.peerDevAddr[1],
4787                 pwdinfo->rx_prov_disc_info.peerDevAddr[2], pwdinfo->rx_prov_disc_info.peerDevAddr[3],
4788                 pwdinfo->rx_prov_disc_info.peerDevAddr[4], pwdinfo->rx_prov_disc_info.peerDevAddr[5]);
4789         wrqu->data.length = strlen(extra);
4790         return ret;
4791
4792 }
4793
4794 static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
4795                 struct iw_request_info *info,
4796                 union iwreq_data *wrqu, char *extra)
4797
4798 {
4799
4800         int ret = 0;
4801         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4802         struct iw_point *pdata = &wrqu->data;
4803         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4804
4805         RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4806                 pwdinfo->p2p_peer_device_addr[0], pwdinfo->p2p_peer_device_addr[1],
4807                 pwdinfo->p2p_peer_device_addr[2], pwdinfo->p2p_peer_device_addr[3],
4808                 pwdinfo->p2p_peer_device_addr[4], pwdinfo->p2p_peer_device_addr[5]);
4809         sprintf(extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
4810                 pwdinfo->p2p_peer_device_addr[0], pwdinfo->p2p_peer_device_addr[1],
4811                 pwdinfo->p2p_peer_device_addr[2], pwdinfo->p2p_peer_device_addr[3],
4812                 pwdinfo->p2p_peer_device_addr[4], pwdinfo->p2p_peer_device_addr[5]);
4813         wrqu->data.length = strlen(extra);
4814         return ret;
4815
4816 }
4817
4818 static int rtw_p2p_get_groupid(struct net_device *dev,
4819                                struct iw_request_info *info,
4820                                union iwreq_data *wrqu, char *extra)
4821
4822 {
4823
4824         int ret = 0;
4825         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4826         struct iw_point *pdata = &wrqu->data;
4827         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4828
4829         sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
4830                 pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
4831                 pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
4832                 pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
4833                 pwdinfo->groupid_info.ssid);
4834         wrqu->data.length = strlen(extra);
4835         return ret;
4836
4837 }
4838
4839 static int rtw_p2p_get_op_ch(struct net_device *dev,
4840                              struct iw_request_info *info,
4841                              union iwreq_data *wrqu, char *extra)
4842
4843 {
4844
4845         int ret = 0;
4846         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4847         struct iw_point *pdata = &wrqu->data;
4848         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4849
4850
4851         RTW_INFO("[%s] Op_ch = %02x\n", __FUNCTION__, pwdinfo->operating_channel);
4852
4853         sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
4854         wrqu->data.length = strlen(extra);
4855         return ret;
4856
4857 }
4858
4859 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
4860                                         struct iw_request_info *info,
4861                         union iwreq_data *wrqu, char *extra, char *subcmd)
4862 {
4863
4864         int ret = 0;
4865         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4866         u8 peerMAC[ETH_ALEN] = { 0x00 };
4867         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4868         _irqL irqL;
4869         _list *plist, *phead;
4870         _queue *queue = &(pmlmepriv->scanned_queue);
4871         struct wlan_network *pnetwork = NULL;
4872         u8 blnMatch = 0;
4873         u16     attr_content = 0;
4874         uint attr_contentlen = 0;
4875         u8      attr_content_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4876
4877         /*      Commented by Albert 20110727 */
4878         /*      The input data is the MAC address which the application wants to know its WPS config method. */
4879         /*      After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
4880         /*      Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
4881
4882         RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
4883
4884         macstr2num(peerMAC, subcmd);
4885
4886         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4887
4888         phead = get_list_head(queue);
4889         plist = get_next(phead);
4890
4891         while (1) {
4892                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4893                         break;
4894
4895                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4896                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4897                         u8 *wpsie;
4898                         uint    wpsie_len = 0;
4899
4900                         /*      The mac address is matched. */
4901
4902                         wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
4903                         if (wpsie) {
4904                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&attr_content, &attr_contentlen);
4905                                 if (attr_contentlen) {
4906                                         attr_content = be16_to_cpu(attr_content);
4907                                         sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
4908                                         blnMatch = 1;
4909                                 }
4910                         }
4911
4912                         break;
4913                 }
4914
4915                 plist = get_next(plist);
4916
4917         }
4918
4919         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4920
4921         if (!blnMatch)
4922                 sprintf(attr_content_str, "\n\nM=0000");
4923
4924         wrqu->data.length = strlen(attr_content_str);
4925         _rtw_memcpy(extra, attr_content_str, wrqu->data.length);
4926
4927         return ret;
4928
4929 }
4930
4931 #ifdef CONFIG_WFD
4932 static int rtw_p2p_get_peer_wfd_port(struct net_device *dev,
4933                                      struct iw_request_info *info,
4934                                      union iwreq_data *wrqu, char *extra)
4935 {
4936
4937         int ret = 0;
4938         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4939         struct iw_point *pdata = &wrqu->data;
4940         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4941
4942         RTW_INFO("[%s] p2p_state = %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo));
4943
4944         sprintf(extra, "\n\nPort=%d\n", pwdinfo->wfd_info->peer_rtsp_ctrlport);
4945         RTW_INFO("[%s] remote port = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
4946
4947         wrqu->data.length = strlen(extra);
4948         return ret;
4949
4950 }
4951
4952 static int rtw_p2p_get_peer_wfd_preferred_connection(struct net_device *dev,
4953                 struct iw_request_info *info,
4954                 union iwreq_data *wrqu, char *extra)
4955 {
4956
4957         int ret = 0;
4958         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4959         struct iw_point *pdata = &wrqu->data;
4960         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4961
4962         sprintf(extra, "\n\nwfd_pc=%d\n", pwdinfo->wfd_info->wfd_pc);
4963         RTW_INFO("[%s] wfd_pc = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_pc);
4964
4965         wrqu->data.length = strlen(extra);
4966         pwdinfo->wfd_info->wfd_pc = _FALSE;     /*      Reset the WFD preferred connection to P2P */
4967         return ret;
4968
4969 }
4970
4971 static int rtw_p2p_get_peer_wfd_session_available(struct net_device *dev,
4972                 struct iw_request_info *info,
4973                 union iwreq_data *wrqu, char *extra)
4974 {
4975
4976         int ret = 0;
4977         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4978         struct iw_point *pdata = &wrqu->data;
4979         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4980
4981         sprintf(extra, "\n\nwfd_sa=%d\n", pwdinfo->wfd_info->peer_session_avail);
4982         RTW_INFO("[%s] wfd_sa = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_session_avail);
4983
4984         wrqu->data.length = strlen(extra);
4985         pwdinfo->wfd_info->peer_session_avail = _TRUE;  /*      Reset the WFD session available */
4986         return ret;
4987
4988 }
4989 #endif /* CONFIG_WFD */
4990
4991 static int rtw_p2p_get_go_device_address(struct net_device *dev,
4992                 struct iw_request_info *info,
4993                 union iwreq_data *wrqu, char *extra, char *subcmd)
4994 {
4995
4996         int ret = 0;
4997         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4998         u8 peerMAC[ETH_ALEN] = { 0x00 };
4999         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5000         _irqL irqL;
5001         _list *plist, *phead;
5002         _queue *queue   = &(pmlmepriv->scanned_queue);
5003         struct wlan_network *pnetwork = NULL;
5004         u8 blnMatch = 0;
5005         u8 *p2pie;
5006         uint p2pielen = 0, attr_contentlen = 0;
5007         u8 attr_content[100] = { 0x00 };
5008         u8 go_devadd_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5009
5010         /*      Commented by Albert 20121209 */
5011         /*      The input data is the GO's interface address which the application wants to know its device address. */
5012         /*      Format: iwpriv wlanx p2p_get2 go_devadd=00:E0:4C:00:00:05 */
5013
5014         RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
5015
5016         macstr2num(peerMAC, subcmd);
5017
5018         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5019
5020         phead = get_list_head(queue);
5021         plist = get_next(phead);
5022
5023         while (1) {
5024                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5025                         break;
5026
5027                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5028                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
5029                         /*      Commented by Albert 2011/05/18 */
5030                         /*      Match the device address located in the P2P IE */
5031                         /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
5032
5033                         p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
5034                         if (p2pie) {
5035                                 while (p2pie) {
5036                                         /*      The P2P Device ID attribute is included in the Beacon frame. */
5037                                         /*      The P2P Device Info attribute is included in the probe response frame. */
5038
5039                                         _rtw_memset(attr_content, 0x00, 100);
5040                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
5041                                                 /*      Handle the P2P Device ID attribute of Beacon first */
5042                                                 blnMatch = 1;
5043                                                 break;
5044
5045                                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
5046                                                 /*      Handle the P2P Device Info attribute of probe response */
5047                                                 blnMatch = 1;
5048                                                 break;
5049                                         }
5050
5051                                         /* Get the next P2P IE */
5052                                         p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
5053                                 }
5054                         }
5055                 }
5056
5057                 plist = get_next(plist);
5058
5059         }
5060
5061         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5062
5063         if (!blnMatch)
5064                 sprintf(go_devadd_str, "\n\ndev_add=NULL");
5065         else {
5066                 sprintf(go_devadd_str, "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
5067                         attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
5068         }
5069
5070         wrqu->data.length = strlen(go_devadd_str);
5071         _rtw_memcpy(extra, go_devadd_str, wrqu->data.length);
5072
5073         return ret;
5074
5075 }
5076
5077 static int rtw_p2p_get_device_type(struct net_device *dev,
5078                                    struct iw_request_info *info,
5079                            union iwreq_data *wrqu, char *extra, char *subcmd)
5080 {
5081
5082         int ret = 0;
5083         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5084         u8 peerMAC[ETH_ALEN] = { 0x00 };
5085         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5086         _irqL irqL;
5087         _list *plist, *phead;
5088         _queue *queue = &(pmlmepriv->scanned_queue);
5089         struct wlan_network *pnetwork = NULL;
5090         u8 blnMatch = 0;
5091         u8 dev_type[8] = { 0x00 };
5092         uint dev_type_len = 0;
5093         u8 dev_type_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };    /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
5094
5095         /*      Commented by Albert 20121209 */
5096         /*      The input data is the MAC address which the application wants to know its device type. */
5097         /*      Such user interface could know the device type. */
5098         /*      Format: iwpriv wlanx p2p_get2 dev_type=00:E0:4C:00:00:05 */
5099
5100         RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
5101
5102         macstr2num(peerMAC, subcmd);
5103
5104         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5105
5106         phead = get_list_head(queue);
5107         plist = get_next(phead);
5108
5109         while (1) {
5110                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5111                         break;
5112
5113                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5114                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
5115                         u8 *wpsie;
5116                         uint    wpsie_len = 0;
5117
5118                         /*      The mac address is matched. */
5119
5120                         wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
5121                         if (wpsie) {
5122                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
5123                                 if (dev_type_len) {
5124                                         u16     type = 0;
5125
5126                                         _rtw_memcpy(&type, dev_type, 2);
5127                                         type = be16_to_cpu(type);
5128                                         sprintf(dev_type_str, "\n\nN=%.2d", type);
5129                                         blnMatch = 1;
5130                                 }
5131                         }
5132                         break;
5133                 }
5134
5135                 plist = get_next(plist);
5136
5137         }
5138
5139         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5140
5141         if (!blnMatch)
5142                 sprintf(dev_type_str, "\n\nN=00");
5143
5144         wrqu->data.length = strlen(dev_type_str);
5145         _rtw_memcpy(extra, dev_type_str, wrqu->data.length);
5146
5147         return ret;
5148
5149 }
5150
5151 static int rtw_p2p_get_device_name(struct net_device *dev,
5152                                    struct iw_request_info *info,
5153                            union iwreq_data *wrqu, char *extra, char *subcmd)
5154 {
5155
5156         int ret = 0;
5157         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5158         u8 peerMAC[ETH_ALEN] = { 0x00 };
5159         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5160         _irqL irqL;
5161         _list *plist, *phead;
5162         _queue *queue = &(pmlmepriv->scanned_queue);
5163         struct wlan_network *pnetwork = NULL;
5164         u8 blnMatch = 0;
5165         u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = { 0x00 };
5166         uint dev_len = 0;
5167         u8 dev_name_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5168
5169         /*      Commented by Albert 20121225 */
5170         /*      The input data is the MAC address which the application wants to know its device name. */
5171         /*      Such user interface could show peer device's device name instead of ssid. */
5172         /*      Format: iwpriv wlanx p2p_get2 devN=00:E0:4C:00:00:05 */
5173
5174         RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
5175
5176         macstr2num(peerMAC, subcmd);
5177
5178         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5179
5180         phead = get_list_head(queue);
5181         plist = get_next(phead);
5182
5183         while (1) {
5184                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5185                         break;
5186
5187                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5188                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
5189                         u8 *wpsie;
5190                         uint    wpsie_len = 0;
5191
5192                         /*      The mac address is matched. */
5193
5194                         wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
5195                         if (wpsie) {
5196                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
5197                                 if (dev_len) {
5198                                         sprintf(dev_name_str, "\n\nN=%s", dev_name);
5199                                         blnMatch = 1;
5200                                 }
5201                         }
5202                         break;
5203                 }
5204
5205                 plist = get_next(plist);
5206
5207         }
5208
5209         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5210
5211         if (!blnMatch)
5212                 sprintf(dev_name_str, "\n\nN=0000");
5213
5214         wrqu->data.length = strlen(dev_name_str);
5215         _rtw_memcpy(extra, dev_name_str, wrqu->data.length);
5216
5217         return ret;
5218
5219 }
5220
5221 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
5222                 struct iw_request_info *info,
5223                 union iwreq_data *wrqu, char *extra, char *subcmd)
5224 {
5225
5226         int ret = 0;
5227         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5228         u8 peerMAC[ETH_ALEN] = { 0x00 };
5229         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5230         _irqL irqL;
5231         _list *plist, *phead;
5232         _queue *queue   = &(pmlmepriv->scanned_queue);
5233         struct wlan_network *pnetwork = NULL;
5234         u8 blnMatch = 0;
5235         u8 *p2pie;
5236         uint p2pielen = 0, attr_contentlen = 0;
5237         u8 attr_content[2] = { 0x00 };
5238         u8 inv_proc_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5239
5240         /*      Commented by Ouden 20121226 */
5241         /*      The application wants to know P2P initation procedure is support or not. */
5242         /*      Format: iwpriv wlanx p2p_get2 InvProc=00:E0:4C:00:00:05 */
5243
5244         RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
5245
5246         macstr2num(peerMAC, subcmd);
5247
5248         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5249
5250         phead = get_list_head(queue);
5251         plist = get_next(phead);
5252
5253         while (1) {
5254                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5255                         break;
5256
5257                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5258                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
5259                         /*      Commented by Albert 20121226 */
5260                         /*      Match the device address located in the P2P IE */
5261                         /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
5262
5263                         p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
5264                         if (p2pie) {
5265                                 while (p2pie) {
5266                                         /* _rtw_memset( attr_content, 0x00, 2); */
5267                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
5268                                                 /*      Handle the P2P capability attribute */
5269                                                 blnMatch = 1;
5270                                                 break;
5271
5272                                         }
5273
5274                                         /* Get the next P2P IE */
5275                                         p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
5276                                 }
5277                         }
5278                 }
5279
5280                 plist = get_next(plist);
5281
5282         }
5283
5284         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5285
5286         if (!blnMatch)
5287                 sprintf(inv_proc_str, "\nIP=-1");
5288         else {
5289                 if ((attr_content[0] & 0x20) == 0x20)
5290                         sprintf(inv_proc_str, "\nIP=1");
5291                 else
5292                         sprintf(inv_proc_str, "\nIP=0");
5293         }
5294
5295         wrqu->data.length = strlen(inv_proc_str);
5296         _rtw_memcpy(extra, inv_proc_str, wrqu->data.length);
5297
5298         return ret;
5299
5300 }
5301
5302 static int rtw_p2p_connect(struct net_device *dev,
5303                            struct iw_request_info *info,
5304                            union iwreq_data *wrqu, char *extra)
5305 {
5306
5307         int ret = 0;
5308         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);
5309         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5310         u8                                      peerMAC[ETH_ALEN] = { 0x00 };
5311         int                                     jj, kk;
5312         u8                                      peerMACStr[ETH_ALEN * 2] = { 0x00 };
5313         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
5314         _irqL                           irqL;
5315         _list                                   *plist, *phead;
5316         _queue                          *queue  = &(pmlmepriv->scanned_queue);
5317         struct  wlan_network    *pnetwork = NULL;
5318         uint                                    uintPeerChannel = 0;
5319
5320         /*      Commented by Albert 20110304 */
5321         /*      The input data contains two informations. */
5322         /*      1. First information is the MAC address which wants to formate with */
5323         /*      2. Second information is the WPS PINCode or "pbc" string for push button method */
5324         /*      Format: 00:E0:4C:00:00:05 */
5325         /*      Format: 00:E0:4C:00:00:05 */
5326
5327         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5328
5329         if (pwdinfo->p2p_state == P2P_STATE_NONE) {
5330                 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5331                 return ret;
5332         }
5333
5334 #ifdef CONFIG_INTEL_WIDI
5335         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
5336                 RTW_INFO("[%s] WiFi is under survey!\n", __FUNCTION__);
5337                 return ret;
5338         }
5339 #endif /* CONFIG_INTEL_WIDI      */
5340
5341         if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
5342                 return -1;
5343
5344         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
5345                 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
5346
5347         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5348
5349         phead = get_list_head(queue);
5350         plist = get_next(phead);
5351
5352         while (1) {
5353                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5354                         break;
5355
5356                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5357                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
5358                         if (pnetwork->network.Configuration.DSConfig != 0)
5359                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5360                         else if (pwdinfo->nego_req_info.peer_ch != 0)
5361                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig = pwdinfo->nego_req_info.peer_ch;
5362                         else {
5363                                 /* Unexpected case */
5364                                 uintPeerChannel = 0;
5365                                 RTW_INFO("%s  uintPeerChannel = 0\n", __func__);
5366                         }
5367                         break;
5368                 }
5369
5370                 plist = get_next(plist);
5371
5372         }
5373
5374         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5375
5376         if (uintPeerChannel) {
5377 #ifdef CONFIG_CONCURRENT_MODE
5378                 if (rtw_mi_check_status(padapter, MI_LINKED))
5379                         _cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
5380 #endif /* CONFIG_CONCURRENT_MODE */
5381
5382                 _rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
5383                 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
5384
5385                 pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
5386                 _rtw_memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
5387                 pwdinfo->nego_req_info.benable = _TRUE;
5388
5389                 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
5390                 if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
5391                         /*      Restore to the listen state if the current p2p state is not nego OK */
5392                         rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
5393                 }
5394
5395                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5396                 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
5397
5398 #ifdef CONFIG_CONCURRENT_MODE
5399                 if (rtw_mi_check_status(padapter, MI_LINKED)) {
5400                         u8 union_ch = rtw_mi_get_union_chan(padapter);
5401                         u8 union_bw = rtw_mi_get_union_bw(padapter);
5402                         u8 union_offset = rtw_mi_get_union_offset(padapter);
5403                         /*      Have to enter the power saving with the AP */
5404                         set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
5405
5406                         rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
5407                 }
5408 #endif /* CONFIG_CONCURRENT_MODE */
5409
5410                 RTW_INFO("[%s] Start PreTx Procedure!\n", __FUNCTION__);
5411                 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
5412 #ifdef CONFIG_CONCURRENT_MODE
5413                 if (rtw_mi_check_status(padapter, MI_LINKED))
5414                         _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_GO_NEGO_TIMEOUT);
5415                 else
5416                         _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
5417 #else
5418                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
5419 #endif /* CONFIG_CONCURRENT_MODE                 */
5420
5421         } else {
5422                 RTW_INFO("[%s] Not Found in Scanning Queue~\n", __FUNCTION__);
5423 #ifdef CONFIG_INTEL_WIDI
5424                 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
5425                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
5426                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
5427                 rtw_free_network_queue(padapter, _TRUE);
5428                 /**
5429                  * For WiDi, if we can't find candidate device in scanning queue,
5430                  * driver will do scanning itself
5431                  */
5432                 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5433                 rtw_sitesurvey_cmd(padapter, NULL, 0, NULL, 0);
5434                 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5435 #endif /* CONFIG_INTEL_WIDI */
5436                 ret = -1;
5437         }
5438 exit:
5439         return ret;
5440 }
5441
5442 static int rtw_p2p_invite_req(struct net_device *dev,
5443                               struct iw_request_info *info,
5444                               union iwreq_data *wrqu, char *extra)
5445 {
5446
5447         int ret = 0;
5448         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);
5449         struct iw_point                 *pdata = &wrqu->data;
5450         struct wifidirect_info          *pwdinfo = &(padapter->wdinfo);
5451         int                                             jj, kk;
5452         u8                                              peerMACStr[ETH_ALEN * 2] = { 0x00 };
5453         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
5454         _list                                           *plist, *phead;
5455         _queue                                  *queue  = &(pmlmepriv->scanned_queue);
5456         struct  wlan_network            *pnetwork = NULL;
5457         uint                                            uintPeerChannel = 0;
5458         u8                                              attr_content[50] = { 0x00 }, _status = 0;
5459         u8                                              *p2pie;
5460         uint                                            p2pielen = 0, attr_contentlen = 0;
5461         _irqL                                   irqL;
5462         struct tx_invite_req_info       *pinvite_req_info = &pwdinfo->invitereq_info;
5463
5464         /*      Commented by Albert 20120321 */
5465         /*      The input data contains two informations. */
5466         /*      1. First information is the P2P device address which you want to send to.        */
5467         /*      2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
5468         /*      Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
5469         /*      Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
5470
5471         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5472
5473         if (wrqu->data.length <=  37) {
5474                 RTW_INFO("[%s] Wrong format!\n", __FUNCTION__);
5475                 return ret;
5476         }
5477
5478         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5479                 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5480                 return ret;
5481         } else {
5482                 /*      Reset the content of struct tx_invite_req_info */
5483                 pinvite_req_info->benable = _FALSE;
5484                 _rtw_memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
5485                 _rtw_memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
5486                 pinvite_req_info->ssidlen = 0x00;
5487                 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
5488                 _rtw_memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
5489                 pinvite_req_info->token = 3;
5490         }
5491
5492         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
5493                 pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
5494
5495         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5496
5497         phead = get_list_head(queue);
5498         plist = get_next(phead);
5499
5500         while (1) {
5501                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5502                         break;
5503
5504                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5505
5506                 /*      Commented by Albert 2011/05/18 */
5507                 /*      Match the device address located in the P2P IE */
5508                 /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
5509
5510                 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
5511                 if (p2pie) {
5512                         /*      The P2P Device ID attribute is included in the Beacon frame. */
5513                         /*      The P2P Device Info attribute is included in the probe response frame. */
5514
5515                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
5516                                 /*      Handle the P2P Device ID attribute of Beacon first */
5517                                 if (_rtw_memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
5518                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5519                                         break;
5520                                 }
5521                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
5522                                 /*      Handle the P2P Device Info attribute of probe response */
5523                                 if (_rtw_memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
5524                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5525                                         break;
5526                                 }
5527                         }
5528
5529                 }
5530
5531                 plist = get_next(plist);
5532
5533         }
5534
5535         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5536
5537 #ifdef CONFIG_WFD
5538         if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST) && uintPeerChannel) {
5539                 struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
5540                 u8 *wfd_ie;
5541                 uint wfd_ielen = 0;
5542
5543                 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
5544                 if (wfd_ie) {
5545                         u8 *wfd_devinfo;
5546                         uint wfd_devlen;
5547
5548                         RTW_INFO("[%s] Found WFD IE!\n", __FUNCTION__);
5549                         wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
5550                         if (wfd_devinfo) {
5551                                 u16     wfd_devinfo_field = 0;
5552
5553                                 /*      Commented by Albert 20120319 */
5554                                 /*      The first two bytes are the WFD device information field of WFD device information subelement. */
5555                                 /*      In big endian format. */
5556                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
5557                                 if (wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL)
5558                                         pwfd_info->peer_session_avail = _TRUE;
5559                                 else
5560                                         pwfd_info->peer_session_avail = _FALSE;
5561                         }
5562                 }
5563
5564                 if (_FALSE == pwfd_info->peer_session_avail) {
5565                         RTW_INFO("[%s] WFD Session not avaiable!\n", __FUNCTION__);
5566                         goto exit;
5567                 }
5568         }
5569 #endif /* CONFIG_WFD */
5570
5571         if (uintPeerChannel) {
5572 #ifdef CONFIG_CONCURRENT_MODE
5573                 if (rtw_mi_check_status(padapter, MI_LINKED))
5574                         _cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
5575 #endif /* CONFIG_CONCURRENT_MODE */
5576
5577                 /*      Store the GO's bssid */
5578                 for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
5579                         pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
5580
5581                 /*      Store the GO's ssid */
5582                 pinvite_req_info->ssidlen = wrqu->data.length - 36;
5583                 _rtw_memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
5584                 pinvite_req_info->benable = _TRUE;
5585                 pinvite_req_info->peer_ch = uintPeerChannel;
5586
5587                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5588                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
5589
5590 #ifdef CONFIG_CONCURRENT_MODE
5591                 if (rtw_mi_check_status(padapter, MI_LINKED)) {
5592                         u8 union_ch = rtw_mi_get_union_chan(padapter);
5593                         u8 union_bw = rtw_mi_get_union_bw(padapter);
5594                         u8 union_offset = rtw_mi_get_union_offset(padapter);
5595                         /*      Have to enter the power saving with the AP */
5596                         set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
5597
5598                         rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
5599                 } else
5600                         set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
5601 #else
5602                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
5603 #endif
5604
5605                 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
5606
5607 #ifdef CONFIG_CONCURRENT_MODE
5608                 if (rtw_mi_check_status(padapter, MI_LINKED))
5609                         _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_INVITE_TIMEOUT);
5610                 else
5611                         _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
5612 #else
5613                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
5614 #endif /* CONFIG_CONCURRENT_MODE                 */
5615
5616
5617         } else
5618                 RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__);
5619 exit:
5620
5621         return ret;
5622
5623 }
5624
5625 static int rtw_p2p_set_persistent(struct net_device *dev,
5626                                   struct iw_request_info *info,
5627                                   union iwreq_data *wrqu, char *extra)
5628 {
5629
5630         int ret = 0;
5631         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);
5632         struct iw_point                 *pdata = &wrqu->data;
5633         struct wifidirect_info          *pwdinfo = &(padapter->wdinfo);
5634         int                                             jj, kk;
5635         u8                                              peerMACStr[ETH_ALEN * 2] = { 0x00 };
5636         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
5637         _list                                           *plist, *phead;
5638         _queue                                  *queue  = &(pmlmepriv->scanned_queue);
5639         struct  wlan_network            *pnetwork = NULL;
5640         uint                                            uintPeerChannel = 0;
5641         u8                                              attr_content[50] = { 0x00 }, _status = 0;
5642         u8                                              *p2pie;
5643         uint                                            p2pielen = 0, attr_contentlen = 0;
5644         _irqL                                   irqL;
5645         struct tx_invite_req_info       *pinvite_req_info = &pwdinfo->invitereq_info;
5646
5647         /*      Commented by Albert 20120328 */
5648         /*      The input data is 0 or 1 */
5649         /*      0: disable persistent group functionality */
5650         /*      1: enable persistent group founctionality */
5651
5652         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5653
5654         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5655                 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5656                 return ret;
5657         } else {
5658                 if (extra[0] == '0')    /*      Disable the persistent group function. */
5659                         pwdinfo->persistent_supported = _FALSE;
5660                 else if (extra[0] == '1')       /*      Enable the persistent group function. */
5661                         pwdinfo->persistent_supported = _TRUE;
5662                 else
5663                         pwdinfo->persistent_supported = _FALSE;
5664         }
5665         printk("[%s] persistent_supported = %d\n", __FUNCTION__, pwdinfo->persistent_supported);
5666
5667 exit:
5668
5669         return ret;
5670
5671 }
5672
5673 static int hexstr2bin(const char *hex, u8 *buf, size_t len)
5674 {
5675         size_t i;
5676         int a;
5677         const char *ipos = hex;
5678         u8 *opos = buf;
5679
5680         for (i = 0; i < len; i++) {
5681                 a = hex2byte_i(ipos);
5682                 if (a < 0)
5683                         return -1;
5684                 *opos++ = a;
5685                 ipos += 2;
5686         }
5687         return 0;
5688 }
5689
5690 static int uuid_str2bin(const char *str, u8 *bin)
5691 {
5692         const char *pos;
5693         u8 *opos;
5694
5695         pos = str;
5696         opos = bin;
5697
5698         if (hexstr2bin(pos, opos, 4))
5699                 return -1;
5700         pos += 8;
5701         opos += 4;
5702
5703         if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
5704                 return -1;
5705         pos += 4;
5706         opos += 2;
5707
5708         if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
5709                 return -1;
5710         pos += 4;
5711         opos += 2;
5712
5713         if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
5714                 return -1;
5715         pos += 4;
5716         opos += 2;
5717
5718         if (*pos++ != '-' || hexstr2bin(pos, opos, 6))
5719                 return -1;
5720
5721         return 0;
5722 }
5723
5724 static int rtw_p2p_set_wps_uuid(struct net_device *dev,
5725                                 struct iw_request_info *info,
5726                                 union iwreq_data *wrqu, char *extra)
5727 {
5728
5729         int ret = 0;
5730         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);
5731         struct wifidirect_info                  *pwdinfo = &(padapter->wdinfo);
5732
5733         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5734
5735         if ((36 == strlen(extra)) && (uuid_str2bin(extra, pwdinfo->uuid) == 0))
5736                 pwdinfo->external_uuid = 1;
5737         else {
5738                 pwdinfo->external_uuid = 0;
5739                 ret = -EINVAL;
5740         }
5741
5742         return ret;
5743
5744 }
5745 #ifdef CONFIG_WFD
5746 static int rtw_p2p_set_pc(struct net_device *dev,
5747                           struct iw_request_info *info,
5748                           union iwreq_data *wrqu, char *extra)
5749 {
5750
5751         int ret = 0;
5752         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);
5753         struct iw_point         *pdata = &wrqu->data;
5754         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5755         u8                                      peerMAC[ETH_ALEN] = { 0x00 };
5756         int                                     jj, kk;
5757         u8                                      peerMACStr[ETH_ALEN * 2] = { 0x00 };
5758         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
5759         _list                                   *plist, *phead;
5760         _queue                          *queue  = &(pmlmepriv->scanned_queue);
5761         struct  wlan_network    *pnetwork = NULL;
5762         u8                                      attr_content[50] = { 0x00 }, _status = 0;
5763         u8 *p2pie;
5764         uint                                    p2pielen = 0, attr_contentlen = 0;
5765         _irqL                           irqL;
5766         uint                                    uintPeerChannel = 0;
5767
5768         struct wifi_display_info        *pwfd_info = pwdinfo->wfd_info;
5769
5770         /*      Commented by Albert 20120512 */
5771         /*      1. Input information is the MAC address which wants to know the Preferred Connection bit (PC bit) */
5772         /*      Format: 00:E0:4C:00:00:05 */
5773
5774         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5775
5776         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5777                 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5778                 return ret;
5779         }
5780
5781         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
5782                 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
5783
5784         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5785
5786         phead = get_list_head(queue);
5787         plist = get_next(phead);
5788
5789         while (1) {
5790                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5791                         break;
5792
5793                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5794
5795                 /*      Commented by Albert 2011/05/18 */
5796                 /*      Match the device address located in the P2P IE */
5797                 /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
5798
5799                 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
5800                 if (p2pie) {
5801                         /*      The P2P Device ID attribute is included in the Beacon frame. */
5802                         /*      The P2P Device Info attribute is included in the probe response frame. */
5803                         printk("[%s] Got P2P IE\n", __FUNCTION__);
5804                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
5805                                 /*      Handle the P2P Device ID attribute of Beacon first */
5806                                 printk("[%s] P2P_ATTR_DEVICE_ID\n", __FUNCTION__);
5807                                 if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
5808                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5809                                         break;
5810                                 }
5811                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
5812                                 /*      Handle the P2P Device Info attribute of probe response */
5813                                 printk("[%s] P2P_ATTR_DEVICE_INFO\n", __FUNCTION__);
5814                                 if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
5815                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5816                                         break;
5817                                 }
5818                         }
5819
5820                 }
5821
5822                 plist = get_next(plist);
5823
5824         }
5825
5826         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5827         printk("[%s] channel = %d\n", __FUNCTION__, uintPeerChannel);
5828
5829         if (uintPeerChannel) {
5830                 u8 *wfd_ie;
5831                 uint wfd_ielen = 0;
5832
5833                 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
5834                 if (wfd_ie) {
5835                         u8 *wfd_devinfo;
5836                         uint wfd_devlen;
5837
5838                         RTW_INFO("[%s] Found WFD IE!\n", __FUNCTION__);
5839                         wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
5840                         if (wfd_devinfo) {
5841                                 u16     wfd_devinfo_field = 0;
5842
5843                                 /*      Commented by Albert 20120319 */
5844                                 /*      The first two bytes are the WFD device information field of WFD device information subelement. */
5845                                 /*      In big endian format. */
5846                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
5847                                 if (wfd_devinfo_field & WFD_DEVINFO_PC_TDLS)
5848                                         pwfd_info->wfd_pc = _TRUE;
5849                                 else
5850                                         pwfd_info->wfd_pc = _FALSE;
5851                         }
5852                 }
5853         } else
5854                 RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__);
5855
5856 exit:
5857
5858         return ret;
5859
5860 }
5861
5862 static int rtw_p2p_set_wfd_device_type(struct net_device *dev,
5863                                        struct iw_request_info *info,
5864                                        union iwreq_data *wrqu, char *extra)
5865 {
5866
5867         int ret = 0;
5868         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);
5869         struct iw_point                 *pdata = &wrqu->data;
5870         struct wifidirect_info          *pwdinfo = &(padapter->wdinfo);
5871         struct wifi_display_info                *pwfd_info = pwdinfo->wfd_info;
5872
5873         /*      Commented by Albert 20120328 */
5874         /*      The input data is 0 or 1 */
5875         /*      0: specify to Miracast source device */
5876         /*      1 or others: specify to Miracast sink device (display device) */
5877
5878         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5879
5880         if (extra[0] == '0')    /*      Set to Miracast source device. */
5881                 pwfd_info->wfd_device_type = WFD_DEVINFO_SOURCE;
5882         else                                    /*      Set to Miracast sink device. */
5883                 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
5884
5885 exit:
5886
5887         return ret;
5888
5889 }
5890
5891 static int rtw_p2p_set_wfd_enable(struct net_device *dev,
5892                                   struct iw_request_info *info,
5893                                   union iwreq_data *wrqu, char *extra)
5894 {
5895         /*      Commented by Kurt 20121206
5896          *      This function is used to set wfd enabled */
5897
5898         int ret = 0;
5899         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5900         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5901
5902         if (*extra == '0')
5903                 rtw_wfd_enable(padapter, 0);
5904         else if (*extra == '1')
5905                 rtw_wfd_enable(padapter, 1);
5906
5907         RTW_INFO("[%s] wfd_enable = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_enable);
5908
5909         return ret;
5910
5911 }
5912
5913 static int rtw_p2p_set_driver_iface(struct net_device *dev,
5914                                     struct iw_request_info *info,
5915                                     union iwreq_data *wrqu, char *extra)
5916 {
5917         /*      Commented by Kurt 20121206
5918          *      This function is used to set driver iface is WEXT or CFG80211 */
5919         int ret = 0;
5920         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5921         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5922
5923         if (*extra == '1') {
5924                 pwdinfo->driver_interface = DRIVER_WEXT;
5925                 RTW_INFO("[%s] driver_interface = WEXT\n", __FUNCTION__);
5926         } else if (*extra == '2') {
5927                 pwdinfo->driver_interface = DRIVER_CFG80211;
5928                 RTW_INFO("[%s] driver_interface = CFG80211\n", __FUNCTION__);
5929         }
5930
5931         return ret;
5932
5933 }
5934
5935 /*      To set the WFD session available to enable or disable */
5936 static int rtw_p2p_set_sa(struct net_device *dev,
5937                           struct iw_request_info *info,
5938                           union iwreq_data *wrqu, char *extra)
5939 {
5940
5941         int ret = 0;
5942         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);
5943         struct iw_point                 *pdata = &wrqu->data;
5944         struct wifidirect_info          *pwdinfo = &(padapter->wdinfo);
5945         struct wifi_display_info                *pwfd_info = pwdinfo->wfd_info;
5946
5947         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5948
5949         if (0) {
5950                 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5951                 return ret;
5952         } else {
5953                 if (extra[0] == '0')    /*      Disable the session available. */
5954                         pwdinfo->session_available = _FALSE;
5955                 else if (extra[0] == '1')       /*      Enable the session available. */
5956                         pwdinfo->session_available = _TRUE;
5957                 else
5958                         pwdinfo->session_available = _FALSE;
5959         }
5960         printk("[%s] session available = %d\n", __FUNCTION__, pwdinfo->session_available);
5961
5962 exit:
5963
5964         return ret;
5965
5966 }
5967 #endif /* CONFIG_WFD */
5968
5969 static int rtw_p2p_prov_disc(struct net_device *dev,
5970                              struct iw_request_info *info,
5971                              union iwreq_data *wrqu, char *extra)
5972 {
5973         int ret = 0;
5974         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);
5975         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5976         u8                                      peerMAC[ETH_ALEN] = { 0x00 };
5977         int                                     jj, kk;
5978         u8                                      peerMACStr[ETH_ALEN * 2] = { 0x00 };
5979         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
5980         _list                                   *plist, *phead;
5981         _queue                          *queue  = &(pmlmepriv->scanned_queue);
5982         struct  wlan_network    *pnetwork = NULL;
5983         uint                                    uintPeerChannel = 0;
5984         u8                                      attr_content[100] = { 0x00 }, _status = 0;
5985         u8 *p2pie;
5986         uint                                    p2pielen = 0, attr_contentlen = 0;
5987         _irqL                           irqL;
5988
5989         /*      Commented by Albert 20110301 */
5990         /*      The input data contains two informations. */
5991         /*      1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
5992         /*      2. Second information is the WPS configuration method which wants to discovery */
5993         /*      Format: 00:E0:4C:00:00:05_display */
5994         /*      Format: 00:E0:4C:00:00:05_keypad */
5995         /*      Format: 00:E0:4C:00:00:05_pbc */
5996         /*      Format: 00:E0:4C:00:00:05_label */
5997
5998         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5999
6000         if (pwdinfo->p2p_state == P2P_STATE_NONE) {
6001                 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
6002                 return ret;
6003         } else {
6004 #ifdef CONFIG_INTEL_WIDI
6005                 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
6006                         RTW_INFO("[%s] WiFi is under survey!\n", __FUNCTION__);
6007                         return ret;
6008                 }
6009 #endif /* CONFIG_INTEL_WIDI */
6010
6011                 /*      Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
6012                 _rtw_memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
6013                 _rtw_memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
6014                 _rtw_memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(NDIS_802_11_SSID));
6015                 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
6016                 pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
6017                 pwdinfo->tx_prov_disc_info.benable = _FALSE;
6018         }
6019
6020         for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
6021                 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
6022
6023         if (_rtw_memcmp(&extra[18], "display", 7))
6024                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
6025         else if (_rtw_memcmp(&extra[18], "keypad", 7))
6026                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
6027         else if (_rtw_memcmp(&extra[18], "pbc", 3))
6028                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
6029         else if (_rtw_memcmp(&extra[18], "label", 5))
6030                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
6031         else {
6032                 RTW_INFO("[%s] Unknown WPS config methodn", __FUNCTION__);
6033                 return ret ;
6034         }
6035
6036         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6037
6038         phead = get_list_head(queue);
6039         plist = get_next(phead);
6040
6041         while (1) {
6042                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
6043                         break;
6044
6045                 if (uintPeerChannel != 0)
6046                         break;
6047
6048                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
6049
6050                 /*      Commented by Albert 2011/05/18 */
6051                 /*      Match the device address located in the P2P IE */
6052                 /*      This is for the case that the P2P device address is not the same as the P2P interface address. */
6053
6054                 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
6055                 if (p2pie) {
6056                         while (p2pie) {
6057                                 /*      The P2P Device ID attribute is included in the Beacon frame. */
6058                                 /*      The P2P Device Info attribute is included in the probe response frame. */
6059
6060                                 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
6061                                         /*      Handle the P2P Device ID attribute of Beacon first */
6062                                         if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
6063                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6064                                                 break;
6065                                         }
6066                                 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
6067                                         /*      Handle the P2P Device Info attribute of probe response */
6068                                         if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
6069                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6070                                                 break;
6071                                         }
6072                                 }
6073
6074                                 /* Get the next P2P IE */
6075                                 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
6076                         }
6077
6078                 }
6079
6080 #ifdef CONFIG_INTEL_WIDI
6081                 /* Some Intel WiDi source may not provide P2P IE, */
6082                 /* so we could only compare mac addr by 802.11 Source Address */
6083                 if (pmlmepriv->widi_state == INTEL_WIDI_STATE_WFD_CONNECTION
6084                     && uintPeerChannel == 0) {
6085                         if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
6086                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6087                                 break;
6088                         }
6089                 }
6090 #endif /* CONFIG_INTEL_WIDI */
6091
6092                 plist = get_next(plist);
6093
6094         }
6095
6096         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6097
6098         if (uintPeerChannel) {
6099 #ifdef CONFIG_WFD
6100                 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
6101                         struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
6102                         u8 *wfd_ie;
6103                         uint wfd_ielen = 0;
6104
6105                         wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
6106                         if (wfd_ie) {
6107                                 u8 *wfd_devinfo;
6108                                 uint wfd_devlen;
6109
6110                                 RTW_INFO("[%s] Found WFD IE!\n", __FUNCTION__);
6111                                 wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
6112                                 if (wfd_devinfo) {
6113                                         u16     wfd_devinfo_field = 0;
6114
6115                                         /*      Commented by Albert 20120319 */
6116                                         /*      The first two bytes are the WFD device information field of WFD device information subelement. */
6117                                         /*      In big endian format. */
6118                                         wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
6119                                         if (wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL)
6120                                                 pwfd_info->peer_session_avail = _TRUE;
6121                                         else
6122                                                 pwfd_info->peer_session_avail = _FALSE;
6123                                 }
6124                         }
6125
6126                         if (_FALSE == pwfd_info->peer_session_avail) {
6127                                 RTW_INFO("[%s] WFD Session not avaiable!\n", __FUNCTION__);
6128                                 goto exit;
6129                         }
6130                 }
6131 #endif /* CONFIG_WFD */
6132
6133                 RTW_INFO("[%s] peer channel: %d!\n", __FUNCTION__, uintPeerChannel);
6134 #ifdef CONFIG_CONCURRENT_MODE
6135                 if (rtw_mi_check_status(padapter, MI_LINKED))
6136                         _cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
6137 #endif /* CONFIG_CONCURRENT_MODE */
6138                 _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
6139                 _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
6140                 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
6141                 pwdinfo->tx_prov_disc_info.benable = _TRUE;
6142                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
6143                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
6144
6145                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
6146                         _rtw_memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(NDIS_802_11_SSID));
6147                 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
6148                         _rtw_memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
6149                         pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
6150                 }
6151
6152 #ifdef CONFIG_CONCURRENT_MODE
6153                 if (rtw_mi_check_status(padapter, MI_LINKED)) {
6154                         u8 union_ch = rtw_mi_get_union_chan(padapter);
6155                         u8 union_bw = rtw_mi_get_union_bw(padapter);
6156                         u8 union_offset = rtw_mi_get_union_offset(padapter);
6157
6158                         /*      Have to enter the power saving with the AP */
6159                         set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
6160
6161                         rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
6162                 } else
6163                         set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
6164 #else
6165                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
6166 #endif
6167
6168                 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
6169
6170 #ifdef CONFIG_CONCURRENT_MODE
6171                 if (rtw_mi_check_status(padapter, MI_LINKED))
6172                         _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_PROVISION_TIMEOUT);
6173                 else
6174                         _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
6175 #else
6176                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
6177 #endif /* CONFIG_CONCURRENT_MODE                 */
6178
6179         } else {
6180                 RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__);
6181 #ifdef CONFIG_INTEL_WIDI
6182                 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
6183                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
6184                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
6185                 rtw_free_network_queue(padapter, _TRUE);
6186                 _enter_critical_bh(&pmlmepriv->lock, &irqL);
6187                 rtw_sitesurvey_cmd(padapter, NULL, 0, NULL, 0);
6188                 _exit_critical_bh(&pmlmepriv->lock, &irqL);
6189 #endif /* CONFIG_INTEL_WIDI */
6190         }
6191 exit:
6192
6193         return ret;
6194
6195 }
6196
6197 /*      Added by Albert 20110328
6198  *      This function is used to inform the driver the user had specified the pin code value or pbc
6199  *      to application. */
6200
6201 static int rtw_p2p_got_wpsinfo(struct net_device *dev,
6202                                struct iw_request_info *info,
6203                                union iwreq_data *wrqu, char *extra)
6204 {
6205
6206         int ret = 0;
6207         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);
6208         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
6209
6210
6211         RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
6212         /*      Added by Albert 20110328 */
6213         /*      if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
6214         /*      if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
6215         /*      if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
6216         /*      if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
6217
6218         if (*extra == '0')
6219                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
6220         else if (*extra == '1')
6221                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
6222         else if (*extra == '2')
6223                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
6224         else if (*extra == '3')
6225                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
6226         else
6227                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
6228
6229         return ret;
6230
6231 }
6232
6233 #endif /* CONFIG_P2P */
6234
6235 static int rtw_p2p_set(struct net_device *dev,
6236                        struct iw_request_info *info,
6237                        union iwreq_data *wrqu, char *extra)
6238 {
6239
6240         int ret = 0;
6241 #ifdef CONFIG_P2P
6242
6243         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6244         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6245         struct iw_point *pdata = &wrqu->data;
6246         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
6247         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6248
6249         RTW_INFO("[%s] extra = %s\n", __FUNCTION__, extra);
6250
6251         if (_rtw_memcmp(extra, "enable=", 7))
6252                 rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
6253         else if (_rtw_memcmp(extra, "setDN=", 6)) {
6254                 wrqu->data.length -= 6;
6255                 rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
6256         } else if (_rtw_memcmp(extra, "profilefound=", 13)) {
6257                 wrqu->data.length -= 13;
6258                 rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
6259         } else if (_rtw_memcmp(extra, "prov_disc=", 10)) {
6260                 wrqu->data.length -= 10;
6261                 rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
6262         } else if (_rtw_memcmp(extra, "nego=", 5)) {
6263                 wrqu->data.length -= 5;
6264                 rtw_p2p_connect(dev, info, wrqu, &extra[5]);
6265         } else if (_rtw_memcmp(extra, "intent=", 7)) {
6266                 /*      Commented by Albert 2011/03/23 */
6267                 /*      The wrqu->data.length will include the null character */
6268                 /*      So, we will decrease 7 + 1 */
6269                 wrqu->data.length -= 8;
6270                 rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
6271         } else if (_rtw_memcmp(extra, "ssid=", 5)) {
6272                 wrqu->data.length -= 5;
6273                 rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
6274         } else if (_rtw_memcmp(extra, "got_wpsinfo=", 12)) {
6275                 wrqu->data.length -= 12;
6276                 rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
6277         } else if (_rtw_memcmp(extra, "listen_ch=", 10)) {
6278                 /*      Commented by Albert 2011/05/24 */
6279                 /*      The wrqu->data.length will include the null character */
6280                 /*      So, we will decrease (10 + 1)    */
6281                 wrqu->data.length -= 11;
6282                 rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
6283         } else if (_rtw_memcmp(extra, "op_ch=", 6)) {
6284                 /*      Commented by Albert 2011/05/24 */
6285                 /*      The wrqu->data.length will include the null character */
6286                 /*      So, we will decrease (6 + 1)     */
6287                 wrqu->data.length -= 7;
6288                 rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
6289         } else if (_rtw_memcmp(extra, "invite=", 7)) {
6290                 wrqu->data.length -= 8;
6291                 rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
6292         } else if (_rtw_memcmp(extra, "persistent=", 11)) {
6293                 wrqu->data.length -= 11;
6294                 rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
6295         } else if (_rtw_memcmp(extra, "uuid=", 5)) {
6296                 wrqu->data.length -= 5;
6297                 ret = rtw_p2p_set_wps_uuid(dev, info, wrqu, &extra[5]);
6298         }
6299
6300 #ifdef CONFIG_WFD
6301         if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
6302                 if (_rtw_memcmp(extra, "sa=", 3)) {
6303                         /* sa: WFD Session Available information */
6304                         wrqu->data.length -= 3;
6305                         rtw_p2p_set_sa(dev, info, wrqu, &extra[3]);
6306                 } else if (_rtw_memcmp(extra, "pc=", 3)) {
6307                         /* pc: WFD Preferred Connection */
6308                         wrqu->data.length -= 3;
6309                         rtw_p2p_set_pc(dev, info, wrqu, &extra[3]);
6310                 } else if (_rtw_memcmp(extra, "wfd_type=", 9)) {
6311                         wrqu->data.length -= 9;
6312                         rtw_p2p_set_wfd_device_type(dev, info, wrqu, &extra[9]);
6313                 } else if (_rtw_memcmp(extra, "wfd_enable=", 11)) {
6314                         wrqu->data.length -= 11;
6315                         rtw_p2p_set_wfd_enable(dev, info, wrqu, &extra[11]);
6316                 } else if (_rtw_memcmp(extra, "driver_iface=", 13)) {
6317                         wrqu->data.length -= 13;
6318                         rtw_p2p_set_driver_iface(dev, info, wrqu, &extra[13]);
6319                 }
6320         }
6321 #endif /* CONFIG_WFD */
6322
6323 #endif /* CONFIG_P2P */
6324
6325         return ret;
6326
6327 }
6328
6329 static int rtw_p2p_get(struct net_device *dev,
6330                        struct iw_request_info *info,
6331                        union iwreq_data *wrqu, char *extra)
6332 {
6333
6334         int ret = 0;
6335
6336 #ifdef CONFIG_P2P
6337
6338         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6339         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6340         struct iw_point *pdata = &wrqu->data;
6341         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
6342         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6343
6344         if (padapter->bShowGetP2PState)
6345                 RTW_INFO("[%s] extra = %s\n", __FUNCTION__, (char *) wrqu->data.pointer);
6346
6347         if (_rtw_memcmp(wrqu->data.pointer, "status", 6))
6348                 rtw_p2p_get_status(dev, info, wrqu, extra);
6349         else if (_rtw_memcmp(wrqu->data.pointer, "role", 4))
6350                 rtw_p2p_get_role(dev, info, wrqu, extra);
6351         else if (_rtw_memcmp(wrqu->data.pointer, "peer_ifa", 8))
6352                 rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
6353         else if (_rtw_memcmp(wrqu->data.pointer, "req_cm", 6))
6354                 rtw_p2p_get_req_cm(dev, info, wrqu, extra);
6355         else if (_rtw_memcmp(wrqu->data.pointer, "peer_deva", 9)) {
6356                 /*      Get the P2P device address when receiving the provision discovery request frame. */
6357                 rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
6358         } else if (_rtw_memcmp(wrqu->data.pointer, "group_id", 8))
6359                 rtw_p2p_get_groupid(dev, info, wrqu, extra);
6360         else if (_rtw_memcmp(wrqu->data.pointer, "inv_peer_deva", 13)) {
6361                 /*      Get the P2P device address when receiving the P2P Invitation request frame. */
6362                 rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
6363         } else if (_rtw_memcmp(wrqu->data.pointer, "op_ch", 5))
6364                 rtw_p2p_get_op_ch(dev, info, wrqu, extra);
6365
6366 #ifdef CONFIG_WFD
6367         if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
6368                 if (_rtw_memcmp(wrqu->data.pointer, "peer_port", 9))
6369                         rtw_p2p_get_peer_wfd_port(dev, info, wrqu, extra);
6370                 else if (_rtw_memcmp(wrqu->data.pointer, "wfd_sa", 6))
6371                         rtw_p2p_get_peer_wfd_session_available(dev, info, wrqu, extra);
6372                 else if (_rtw_memcmp(wrqu->data.pointer, "wfd_pc", 6))
6373                         rtw_p2p_get_peer_wfd_preferred_connection(dev, info, wrqu, extra);
6374         }
6375 #endif /* CONFIG_WFD */
6376
6377 #endif /* CONFIG_P2P */
6378
6379         return ret;
6380
6381 }
6382
6383 static int rtw_p2p_get2(struct net_device *dev,
6384                         struct iw_request_info *info,
6385                         union iwreq_data *wrqu, char *extra)
6386 {
6387
6388         int ret = 0;
6389
6390 #ifdef CONFIG_P2P
6391
6392         int length = wrqu->data.length;
6393         char *buffer = (u8 *)rtw_malloc(length);
6394
6395         if (buffer == NULL) {
6396                 ret = -ENOMEM;
6397                 goto bad;
6398         }
6399
6400         if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length)) {
6401                 ret = -EFAULT;
6402                 goto bad;
6403         }
6404
6405         RTW_INFO("[%s] buffer = %s\n", __FUNCTION__, buffer);
6406
6407         if (_rtw_memcmp(buffer, "wpsCM=", 6))
6408                 ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, extra, &buffer[6]);
6409         else if (_rtw_memcmp(buffer, "devN=", 5))
6410                 ret = rtw_p2p_get_device_name(dev, info, wrqu, extra, &buffer[5]);
6411         else if (_rtw_memcmp(buffer, "dev_type=", 9))
6412                 ret = rtw_p2p_get_device_type(dev, info, wrqu, extra, &buffer[9]);
6413         else if (_rtw_memcmp(buffer, "go_devadd=", 10))
6414                 ret = rtw_p2p_get_go_device_address(dev, info, wrqu, extra, &buffer[10]);
6415         else if (_rtw_memcmp(buffer, "InvProc=", 8))
6416                 ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, extra, &buffer[8]);
6417         else {
6418                 snprintf(extra, sizeof("Command not found."), "Command not found.");
6419                 wrqu->data.length = strlen(extra);
6420         }
6421
6422 bad:
6423         if (buffer)
6424                 rtw_mfree(buffer, length);
6425
6426 #endif /* CONFIG_P2P */
6427
6428         return ret;
6429
6430 }
6431
6432 static int rtw_cta_test_start(struct net_device *dev,
6433                               struct iw_request_info *info,
6434                               union iwreq_data *wrqu, char *extra)
6435 {
6436         int ret = 0;
6437         _adapter        *padapter = (_adapter *)rtw_netdev_priv(dev);
6438         RTW_INFO("%s %s\n", __func__, extra);
6439         if (!strcmp(extra, "1"))
6440                 padapter->in_cta_test = 1;
6441         else
6442                 padapter->in_cta_test = 0;
6443
6444         if (padapter->in_cta_test) {
6445                 u32 v = rtw_read32(padapter, REG_RCR);
6446                 v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); /* | RCR_ADF */
6447                 rtw_write32(padapter, REG_RCR, v);
6448                 RTW_INFO("enable RCR_ADF\n");
6449         } else {
6450                 u32 v = rtw_read32(padapter, REG_RCR);
6451                 v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN ;/* | RCR_ADF */
6452                 rtw_write32(padapter, REG_RCR, v);
6453                 RTW_INFO("disable RCR_ADF\n");
6454         }
6455         return ret;
6456 }
6457
6458
6459 extern int rtw_change_ifname(_adapter *padapter, const char *ifname);
6460 static int rtw_rereg_nd_name(struct net_device *dev,
6461                              struct iw_request_info *info,
6462                              union iwreq_data *wrqu, char *extra)
6463 {
6464         int ret = 0;
6465         _adapter *padapter = rtw_netdev_priv(dev);
6466         struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
6467         char new_ifname[IFNAMSIZ];
6468
6469         if (rereg_priv->old_ifname[0] == 0) {
6470                 char *reg_ifname;
6471 #ifdef CONFIG_CONCURRENT_MODE
6472                 if (padapter->isprimary)
6473                         reg_ifname = padapter->registrypriv.ifname;
6474                 else
6475 #endif
6476                         reg_ifname = padapter->registrypriv.if2name;
6477
6478                 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
6479                 rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
6480         }
6481
6482         /* RTW_INFO("%s wrqu->data.length:%d\n", __FUNCTION__, wrqu->data.length); */
6483         if (wrqu->data.length > IFNAMSIZ)
6484                 return -EFAULT;
6485
6486         if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
6487                 return -EFAULT;
6488
6489         if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
6490                 return ret;
6491
6492         RTW_INFO("%s new_ifname:%s\n", __FUNCTION__, new_ifname);
6493         ret = rtw_change_ifname(padapter, new_ifname);
6494         if (0 != ret)
6495                 goto exit;
6496
6497         if (_rtw_memcmp(rereg_priv->old_ifname, "disable%d", 9) == _TRUE) {
6498                 padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
6499                 rtw_hal_sw_led_init(padapter);
6500                 /* rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode); */
6501         }
6502
6503         strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
6504         rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
6505
6506         if (_rtw_memcmp(new_ifname, "disable%d", 9) == _TRUE) {
6507
6508                 RTW_INFO("%s disable\n", __FUNCTION__);
6509                 /* free network queue for Android's timming issue */
6510                 rtw_free_network_queue(padapter, _TRUE);
6511
6512                 /* close led */
6513                 rtw_led_control(padapter, LED_CTL_POWER_OFF);
6514                 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
6515                 padapter->ledpriv.bRegUseLed = _FALSE;
6516                 rtw_hal_sw_led_deinit(padapter);
6517
6518                 /* the interface is being "disabled", we can do deeper IPS */
6519                 /* rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); */
6520                 /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
6521         }
6522 exit:
6523         return ret;
6524
6525 }
6526
6527 #ifdef CONFIG_IOL
6528         #include <rtw_iol.h>
6529 #endif
6530
6531 #ifdef DBG_CMD_QUEUE
6532         u8 dump_cmd_id = 0;
6533 #endif
6534 static int rtw_dbg_port(struct net_device *dev,
6535                         struct iw_request_info *info,
6536                         union iwreq_data *wrqu, char *extra)
6537 {
6538         _irqL irqL;
6539         int ret = 0;
6540         u8 major_cmd, minor_cmd;
6541         u16 arg;
6542         u32 extra_arg, *pdata, val32;
6543         struct sta_info *psta;
6544         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6545         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6546         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6547         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6548         struct security_priv *psecuritypriv = &padapter->securitypriv;
6549         struct wlan_network *cur_network = &(pmlmepriv->cur_network);
6550         struct sta_priv *pstapriv = &padapter->stapriv;
6551
6552
6553         pdata = (u32 *)&wrqu->data;
6554
6555         val32 = *pdata;
6556         arg = (u16)(val32 & 0x0000ffff);
6557         major_cmd = (u8)(val32 >> 24);
6558         minor_cmd = (u8)((val32 >> 16) & 0x00ff);
6559
6560         extra_arg = *(pdata + 1);
6561
6562         switch (major_cmd) {
6563         case 0x70: /* read_reg */
6564                 switch (minor_cmd) {
6565                 case 1:
6566                         RTW_INFO("rtw_read8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
6567                         break;
6568                 case 2:
6569                         RTW_INFO("rtw_read16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
6570                         break;
6571                 case 4:
6572                         RTW_INFO("rtw_read32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
6573                         break;
6574                 }
6575                 break;
6576         case 0x71: /* write_reg */
6577                 switch (minor_cmd) {
6578                 case 1:
6579                         rtw_write8(padapter, arg, extra_arg);
6580                         RTW_INFO("rtw_write8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
6581                         break;
6582                 case 2:
6583                         rtw_write16(padapter, arg, extra_arg);
6584                         RTW_INFO("rtw_write16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
6585                         break;
6586                 case 4:
6587                         rtw_write32(padapter, arg, extra_arg);
6588                         RTW_INFO("rtw_write32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
6589                         break;
6590                 }
6591                 break;
6592         case 0x72: /* read_bb */
6593                 RTW_INFO("read_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
6594                 break;
6595         case 0x73: /* write_bb */
6596                 rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
6597                 RTW_INFO("write_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
6598                 break;
6599         case 0x74: /* read_rf */
6600                 RTW_INFO("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));
6601                 break;
6602         case 0x75: /* write_rf */
6603                 rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
6604                 RTW_INFO("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));
6605                 break;
6606
6607         case 0x76:
6608                 switch (minor_cmd) {
6609                 case 0x00: /* normal mode, */
6610                         padapter->recvpriv.is_signal_dbg = 0;
6611                         break;
6612                 case 0x01: /* dbg mode */
6613                         padapter->recvpriv.is_signal_dbg = 1;
6614                         extra_arg = extra_arg > 100 ? 100 : extra_arg;
6615                         padapter->recvpriv.signal_strength_dbg = extra_arg;
6616                         break;
6617                 }
6618                 break;
6619         case 0x78: /* IOL test */
6620                 switch (minor_cmd) {
6621 #ifdef CONFIG_IOL
6622                 case 0x04: { /* LLT table initialization test */
6623                         u8 page_boundary = 0xf9;
6624                         {
6625                                 struct xmit_frame       *xmit_frame;
6626
6627                                 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6628                                 if (xmit_frame == NULL) {
6629                                         ret = -ENOMEM;
6630                                         break;
6631                                 }
6632
6633                                 rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
6634
6635
6636                                 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
6637                                         ret = -EPERM;
6638                         }
6639                 }
6640                 break;
6641                 case 0x05: { /* blink LED test */
6642                         u16 reg = 0x4c;
6643                         u32 blink_num = 50;
6644                         u32 blink_delay_ms = 200;
6645                         int i;
6646
6647                         {
6648                                 struct xmit_frame       *xmit_frame;
6649
6650                                 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6651                                 if (xmit_frame == NULL) {
6652                                         ret = -ENOMEM;
6653                                         break;
6654                                 }
6655
6656                                 for (i = 0; i < blink_num; i++) {
6657 #ifdef CONFIG_IOL_NEW_GENERATION
6658                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
6659                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
6660                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
6661                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
6662 #else
6663                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00);
6664                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
6665                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08);
6666                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
6667 #endif
6668                                 }
6669                                 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms * blink_num * 2) + 200, 0))
6670                                         ret = -EPERM;
6671                         }
6672                 }
6673                 break;
6674
6675                 case 0x06: { /* continuous wirte byte test */
6676                         u16 reg = arg;
6677                         u16 start_value = 0;
6678                         u32 write_num = extra_arg;
6679                         int i;
6680                         u8 final;
6681
6682                         {
6683                                 struct xmit_frame       *xmit_frame;
6684
6685                                 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6686                                 if (xmit_frame == NULL) {
6687                                         ret = -ENOMEM;
6688                                         break;
6689                                 }
6690
6691                                 for (i = 0; i < write_num; i++) {
6692 #ifdef CONFIG_IOL_NEW_GENERATION
6693                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value, 0xFF);
6694 #else
6695                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value);
6696 #endif
6697                                 }
6698                                 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
6699                                         ret = -EPERM;
6700                         }
6701
6702                         final = rtw_read8(padapter, reg);
6703                         if (start_value + write_num - 1 == final)
6704                                 RTW_INFO("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6705                         else
6706                                 RTW_INFO("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6707                 }
6708                 break;
6709
6710                 case 0x07: { /* continuous wirte word test */
6711                         u16 reg = arg;
6712                         u16 start_value = 200;
6713                         u32 write_num = extra_arg;
6714
6715                         int i;
6716                         u16 final;
6717
6718                         {
6719                                 struct xmit_frame       *xmit_frame;
6720
6721                                 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6722                                 if (xmit_frame == NULL) {
6723                                         ret = -ENOMEM;
6724                                         break;
6725                                 }
6726
6727                                 for (i = 0; i < write_num; i++) {
6728 #ifdef CONFIG_IOL_NEW_GENERATION
6729                                         rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value, 0xFFFF);
6730 #else
6731                                         rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value);
6732 #endif
6733                                 }
6734                                 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
6735                                         ret = -EPERM;
6736                         }
6737
6738                         final = rtw_read16(padapter, reg);
6739                         if (start_value + write_num - 1 == final)
6740                                 RTW_INFO("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6741                         else
6742                                 RTW_INFO("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6743                 }
6744                 break;
6745
6746                 case 0x08: { /* continuous wirte dword test */
6747                         u16 reg = arg;
6748                         u32 start_value = 0x110000c7;
6749                         u32 write_num = extra_arg;
6750
6751                         int i;
6752                         u32 final;
6753
6754                         {
6755                                 struct xmit_frame       *xmit_frame;
6756
6757                                 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6758                                 if (xmit_frame == NULL) {
6759                                         ret = -ENOMEM;
6760                                         break;
6761                                 }
6762
6763                                 for (i = 0; i < write_num; i++) {
6764 #ifdef CONFIG_IOL_NEW_GENERATION
6765                                         rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value, 0xFFFFFFFF);
6766 #else
6767                                         rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value);
6768 #endif
6769                                 }
6770                                 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
6771                                         ret = -EPERM;
6772
6773                         }
6774
6775                         final = rtw_read32(padapter, reg);
6776                         if (start_value + write_num - 1 == final)
6777                                 RTW_INFO("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6778                         else
6779                                 RTW_INFO("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6780                 }
6781                 break;
6782 #endif /* CONFIG_IOL */
6783                 }
6784                 break;
6785         case 0x79: {
6786                 /*
6787                 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
6788                 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
6789                 */
6790                 u8 value =  extra_arg & 0x0f;
6791                 u8 sign = minor_cmd;
6792                 u16 write_value = 0;
6793
6794                 RTW_INFO("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
6795
6796                 if (sign)
6797                         value = value | 0x10;
6798
6799                 write_value = value | (value << 5);
6800                 rtw_write16(padapter, 0x6d9, write_value);
6801         }
6802         break;
6803         case 0x7a:
6804                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress
6805                                    , WLAN_REASON_EXPIRATION_CHK, _FALSE);
6806                 break;
6807         case 0x7F:
6808                 switch (minor_cmd) {
6809                 case 0x0:
6810                         RTW_INFO("fwstate=0x%x\n", get_fwstate(pmlmepriv));
6811                         break;
6812                 case 0x01:
6813                         RTW_INFO("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
6814                                 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
6815                                 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
6816                         break;
6817                 case 0x02:
6818                         RTW_INFO("pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
6819                         RTW_INFO("DrvBcnEarly=%d\n", pmlmeext->DrvBcnEarly);
6820                         RTW_INFO("DrvBcnTimeOut=%d\n", pmlmeext->DrvBcnTimeOut);
6821                         break;
6822                 case 0x03:
6823                         RTW_INFO("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
6824 #ifdef CONFIG_80211N_HT
6825                         RTW_INFO("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
6826 #endif /* CONFIG_80211N_HT */
6827                         break;
6828                 case 0x04:
6829                         RTW_INFO("cur_ch=%d\n", pmlmeext->cur_channel);
6830                         RTW_INFO("cur_bw=%d\n", pmlmeext->cur_bwmode);
6831                         RTW_INFO("cur_ch_off=%d\n", pmlmeext->cur_ch_offset);
6832
6833                         RTW_INFO("oper_ch=%d\n", rtw_get_oper_ch(padapter));
6834                         RTW_INFO("oper_bw=%d\n", rtw_get_oper_bw(padapter));
6835                         RTW_INFO("oper_ch_offet=%d\n", rtw_get_oper_choffset(padapter));
6836
6837                         break;
6838                 case 0x05:
6839                         psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
6840                         if (psta) {
6841                                 RTW_INFO("SSID=%s\n", cur_network->network.Ssid.Ssid);
6842                                 RTW_INFO("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
6843                                 RTW_INFO("cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
6844                                 RTW_INFO("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
6845                                 RTW_INFO("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
6846 #ifdef CONFIG_80211N_HT
6847                                 RTW_INFO("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
6848                                 RTW_INFO("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);
6849                                 RTW_INFO("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
6850                                 RTW_INFO("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
6851 #endif /* CONFIG_80211N_HT */
6852
6853                                 sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
6854                         } else
6855                                 RTW_INFO("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
6856                         break;
6857                 case 0x06: {
6858                 }
6859                 break;
6860                 case 0x07:
6861                         RTW_INFO("bSurpriseRemoved=%s, bDriverStopped=%s\n"
6862                                 , rtw_is_surprise_removed(padapter) ? "True" : "False"
6863                                 , rtw_is_drv_stopped(padapter) ? "True" : "False");
6864                         break;
6865                 case 0x08: {
6866                         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6867                         struct recv_priv  *precvpriv = &padapter->recvpriv;
6868
6869                         RTW_INFO("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d"
6870                                 ", free_xmit_extbuf_cnt=%d, free_xframe_ext_cnt=%d"
6871                                  ", free_recvframe_cnt=%d\n",
6872                                 pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt,
6873                                 pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt,
6874                                  precvpriv->free_recvframe_cnt);
6875 #ifdef CONFIG_USB_HCI
6876                         RTW_INFO("rx_urb_pending_cn=%d\n", ATOMIC_READ(&(precvpriv->rx_pending_cnt)));
6877 #endif
6878                 }
6879                 break;
6880                 case 0x09: {
6881                         int i;
6882                         _list   *plist, *phead;
6883
6884 #ifdef CONFIG_AP_MODE
6885                         RTW_INFO("sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
6886 #endif
6887                         _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
6888
6889                         for (i = 0; i < NUM_STA; i++) {
6890                                 phead = &(pstapriv->sta_hash[i]);
6891                                 plist = get_next(phead);
6892
6893                                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
6894                                         psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
6895
6896                                         plist = get_next(plist);
6897
6898                                         if (extra_arg == psta->aid) {
6899                                                 RTW_INFO("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
6900                                                 RTW_INFO("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
6901                                                 RTW_INFO("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
6902 #ifdef CONFIG_80211N_HT
6903                                                 RTW_INFO("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
6904                                                 RTW_INFO("bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m,
6905                                                         psta->htpriv.sgi_40m);
6906                                                 RTW_INFO("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
6907                                                 RTW_INFO("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
6908 #endif /* CONFIG_80211N_HT */
6909
6910 #ifdef CONFIG_AP_MODE
6911                                                 RTW_INFO("capability=0x%x\n", psta->capability);
6912                                                 RTW_INFO("flags=0x%x\n", psta->flags);
6913                                                 RTW_INFO("wpa_psk=0x%x\n", psta->wpa_psk);
6914                                                 RTW_INFO("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
6915                                                 RTW_INFO("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
6916                                                 RTW_INFO("qos_info=0x%x\n", psta->qos_info);
6917 #endif
6918                                                 RTW_INFO("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
6919
6920                                                 sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
6921                                         }
6922
6923                                 }
6924                         }
6925
6926                         _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
6927
6928                 }
6929                 break;
6930
6931                 case 0x0b: { /* Enable=1, Disable=0 driver control vrtl_carrier_sense. */
6932                         /* u8 driver_vcs_en; */ /* Enable=1, Disable=0 driver control vrtl_carrier_sense. */
6933                         /* u8 driver_vcs_type; */ /* force 0:disable VCS, 1:RTS-CTS, 2:CTS-to-self when vcs_en=1. */
6934
6935                         if (arg == 0) {
6936                                 RTW_INFO("disable driver ctrl vcs\n");
6937                                 padapter->driver_vcs_en = 0;
6938                         } else if (arg == 1) {
6939                                 RTW_INFO("enable driver ctrl vcs = %d\n", extra_arg);
6940                                 padapter->driver_vcs_en = 1;
6941
6942                                 if (extra_arg > 2)
6943                                         padapter->driver_vcs_type = 1;
6944                                 else
6945                                         padapter->driver_vcs_type = extra_arg;
6946                         }
6947                 }
6948                 break;
6949                 case 0x0c: { /* dump rx/tx packet */
6950                         if (arg == 0) {
6951                                 RTW_INFO("dump rx packet (%d)\n", extra_arg);
6952                                 /* pHalData->bDumpRxPkt =extra_arg;                                              */
6953                                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
6954                         } else if (arg == 1) {
6955                                 RTW_INFO("dump tx packet (%d)\n", extra_arg);
6956                                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
6957                         }
6958                 }
6959                 break;
6960                 case 0x0e: {
6961                         if (arg == 0) {
6962                                 RTW_INFO("disable driver ctrl rx_ampdu_factor\n");
6963                                 padapter->driver_rx_ampdu_factor = 0xFF;
6964                         } else if (arg == 1) {
6965
6966                                 RTW_INFO("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg);
6967
6968                                 if (extra_arg > 0x03)
6969                                         padapter->driver_rx_ampdu_factor = 0xFF;
6970                                 else
6971                                         padapter->driver_rx_ampdu_factor = extra_arg;
6972                         }
6973                 }
6974                 break;
6975 #ifdef DBG_CONFIG_ERROR_DETECT
6976                 case 0x0f: {
6977                         if (extra_arg == 0) {
6978                                 RTW_INFO("###### silent reset test.......#####\n");
6979                                 rtw_hal_sreset_reset(padapter);
6980                         } else {
6981                                 HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
6982                                 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
6983                                 psrtpriv->dbg_trigger_point = extra_arg;
6984                         }
6985
6986                 }
6987                 break;
6988                 case 0x15: {
6989                         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
6990                         RTW_INFO("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
6991                 }
6992                 break;
6993
6994 #endif
6995
6996                 case 0x10: /* driver version display */
6997                         dump_drv_version(RTW_DBGDUMP);
6998                         break;
6999                 case 0x11: { /* dump linked status */
7000                         int pre_mode;
7001                         pre_mode = padapter->bLinkInfoDump;
7002                         /* linked_info_dump(padapter,extra_arg); */
7003                         if (extra_arg == 1 || (extra_arg == 0 && pre_mode == 1)) /* not consider pwr_saving 0: */
7004                                 padapter->bLinkInfoDump = extra_arg;
7005
7006                         else if ((extra_arg == 2) || (extra_arg == 0 && pre_mode == 2)) { /* consider power_saving */
7007                                 /* RTW_INFO("linked_info_dump =%s\n", (padapter->bLinkInfoDump)?"enable":"disable") */
7008                                 linked_info_dump(padapter, extra_arg);
7009                         }
7010
7011
7012
7013                 }
7014                 break;
7015 #ifdef CONFIG_80211N_HT
7016                 case 0x12: { /* set rx_stbc */
7017                         struct registry_priv    *pregpriv = &padapter->registrypriv;
7018                         /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
7019                         /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
7020                         if (pregpriv && (extra_arg == 0 || extra_arg == 1 || extra_arg == 2 || extra_arg == 3)) {
7021                                 pregpriv->rx_stbc = extra_arg;
7022                                 RTW_INFO("set rx_stbc=%d\n", pregpriv->rx_stbc);
7023                         } else
7024                                 RTW_INFO("get rx_stbc=%d\n", pregpriv->rx_stbc);
7025
7026                 }
7027                 break;
7028                 case 0x13: { /* set ampdu_enable */
7029                         struct registry_priv    *pregpriv = &padapter->registrypriv;
7030                         /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
7031                         if (pregpriv && extra_arg < 3) {
7032                                 pregpriv->ampdu_enable = extra_arg;
7033                                 RTW_INFO("set ampdu_enable=%d\n", pregpriv->ampdu_enable);
7034                         } else
7035                                 RTW_INFO("get ampdu_enable=%d\n", pregpriv->ampdu_enable);
7036
7037                 }
7038                 break;
7039 #endif
7040                 case 0x14: { /* get wifi_spec */
7041                         struct registry_priv    *pregpriv = &padapter->registrypriv;
7042                         RTW_INFO("get wifi_spec=%d\n", pregpriv->wifi_spec);
7043
7044                 }
7045                 break;
7046                 case 0x16: {
7047                         if (arg == 0xff)
7048                                 rtw_odm_dbg_comp_msg(RTW_DBGDUMP, padapter);
7049                         else {
7050                                 u64 dbg_comp = (u64)extra_arg;
7051                                 rtw_odm_dbg_comp_set(padapter, dbg_comp);
7052                         }
7053                 }
7054                 break;
7055 #ifdef DBG_FIXED_CHAN
7056                 case 0x17: {
7057                         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7058                         printk("===>  Fixed channel to %d\n", extra_arg);
7059                         pmlmeext->fixed_chan = extra_arg;
7060
7061                 }
7062                 break;
7063 #endif
7064 #ifdef CONFIG_80211N_HT
7065                 case 0x19: {
7066                         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
7067                         /* extra_arg : */
7068                         /* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
7069                         /* BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
7070                         if (arg == 0) {
7071                                 RTW_INFO("driver disable LDPC\n");
7072                                 pregistrypriv->ldpc_cap = 0x00;
7073                         } else if (arg == 1) {
7074                                 RTW_INFO("driver set LDPC cap = 0x%x\n", extra_arg);
7075                                 pregistrypriv->ldpc_cap = (u8)(extra_arg & 0x33);
7076                         }
7077                 }
7078                 break;
7079                 case 0x1a: {
7080                         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
7081                         /* extra_arg : */
7082                         /* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
7083                         /* BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
7084                         if (arg == 0) {
7085                                 RTW_INFO("driver disable STBC\n");
7086                                 pregistrypriv->stbc_cap = 0x00;
7087                         } else if (arg == 1) {
7088                                 RTW_INFO("driver set STBC cap = 0x%x\n", extra_arg);
7089                                 pregistrypriv->stbc_cap = (u8)(extra_arg & 0x33);
7090                         }
7091                 }
7092                 break;
7093 #endif /* CONFIG_80211N_HT */
7094                 case 0x1b: {
7095                         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
7096
7097                         if (arg == 0) {
7098                                 RTW_INFO("disable driver ctrl max_rx_rate, reset to default_rate_set\n");
7099                                 init_mlme_default_rate_set(padapter);
7100 #ifdef CONFIG_80211N_HT
7101                                 pregistrypriv->ht_enable = (u8)rtw_ht_enable;
7102 #endif /* CONFIG_80211N_HT */
7103                         } else if (arg == 1) {
7104
7105                                 int i;
7106                                 u8 max_rx_rate;
7107
7108                                 RTW_INFO("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg);
7109
7110                                 max_rx_rate = (u8)extra_arg;
7111
7112                                 if (max_rx_rate < 0xc) { /* max_rx_rate < MSC0->B or G -> disable HT */
7113 #ifdef CONFIG_80211N_HT
7114                                         pregistrypriv->ht_enable = 0;
7115 #endif /* CONFIG_80211N_HT */
7116                                         for (i = 0; i < NumRates; i++) {
7117                                                 if (pmlmeext->datarate[i] > max_rx_rate)
7118                                                         pmlmeext->datarate[i] = 0xff;
7119                                         }
7120
7121                                 }
7122 #ifdef CONFIG_80211N_HT
7123                                 else if (max_rx_rate < 0x1c) { /* mcs0~mcs15 */
7124                                         u32 mcs_bitmap = 0x0;
7125
7126                                         for (i = 0; i < ((max_rx_rate + 1) - 0xc); i++)
7127                                                 mcs_bitmap |= BIT(i);
7128
7129                                         set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
7130                                 }
7131 #endif /* CONFIG_80211N_HT                                                       */
7132                         }
7133                 }
7134                 break;
7135                 case 0x1c: { /* enable/disable driver control AMPDU Density for peer sta's rx */
7136                         if (arg == 0) {
7137                                 RTW_INFO("disable driver ctrl ampdu density\n");
7138                                 padapter->driver_ampdu_spacing = 0xFF;
7139                         } else if (arg == 1) {
7140
7141                                 RTW_INFO("enable driver ctrl ampdu density = %d\n", extra_arg);
7142
7143                                 if (extra_arg > 0x07)
7144                                         padapter->driver_ampdu_spacing = 0xFF;
7145                                 else
7146                                         padapter->driver_ampdu_spacing = extra_arg;
7147                         }
7148                 }
7149                 break;
7150 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
7151                 case 0x1e: {
7152                         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
7153                         PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
7154                         u8 chan = rtw_get_oper_ch(padapter);
7155                         RTW_INFO("===========================================\n");
7156                         ODM_InbandNoise_Monitor(pDM_Odm, _TRUE, 0x1e, 100);
7157                         RTW_INFO("channel(%d),noise_a = %d, noise_b = %d , noise_all:%d\n",
7158                                 chan, pDM_Odm->noise_level.noise[ODM_RF_PATH_A],
7159                                 pDM_Odm->noise_level.noise[ODM_RF_PATH_B],
7160                                  pDM_Odm->noise_level.noise_all);
7161                         RTW_INFO("===========================================\n");
7162
7163                 }
7164                 break;
7165 #endif
7166                 case 0x23: {
7167                         RTW_INFO("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
7168                         padapter->bNotifyChannelChange = extra_arg;
7169                         break;
7170                 }
7171                 case 0x24: {
7172 #ifdef CONFIG_P2P
7173                         RTW_INFO("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
7174                         padapter->bShowGetP2PState = extra_arg;
7175 #endif /* CONFIG_P2P */
7176                         break;
7177                 }
7178 #ifdef CONFIG_GPIO_API
7179                 case 0x25: { /* Get GPIO register */
7180                         /*
7181                         * dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7
7182                         */
7183
7184                         u8 value;
7185                         RTW_INFO("Read GPIO Value  extra_arg = %d\n", extra_arg);
7186                         value = rtw_hal_get_gpio(padapter, extra_arg);
7187                         RTW_INFO("Read GPIO Value = %d\n", value);
7188                         break;
7189                 }
7190                 case 0x26: { /* Set GPIO direction */
7191
7192                         /* dbg 0x7f26000x [y], Set gpio direction,
7193                         * x: gpio_num,4~7  y: indicate direction, 0~1
7194                         */
7195
7196                         int value;
7197                         RTW_INFO("Set GPIO Direction! arg = %d ,extra_arg=%d\n", arg , extra_arg);
7198                         value = rtw_hal_config_gpio(padapter, arg, extra_arg);
7199                         RTW_INFO("Set GPIO Direction %s\n", (value == -1) ? "Fail!!!" : "Success");
7200                         break;
7201                 }
7202                 case 0x27: { /* Set GPIO output direction value */
7203                         /*
7204                         * dbg 0x7f27000x [y], Set gpio output direction value,
7205                         * x: gpio_num,4~7  y: indicate direction, 0~1
7206                         */
7207
7208                         int value;
7209                         RTW_INFO("Set GPIO Value! arg = %d ,extra_arg=%d\n", arg , extra_arg);
7210                         value = rtw_hal_set_gpio_output_value(padapter, arg, extra_arg);
7211                         RTW_INFO("Set GPIO Value %s\n", (value == -1) ? "Fail!!!" : "Success");
7212                         break;
7213                 }
7214 #endif
7215 #ifdef DBG_CMD_QUEUE
7216                 case 0x28: {
7217                         dump_cmd_id = extra_arg;
7218                         RTW_INFO("dump_cmd_id:%d\n", dump_cmd_id);
7219                 }
7220                 break;
7221 #endif /* DBG_CMD_QUEUE */
7222                 case 0xaa: {
7223                         if ((extra_arg & 0x7F) > 0x3F)
7224                                 extra_arg = 0xFF;
7225                         RTW_INFO("chang data rate to :0x%02x\n", extra_arg);
7226                         padapter->fix_rate = extra_arg;
7227                 }
7228                 break;
7229                 case 0xdd: { /* registers dump , 0 for mac reg,1 for bb reg, 2 for rf reg */
7230                         if (extra_arg == 0)
7231                                 mac_reg_dump(RTW_DBGDUMP, padapter);
7232                         else if (extra_arg == 1)
7233                                 bb_reg_dump(RTW_DBGDUMP, padapter);
7234                         else if (extra_arg == 2)
7235                                 rf_reg_dump(RTW_DBGDUMP, padapter);
7236                 }
7237                 break;
7238
7239                 case 0xee: {
7240                         RTW_INFO(" === please control /proc  to trun on/off PHYDM func ===\n");
7241                 }
7242                 break;
7243
7244                 case 0xfd:
7245                         rtw_write8(padapter, 0xc50, arg);
7246                         RTW_INFO("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
7247                         rtw_write8(padapter, 0xc58, arg);
7248                         RTW_INFO("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
7249                         break;
7250                 case 0xfe:
7251                         RTW_INFO("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
7252                         RTW_INFO("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
7253                         break;
7254                 case 0xff: {
7255                         RTW_INFO("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
7256                         RTW_INFO("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
7257                         RTW_INFO("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
7258                         RTW_INFO("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
7259                         RTW_INFO("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
7260
7261                         RTW_INFO("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
7262
7263
7264                         RTW_INFO("\n");
7265
7266                         RTW_INFO("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
7267                         RTW_INFO("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
7268
7269                         RTW_INFO("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
7270
7271                         RTW_INFO("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
7272
7273                         RTW_INFO("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
7274                         RTW_INFO("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
7275
7276                         RTW_INFO("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
7277                         RTW_INFO("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
7278                         RTW_INFO("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
7279                         RTW_INFO("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
7280                 }
7281                 break;
7282                 }
7283                 break;
7284         default:
7285                 RTW_INFO("error dbg cmd!\n");
7286                 break;
7287         }
7288
7289
7290         return ret;
7291
7292 }
7293
7294 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
7295 {
7296         uint ret = 0;
7297         u32 flags;
7298         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7299
7300         switch (name) {
7301         case IEEE_PARAM_WPA_ENABLED:
7302
7303                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
7304
7305                 /* ret = ieee80211_wpa_enable(ieee, value); */
7306
7307                 switch ((value) & 0xff) {
7308                 case 1: /* WPA */
7309                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
7310                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
7311                         break;
7312                 case 2: /* WPA2 */
7313                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
7314                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
7315                         break;
7316                 }
7317
7318                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("wpa_set_param:padapter->securitypriv.ndisauthtype=%d\n", padapter->securitypriv.ndisauthtype));
7319
7320                 break;
7321
7322         case IEEE_PARAM_TKIP_COUNTERMEASURES:
7323                 /* ieee->tkip_countermeasures=value; */
7324                 break;
7325
7326         case IEEE_PARAM_DROP_UNENCRYPTED: {
7327                 /* HACK:
7328                  *
7329                  * wpa_supplicant calls set_wpa_enabled when the driver
7330                  * is loaded and unloaded, regardless of if WPA is being
7331                  * used.  No other calls are made which can be used to
7332                  * determine if encryption will be used or not prior to
7333                  * association being expected.  If encryption is not being
7334                  * used, drop_unencrypted is set to false, else true -- we
7335                  * can use this to determine if the CAP_PRIVACY_ON bit should
7336                  * be set.
7337                  */
7338
7339 #if 0
7340                 struct ieee80211_security sec = {
7341                         .flags = SEC_ENABLED,
7342                         .enabled = value,
7343                 };
7344                 ieee->drop_unencrypted = value;
7345                 /* We only change SEC_LEVEL for open mode. Others
7346                  * are set by ipw_wpa_set_encryption.
7347                  */
7348                 if (!value) {
7349                         sec.flags |= SEC_LEVEL;
7350                         sec.level = SEC_LEVEL_0;
7351                 } else {
7352                         sec.flags |= SEC_LEVEL;
7353                         sec.level = SEC_LEVEL_1;
7354                 }
7355                 if (ieee->set_security)
7356                         ieee->set_security(ieee->dev, &sec);
7357 #endif
7358                 break;
7359
7360         }
7361         case IEEE_PARAM_PRIVACY_INVOKED:
7362
7363                 /* ieee->privacy_invoked=value; */
7364
7365                 break;
7366
7367         case IEEE_PARAM_AUTH_ALGS:
7368
7369                 ret = wpa_set_auth_algs(dev, value);
7370
7371                 break;
7372
7373         case IEEE_PARAM_IEEE_802_1X:
7374
7375                 /* ieee->ieee802_1x=value;               */
7376
7377                 break;
7378
7379         case IEEE_PARAM_WPAX_SELECT:
7380
7381                 /* added for WPA2 mixed mode */
7382                 /*RTW_WARN("------------------------>wpax value = %x\n", value);*/
7383                 /*
7384                 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
7385                 ieee->wpax_type_set = 1;
7386                 ieee->wpax_type_notify = value;
7387                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
7388                 */
7389
7390                 break;
7391
7392         default:
7393
7394
7395
7396                 ret = -EOPNOTSUPP;
7397
7398
7399                 break;
7400
7401         }
7402
7403         return ret;
7404
7405 }
7406
7407 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
7408 {
7409         int ret = 0;
7410         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7411
7412         switch (command) {
7413         case IEEE_MLME_STA_DEAUTH:
7414
7415                 if (!rtw_set_802_11_disassociate(padapter))
7416                         ret = -1;
7417
7418                 break;
7419
7420         case IEEE_MLME_STA_DISASSOC:
7421
7422                 if (!rtw_set_802_11_disassociate(padapter))
7423                         ret = -1;
7424
7425                 break;
7426
7427         default:
7428                 ret = -EOPNOTSUPP;
7429                 break;
7430         }
7431
7432         return ret;
7433
7434 }
7435
7436 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
7437 {
7438         struct ieee_param *param;
7439         uint ret = 0;
7440
7441         /* down(&ieee->wx_sem);  */
7442
7443         if (p->length < sizeof(struct ieee_param) || !p->pointer) {
7444                 ret = -EINVAL;
7445                 goto out;
7446         }
7447
7448         param = (struct ieee_param *)rtw_malloc(p->length);
7449         if (param == NULL) {
7450                 ret = -ENOMEM;
7451                 goto out;
7452         }
7453
7454         if (copy_from_user(param, p->pointer, p->length)) {
7455                 rtw_mfree((u8 *)param, p->length);
7456                 ret = -EFAULT;
7457                 goto out;
7458         }
7459
7460         switch (param->cmd) {
7461
7462         case IEEE_CMD_SET_WPA_PARAM:
7463                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
7464                 break;
7465
7466         case IEEE_CMD_SET_WPA_IE:
7467                 /* ret = wpa_set_wpa_ie(dev, param, p->length); */
7468                 ret =  rtw_set_wpa_ie((_adapter *)rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
7469                 break;
7470
7471         case IEEE_CMD_SET_ENCRYPTION:
7472                 ret = wpa_set_encryption(dev, param, p->length);
7473                 break;
7474
7475         case IEEE_CMD_MLME:
7476                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
7477                 break;
7478
7479         default:
7480                 RTW_INFO("Unknown WPA supplicant request: %d\n", param->cmd);
7481                 ret = -EOPNOTSUPP;
7482                 break;
7483
7484         }
7485
7486         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
7487                 ret = -EFAULT;
7488
7489         rtw_mfree((u8 *)param, p->length);
7490
7491 out:
7492
7493         /* up(&ieee->wx_sem); */
7494
7495         return ret;
7496
7497 }
7498
7499 #ifdef CONFIG_AP_MODE
7500 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
7501 {
7502         int ret = 0;
7503         u32 wep_key_idx, wep_key_len, wep_total_len;
7504         NDIS_802_11_WEP *pwep = NULL;
7505         struct sta_info *psta = NULL, *pbcmc_sta = NULL;
7506         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7507         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
7508         struct security_priv *psecuritypriv = &(padapter->securitypriv);
7509         struct sta_priv *pstapriv = &padapter->stapriv;
7510
7511         RTW_INFO("%s\n", __FUNCTION__);
7512
7513         param->u.crypt.err = 0;
7514         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
7515
7516         /* sizeof(struct ieee_param) = 64 bytes; */
7517         /* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
7518         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
7519                 ret =  -EINVAL;
7520                 goto exit;
7521         }
7522
7523         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7524             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7525             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
7526                 if (param->u.crypt.idx >= WEP_KEYS
7527 #ifdef CONFIG_IEEE80211W
7528                     && param->u.crypt.idx > BIP_MAX_KEYID
7529 #endif /* CONFIG_IEEE80211W */
7530                    ) {
7531                         ret = -EINVAL;
7532                         goto exit;
7533                 }
7534         } else {
7535                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7536                 if (!psta) {
7537                         /* ret = -EINVAL; */
7538                         RTW_INFO("rtw_set_encryption(), sta has already been removed or never been added\n");
7539                         goto exit;
7540                 }
7541         }
7542
7543         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
7544                 /* todo:clear default encryption keys */
7545
7546                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
7547                 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
7548                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
7549                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
7550
7551                 RTW_INFO("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
7552
7553                 goto exit;
7554         }
7555
7556
7557         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
7558                 RTW_INFO("r871x_set_encryption, crypt.alg = WEP\n");
7559
7560                 wep_key_idx = param->u.crypt.idx;
7561                 wep_key_len = param->u.crypt.key_len;
7562
7563                 RTW_INFO("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
7564
7565                 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
7566                         ret = -EINVAL;
7567                         goto exit;
7568                 }
7569
7570
7571                 if (wep_key_len > 0) {
7572                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
7573                         wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
7574                         pwep = (NDIS_802_11_WEP *)rtw_malloc(wep_total_len);
7575                         if (pwep == NULL) {
7576                                 RTW_INFO(" r871x_set_encryption: pwep allocate fail !!!\n");
7577                                 goto exit;
7578                         }
7579
7580                         _rtw_memset(pwep, 0, wep_total_len);
7581
7582                         pwep->KeyLength = wep_key_len;
7583                         pwep->Length = wep_total_len;
7584
7585                 }
7586
7587                 pwep->KeyIndex = wep_key_idx;
7588
7589                 _rtw_memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
7590
7591                 if (param->u.crypt.set_tx) {
7592                         RTW_INFO("wep, set_tx=1\n");
7593
7594                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
7595                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
7596                         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
7597                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
7598
7599                         if (pwep->KeyLength == 13) {
7600                                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
7601                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
7602                         }
7603
7604
7605                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
7606
7607                         _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
7608
7609                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
7610
7611                         rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
7612                 } else {
7613                         RTW_INFO("wep, set_tx=0\n");
7614
7615                         /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and  */
7616                         /* "psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to cam */
7617
7618                         _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
7619
7620                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
7621
7622                         rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
7623                 }
7624
7625                 goto exit;
7626
7627         }
7628
7629
7630         if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) /*  */ { /* group key */
7631                 if (param->u.crypt.set_tx == 1) {
7632                         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
7633                                 RTW_INFO("%s, set group_key, WEP\n", __FUNCTION__);
7634
7635                                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7636
7637                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
7638                                 if (param->u.crypt.key_len == 13)
7639                                         psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
7640
7641                         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
7642                                 RTW_INFO("%s, set group_key, TKIP\n", __FUNCTION__);
7643
7644                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
7645
7646                                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7647
7648                                 /* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
7649                                 /* set mic key */
7650                                 _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
7651                                 _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
7652
7653                                 psecuritypriv->busetkipkey = _TRUE;
7654
7655                         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
7656                                 RTW_INFO("%s, set group_key, CCMP\n", __FUNCTION__);
7657
7658                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
7659
7660                                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7661                         }
7662 #ifdef CONFIG_IEEE80211W
7663                         else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
7664                                 int no;
7665
7666                                 RTW_INFO("BIP key_len=%d , index=%d\n", param->u.crypt.key_len, param->u.crypt.idx);
7667                                 /* save the IGTK key, length 16 bytes */
7668                                 _rtw_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));
7669                                 /* RTW_INFO("IGTK key below:\n");
7670                                 for(no=0;no<16;no++)
7671                                         printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
7672                                 RTW_INFO("\n"); */
7673                                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
7674                                 padapter->securitypriv.binstallBIPkey = _TRUE;
7675                                 RTW_INFO(" ~~~~set sta key:IGKT\n");
7676                                 goto exit;
7677                         }
7678 #endif /* CONFIG_IEEE80211W */
7679                         else {
7680                                 RTW_INFO("%s, set group_key, none\n", __FUNCTION__);
7681
7682                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
7683                         }
7684
7685                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
7686
7687                         psecuritypriv->binstallGrpkey = _TRUE;
7688
7689                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
7690
7691                         rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
7692
7693                         pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
7694                         if (pbcmc_sta) {
7695                                 pbcmc_sta->ieee8021x_blocked = _FALSE;
7696                                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy                   */
7697                         }
7698
7699                 }
7700
7701                 goto exit;
7702
7703         }
7704
7705         if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
7706                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
7707                         if (param->u.crypt.set_tx == 1) {
7708                                 _rtw_memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7709
7710                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
7711                                         RTW_INFO("%s, set pairwise key, WEP\n", __FUNCTION__);
7712
7713                                         psta->dot118021XPrivacy = _WEP40_;
7714                                         if (param->u.crypt.key_len == 13)
7715                                                 psta->dot118021XPrivacy = _WEP104_;
7716                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
7717                                         RTW_INFO("%s, set pairwise key, TKIP\n", __FUNCTION__);
7718
7719                                         psta->dot118021XPrivacy = _TKIP_;
7720
7721                                         /* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
7722                                         /* set mic key */
7723                                         _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
7724                                         _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
7725
7726                                         psecuritypriv->busetkipkey = _TRUE;
7727
7728                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
7729
7730                                         RTW_INFO("%s, set pairwise key, CCMP\n", __FUNCTION__);
7731
7732                                         psta->dot118021XPrivacy = _AES_;
7733                                 } else {
7734                                         RTW_INFO("%s, set pairwise key, none\n", __FUNCTION__);
7735
7736                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
7737                                 }
7738
7739                                 rtw_ap_set_pairwise_key(padapter, psta);
7740
7741                                 psta->ieee8021x_blocked = _FALSE;
7742
7743                                 psta->bpairwise_key_installed = _TRUE;
7744
7745                         } else { /* group key??? */
7746                                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
7747                                         _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7748
7749                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
7750                                         if (param->u.crypt.key_len == 13)
7751                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
7752                                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
7753                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
7754
7755                                         _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7756
7757                                         /* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
7758                                         /* set mic key */
7759                                         _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
7760                                         _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
7761
7762                                         psecuritypriv->busetkipkey = _TRUE;
7763
7764                                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
7765                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
7766
7767                                         _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7768                                 } else
7769                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
7770
7771                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
7772
7773                                 psecuritypriv->binstallGrpkey = _TRUE;
7774
7775                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
7776
7777                                 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
7778
7779                                 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
7780                                 if (pbcmc_sta) {
7781                                         pbcmc_sta->ieee8021x_blocked = _FALSE;
7782                                         pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy                   */
7783                                 }
7784
7785                         }
7786
7787                 }
7788
7789         }
7790
7791 exit:
7792
7793         if (pwep)
7794                 rtw_mfree((u8 *)pwep, wep_total_len);
7795
7796         return ret;
7797
7798 }
7799
7800 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
7801 {
7802         int ret = 0;
7803         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7804         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7805         struct sta_priv *pstapriv = &padapter->stapriv;
7806         unsigned char *pbuf = param->u.bcn_ie.buf;
7807
7808
7809         RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
7810
7811         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7812                 return -EINVAL;
7813
7814         _rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
7815
7816         if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
7817                 pstapriv->max_num_sta = NUM_STA;
7818
7819
7820         if (rtw_check_beacon_data(padapter, pbuf, (len - 12 - 2)) == _SUCCESS) /* 12 = param header, 2:no packed */
7821                 ret = 0;
7822         else
7823                 ret = -EINVAL;
7824
7825
7826         return ret;
7827
7828 }
7829
7830 static int rtw_hostapd_sta_flush(struct net_device *dev)
7831 {
7832         /* _irqL irqL; */
7833         /* _list        *phead, *plist; */
7834         int ret = 0;
7835         /* struct sta_info *psta = NULL; */
7836         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7837         /* struct sta_priv *pstapriv = &padapter->stapriv; */
7838
7839         RTW_INFO("%s\n", __FUNCTION__);
7840
7841         flush_all_cam_entry(padapter);  /* clear CAM */
7842
7843         ret = rtw_sta_flush(padapter, _TRUE);
7844
7845         return ret;
7846
7847 }
7848
7849 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
7850 {
7851         _irqL irqL;
7852         int ret = 0;
7853         struct sta_info *psta = NULL;
7854         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7855         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7856         struct sta_priv *pstapriv = &padapter->stapriv;
7857
7858         RTW_INFO("rtw_add_sta(aid=%d)=" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
7859
7860         if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != _TRUE)
7861                 return -EINVAL;
7862
7863         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7864             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7865             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7866                 return -EINVAL;
7867
7868 #if 0
7869         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7870         if (psta) {
7871                 RTW_INFO("rtw_add_sta(), free has been added psta=%p\n", psta);
7872                 /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                */
7873                 rtw_free_stainfo(padapter,  psta);
7874                 /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
7875
7876                 psta = NULL;
7877         }
7878 #endif
7879         /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
7880         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7881         if (psta) {
7882                 int flags = param->u.add_sta.flags;
7883
7884                 /* RTW_INFO("rtw_add_sta(), init sta's variables, psta=%p\n", psta); */
7885
7886                 psta->aid = param->u.add_sta.aid;/* aid=1~2007 */
7887
7888                 _rtw_memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
7889
7890
7891                 /* check wmm cap. */
7892                 if (WLAN_STA_WME & flags)
7893                         psta->qos_option = 1;
7894                 else
7895                         psta->qos_option = 0;
7896
7897                 if (pmlmepriv->qospriv.qos_option == 0)
7898                         psta->qos_option = 0;
7899
7900
7901 #ifdef CONFIG_80211N_HT
7902                 /* chec 802.11n ht cap. */
7903                 if (WLAN_STA_HT & flags) {
7904                         psta->htpriv.ht_option = _TRUE;
7905                         psta->qos_option = 1;
7906                         _rtw_memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
7907                 } else
7908                         psta->htpriv.ht_option = _FALSE;
7909
7910                 if (pmlmepriv->htpriv.ht_option == _FALSE)
7911                         psta->htpriv.ht_option = _FALSE;
7912 #endif
7913
7914
7915                 update_sta_info_apmode(padapter, psta);
7916
7917
7918         } else
7919                 ret = -ENOMEM;
7920
7921         return ret;
7922
7923 }
7924
7925 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
7926 {
7927         _irqL irqL;
7928         int ret = 0;
7929         struct sta_info *psta = NULL;
7930         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7931         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7932         struct sta_priv *pstapriv = &padapter->stapriv;
7933
7934         RTW_INFO("rtw_del_sta=" MAC_FMT "\n", MAC_ARG(param->sta_addr));
7935
7936         if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != _TRUE)
7937                 return -EINVAL;
7938
7939         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7940             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7941             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7942                 return -EINVAL;
7943
7944         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7945         if (psta) {
7946                 u8 updated = _FALSE;
7947
7948                 /* RTW_INFO("free psta=%p, aid=%d\n", psta, psta->aid); */
7949
7950                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
7951                 if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
7952                         rtw_list_delete(&psta->asoc_list);
7953                         pstapriv->asoc_list_cnt--;
7954                         updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);
7955
7956                 }
7957                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
7958
7959                 associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
7960
7961                 psta = NULL;
7962
7963         } else {
7964                 RTW_INFO("rtw_del_sta(), sta has already been removed or never been added\n");
7965
7966                 /* ret = -1; */
7967         }
7968
7969
7970         return ret;
7971
7972 }
7973
7974 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
7975 {
7976         int ret = 0;
7977         struct sta_info *psta = NULL;
7978         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7979         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7980         struct sta_priv *pstapriv = &padapter->stapriv;
7981         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
7982         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
7983
7984         RTW_INFO("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
7985
7986         if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != _TRUE)
7987                 return -EINVAL;
7988
7989         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
7990             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
7991             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
7992                 return -EINVAL;
7993
7994         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
7995         if (psta) {
7996 #if 0
7997                 struct {
7998                         u16 aid;
7999                         u16 capability;
8000                         int flags;
8001                         u32 sta_set;
8002                         u8 tx_supp_rates[16];
8003                         u32 tx_supp_rates_len;
8004                         struct rtw_ieee80211_ht_cap ht_cap;
8005                         u64     rx_pkts;
8006                         u64     rx_bytes;
8007                         u64     rx_drops;
8008                         u64     tx_pkts;
8009                         u64     tx_bytes;
8010                         u64     tx_drops;
8011                 } get_sta;
8012 #endif
8013                 psta_data->aid = (u16)psta->aid;
8014                 psta_data->capability = psta->capability;
8015                 psta_data->flags = psta->flags;
8016
8017                 /*
8018                                 nonerp_set : BIT(0)
8019                                 no_short_slot_time_set : BIT(1)
8020                                 no_short_preamble_set : BIT(2)
8021                                 no_ht_gf_set : BIT(3)
8022                                 no_ht_set : BIT(4)
8023                                 ht_20mhz_set : BIT(5)
8024                 */
8025
8026                 psta_data->sta_set = ((psta->nonerp_set) |
8027                                       (psta->no_short_slot_time_set << 1) |
8028                                       (psta->no_short_preamble_set << 2) |
8029                                       (psta->no_ht_gf_set << 3) |
8030                                       (psta->no_ht_set << 4) |
8031                                       (psta->ht_20mhz_set << 5));
8032
8033                 psta_data->tx_supp_rates_len =  psta->bssratelen;
8034                 _rtw_memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
8035 #ifdef CONFIG_80211N_HT
8036                 _rtw_memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
8037 #endif /* CONFIG_80211N_HT */
8038                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
8039                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
8040                 psta_data->rx_drops = psta->sta_stats.rx_drops;
8041
8042                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
8043                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
8044                 psta_data->tx_drops = psta->sta_stats.tx_drops;
8045
8046
8047         } else
8048                 ret = -1;
8049
8050         return ret;
8051
8052 }
8053
8054 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
8055 {
8056         int ret = 0;
8057         struct sta_info *psta = NULL;
8058         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8059         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8060         struct sta_priv *pstapriv = &padapter->stapriv;
8061
8062         RTW_INFO("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
8063
8064         if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != _TRUE)
8065                 return -EINVAL;
8066
8067         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8068             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8069             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
8070                 return -EINVAL;
8071
8072         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
8073         if (psta) {
8074                 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
8075                         int wpa_ie_len;
8076                         int copy_len;
8077
8078                         wpa_ie_len = psta->wpa_ie[1];
8079
8080                         copy_len = ((wpa_ie_len + 2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len + 2);
8081
8082                         param->u.wpa_ie.len = copy_len;
8083
8084                         _rtw_memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
8085                 } else {
8086                         /* ret = -1; */
8087                         RTW_INFO("sta's wpa_ie is NONE\n");
8088                 }
8089         } else
8090                 ret = -1;
8091
8092         return ret;
8093
8094 }
8095
8096 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
8097 {
8098         int ret = 0;
8099         unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
8100         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8101         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8102         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8103         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8104         int ie_len;
8105
8106         RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
8107
8108         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8109                 return -EINVAL;
8110
8111         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
8112
8113
8114         if (pmlmepriv->wps_beacon_ie) {
8115                 rtw_mfree(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
8116                 pmlmepriv->wps_beacon_ie = NULL;
8117         }
8118
8119         if (ie_len > 0) {
8120                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
8121                 pmlmepriv->wps_beacon_ie_len = ie_len;
8122                 if (pmlmepriv->wps_beacon_ie == NULL) {
8123                         RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
8124                         return -EINVAL;
8125                 }
8126
8127                 _rtw_memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
8128
8129                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE);
8130
8131                 pmlmeext->bstart_bss = _TRUE;
8132
8133         }
8134
8135
8136         return ret;
8137
8138 }
8139
8140 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
8141 {
8142         int ret = 0;
8143         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8144         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8145         int ie_len;
8146
8147         RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
8148
8149         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8150                 return -EINVAL;
8151
8152         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
8153
8154
8155         if (pmlmepriv->wps_probe_resp_ie) {
8156                 rtw_mfree(pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
8157                 pmlmepriv->wps_probe_resp_ie = NULL;
8158         }
8159
8160         if (ie_len > 0) {
8161                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
8162                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
8163                 if (pmlmepriv->wps_probe_resp_ie == NULL) {
8164                         RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
8165                         return -EINVAL;
8166                 }
8167                 _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
8168         }
8169
8170
8171         return ret;
8172
8173 }
8174
8175 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
8176 {
8177         int ret = 0;
8178         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8179         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8180         int ie_len;
8181
8182         RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
8183
8184         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8185                 return -EINVAL;
8186
8187         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
8188
8189
8190         if (pmlmepriv->wps_assoc_resp_ie) {
8191                 rtw_mfree(pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
8192                 pmlmepriv->wps_assoc_resp_ie = NULL;
8193         }
8194
8195         if (ie_len > 0) {
8196                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
8197                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
8198                 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
8199                         RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
8200                         return -EINVAL;
8201                 }
8202
8203                 _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
8204         }
8205
8206
8207         return ret;
8208
8209 }
8210
8211 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
8212 {
8213         int ret = 0;
8214         _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
8215         struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
8216         struct mlme_ext_priv    *mlmeext = &(adapter->mlmeextpriv);
8217         struct mlme_ext_info    *mlmeinfo = &(mlmeext->mlmext_info);
8218         int ie_len;
8219         u8 *ssid_ie;
8220         char ssid[NDIS_802_11_LENGTH_SSID + 1];
8221         sint ssid_len = 0;
8222         u8 ignore_broadcast_ssid;
8223
8224         if (check_fwstate(mlmepriv, WIFI_AP_STATE) != _TRUE)
8225                 return -EPERM;
8226
8227         if (param->u.bcn_ie.reserved[0] != 0xea)
8228                 return -EINVAL;
8229
8230         mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
8231
8232         ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
8233         ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
8234
8235         if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
8236                 WLAN_BSSID_EX *pbss_network = &mlmepriv->cur_network.network;
8237                 WLAN_BSSID_EX *pbss_network_ext = &mlmeinfo->network;
8238
8239                 _rtw_memcpy(ssid, ssid_ie + 2, ssid_len);
8240                 ssid[ssid_len] = 0x0;
8241
8242                 if (0)
8243                         RTW_INFO(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
8244                                  ssid, ssid_len,
8245                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
8246                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
8247
8248                 _rtw_memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
8249                 pbss_network->Ssid.SsidLength = ssid_len;
8250                 _rtw_memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
8251                 pbss_network_ext->Ssid.SsidLength = ssid_len;
8252
8253                 if (0)
8254                         RTW_INFO(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
8255                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
8256                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
8257         }
8258
8259         RTW_INFO(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
8260                  ignore_broadcast_ssid, ssid, ssid_len);
8261
8262         return ret;
8263 }
8264
8265 #if CONFIG_RTW_MACADDR_ACL
8266 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
8267 {
8268         int ret = 0;
8269         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8270         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8271
8272         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8273                 return -EINVAL;
8274
8275         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8276             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8277             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
8278                 return -EINVAL;
8279
8280         ret = rtw_acl_remove_sta(padapter, param->sta_addr);
8281
8282         return ret;
8283
8284 }
8285
8286 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
8287 {
8288         int ret = 0;
8289         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8290         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8291
8292         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8293                 return -EINVAL;
8294
8295         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8296             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8297             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
8298                 return -EINVAL;
8299
8300         ret = rtw_acl_add_sta(padapter, param->sta_addr);
8301
8302         return ret;
8303
8304 }
8305
8306 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
8307 {
8308         int ret = 0;
8309         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8310         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8311
8312         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8313                 return -EINVAL;
8314
8315         rtw_set_macaddr_acl(padapter, param->u.mlme.command);
8316
8317         return ret;
8318 }
8319 #endif /* CONFIG_RTW_MACADDR_ACL */
8320
8321 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
8322 {
8323         struct ieee_param *param;
8324         int ret = 0;
8325         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8326
8327         /* RTW_INFO("%s\n", __FUNCTION__); */
8328
8329         /*
8330         * this function is expect to call in master mode, which allows no power saving
8331         * so, we just check hw_init_completed
8332         */
8333
8334         if (!rtw_is_hw_init_completed(padapter)) {
8335                 ret = -EPERM;
8336                 goto out;
8337         }
8338
8339
8340         /* if (p->length < sizeof(struct ieee_param) || !p->pointer){ */
8341         if (!p->pointer) {
8342                 ret = -EINVAL;
8343                 goto out;
8344         }
8345
8346         param = (struct ieee_param *)rtw_malloc(p->length);
8347         if (param == NULL) {
8348                 ret = -ENOMEM;
8349                 goto out;
8350         }
8351
8352         if (copy_from_user(param, p->pointer, p->length)) {
8353                 rtw_mfree((u8 *)param, p->length);
8354                 ret = -EFAULT;
8355                 goto out;
8356         }
8357
8358         /* RTW_INFO("%s, cmd=%d\n", __FUNCTION__, param->cmd); */
8359
8360         switch (param->cmd) {
8361         case RTL871X_HOSTAPD_FLUSH:
8362
8363                 ret = rtw_hostapd_sta_flush(dev);
8364
8365                 break;
8366
8367         case RTL871X_HOSTAPD_ADD_STA:
8368
8369                 ret = rtw_add_sta(dev, param);
8370
8371                 break;
8372
8373         case RTL871X_HOSTAPD_REMOVE_STA:
8374
8375                 ret = rtw_del_sta(dev, param);
8376
8377                 break;
8378
8379         case RTL871X_HOSTAPD_SET_BEACON:
8380
8381                 ret = rtw_set_beacon(dev, param, p->length);
8382
8383                 break;
8384
8385         case RTL871X_SET_ENCRYPTION:
8386
8387                 ret = rtw_set_encryption(dev, param, p->length);
8388
8389                 break;
8390
8391         case RTL871X_HOSTAPD_GET_WPAIE_STA:
8392
8393                 ret = rtw_get_sta_wpaie(dev, param);
8394
8395                 break;
8396
8397         case RTL871X_HOSTAPD_SET_WPS_BEACON:
8398
8399                 ret = rtw_set_wps_beacon(dev, param, p->length);
8400
8401                 break;
8402
8403         case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
8404
8405                 ret = rtw_set_wps_probe_resp(dev, param, p->length);
8406
8407                 break;
8408
8409         case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
8410
8411                 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
8412
8413                 break;
8414
8415         case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
8416
8417                 ret = rtw_set_hidden_ssid(dev, param, p->length);
8418
8419                 break;
8420
8421         case RTL871X_HOSTAPD_GET_INFO_STA:
8422
8423                 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
8424
8425                 break;
8426
8427 #if CONFIG_RTW_MACADDR_ACL
8428         case RTL871X_HOSTAPD_SET_MACADDR_ACL:
8429                 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
8430                 break;
8431         case RTL871X_HOSTAPD_ACL_ADD_STA:
8432                 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
8433                 break;
8434         case RTL871X_HOSTAPD_ACL_REMOVE_STA:
8435                 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
8436                 break;
8437 #endif /* CONFIG_RTW_MACADDR_ACL */
8438
8439         default:
8440                 RTW_INFO("Unknown hostapd request: %d\n", param->cmd);
8441                 ret = -EOPNOTSUPP;
8442                 break;
8443
8444         }
8445
8446         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
8447                 ret = -EFAULT;
8448
8449
8450         rtw_mfree((u8 *)param, p->length);
8451
8452 out:
8453
8454         return ret;
8455
8456 }
8457 #endif
8458
8459 static int rtw_wx_set_priv(struct net_device *dev,
8460                            struct iw_request_info *info,
8461                            union iwreq_data *awrq,
8462                            char *extra)
8463 {
8464
8465 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
8466         char *ext_dbg;
8467 #endif
8468
8469         int ret = 0;
8470         int len = 0;
8471         char *ext;
8472         int i;
8473
8474         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8475         struct iw_point *dwrq = (struct iw_point *)awrq;
8476
8477         /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n")); */
8478         if (dwrq->length == 0)
8479                 return -EFAULT;
8480
8481         len = dwrq->length;
8482         ext = rtw_vmalloc(len);
8483         if (!ext)
8484                 return -ENOMEM;
8485
8486         if (copy_from_user(ext, dwrq->pointer, len)) {
8487                 rtw_vmfree(ext, len);
8488                 return -EFAULT;
8489         }
8490
8491
8492         /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, */
8493         /*       ("rtw_wx_set_priv: %s req=%s\n", */
8494         /*        dev->name, ext)); */
8495
8496 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
8497         ext_dbg = rtw_vmalloc(len);
8498         if (!ext_dbg) {
8499                 rtw_vmfree(ext, len);
8500                 return -ENOMEM;
8501         }
8502
8503         _rtw_memcpy(ext_dbg, ext, len);
8504 #endif
8505
8506         /* added for wps2.0 @20110524 */
8507         if (dwrq->flags == 0x8766 && len > 8) {
8508                 u32 cp_sz;
8509                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8510                 u8 *probereq_wpsie = ext;
8511                 int probereq_wpsie_len = len;
8512                 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
8513
8514                 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
8515                     (_rtw_memcmp(&probereq_wpsie[2], wps_oui, 4) == _TRUE)) {
8516                         cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
8517
8518                         if (pmlmepriv->wps_probe_req_ie) {
8519                                 u32 free_len = pmlmepriv->wps_probe_req_ie_len;
8520                                 pmlmepriv->wps_probe_req_ie_len = 0;
8521                                 rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
8522                                 pmlmepriv->wps_probe_req_ie = NULL;
8523                         }
8524
8525                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
8526                         if (pmlmepriv->wps_probe_req_ie == NULL) {
8527                                 printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
8528                                 ret =  -EINVAL;
8529                                 goto FREE_EXT;
8530
8531                         }
8532
8533                         _rtw_memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
8534                         pmlmepriv->wps_probe_req_ie_len = cp_sz;
8535
8536                 }
8537
8538                 goto FREE_EXT;
8539
8540         }
8541
8542         if (len >= WEXT_CSCAN_HEADER_SIZE
8543             && _rtw_memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
8544            ) {
8545                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
8546                 goto FREE_EXT;
8547         }
8548
8549 #ifdef CONFIG_ANDROID
8550         /* RTW_INFO("rtw_wx_set_priv: %s req=%s\n", dev->name, ext); */
8551
8552         i = rtw_android_cmdstr_to_num(ext);
8553
8554         switch (i) {
8555         case ANDROID_WIFI_CMD_START:
8556                 indicate_wx_custom_event(padapter, "START");
8557                 break;
8558         case ANDROID_WIFI_CMD_STOP:
8559                 indicate_wx_custom_event(padapter, "STOP");
8560                 break;
8561         case ANDROID_WIFI_CMD_RSSI: {
8562                 struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
8563                 struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
8564
8565                 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
8566                         sprintf(ext, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
8567                 else
8568                         sprintf(ext, "OK");
8569         }
8570         break;
8571         case ANDROID_WIFI_CMD_LINKSPEED: {
8572                 u16 mbps = rtw_get_cur_max_rate(padapter) / 10;
8573                 sprintf(ext, "LINKSPEED %d", mbps);
8574         }
8575         break;
8576         case ANDROID_WIFI_CMD_MACADDR:
8577                 sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
8578                 break;
8579         case ANDROID_WIFI_CMD_SCAN_ACTIVE: {
8580                 /* rtw_set_scan_mode(padapter, SCAN_ACTIVE); */
8581                 sprintf(ext, "OK");
8582         }
8583         break;
8584         case ANDROID_WIFI_CMD_SCAN_PASSIVE: {
8585                 /* rtw_set_scan_mode(padapter, SCAN_PASSIVE); */
8586                 sprintf(ext, "OK");
8587         }
8588         break;
8589
8590         case ANDROID_WIFI_CMD_COUNTRY: {
8591                 char country_code[10];
8592                 sscanf(ext, "%*s %s", country_code);
8593                 rtw_set_country(padapter, country_code);
8594                 sprintf(ext, "OK");
8595         }
8596         break;
8597         default:
8598 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
8599                 RTW_INFO("%s: %s unknowned req=%s\n", __FUNCTION__,
8600                          dev->name, ext_dbg);
8601 #endif
8602
8603                 sprintf(ext, "OK");
8604
8605         }
8606
8607         if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext) + 1))))
8608                 ret = -EFAULT;
8609
8610 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
8611         RTW_INFO("%s: %s req=%s rep=%s dwrq->length=%d, strlen(ext)+1=%d\n", __FUNCTION__,
8612                 dev->name, ext_dbg , ext, dwrq->length, (u16)(strlen(ext) + 1));
8613 #endif
8614 #endif /* end of CONFIG_ANDROID */
8615
8616
8617 FREE_EXT:
8618
8619         rtw_vmfree(ext, len);
8620 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
8621         rtw_vmfree(ext_dbg, len);
8622 #endif
8623
8624         /* RTW_INFO("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret=%d\n",  */
8625         /*              dev->name, ret); */
8626
8627         return ret;
8628
8629 }
8630 #ifdef CONFIG_WOWLAN
8631 static int rtw_wowlan_ctrl(struct net_device *dev,
8632                            struct iw_request_info *info,
8633                            union iwreq_data *wrqu, char *extra)
8634 {
8635         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8636         struct wowlan_ioctl_param poidparam;
8637         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
8638         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8639         struct sta_info *psta = NULL;
8640         int ret = 0;
8641         u32 start_time = rtw_get_current_time();
8642         poidparam.subcode = 0;
8643
8644         RTW_INFO("+rtw_wowlan_ctrl: %s\n", extra);
8645
8646         if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
8647             check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
8648 #ifdef CONFIG_PNO_SUPPORT
8649                 pwrctrlpriv->wowlan_pno_enable = _TRUE;
8650 #else
8651                 RTW_INFO("[%s] WARNING: Please Connect With AP First!!\n", __func__);
8652                 goto _rtw_wowlan_ctrl_exit_free;
8653 #endif /* CONFIG_PNO_SUPPORT */
8654         }
8655
8656         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
8657                 rtw_scan_abort(padapter);
8658
8659         if (_rtw_memcmp(extra, "enable", 6))
8660
8661
8662                 rtw_suspend_common(padapter);
8663
8664         else if (_rtw_memcmp(extra, "disable", 7)) {
8665 #ifdef CONFIG_USB_HCI
8666                 RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
8667                 RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
8668 #endif
8669                 rtw_resume_common(padapter);
8670
8671 #ifdef CONFIG_PNO_SUPPORT
8672                 pwrctrlpriv->wowlan_pno_enable = _FALSE;
8673 #endif /* CONFIG_PNO_SUPPORT */
8674
8675         } else {
8676                 RTW_INFO("[%s] Invalid Parameter.\n", __func__);
8677                 goto _rtw_wowlan_ctrl_exit_free;
8678         }
8679         /* mutex_lock(&ioctl_mutex); */
8680 _rtw_wowlan_ctrl_exit_free:
8681         RTW_INFO("-rtw_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
8682         RTW_PRINT("%s in %d ms\n", __func__,
8683                   rtw_get_passing_time_ms(start_time));
8684 _rtw_wowlan_ctrl_exit:
8685         return ret;
8686 }
8687
8688 /*
8689  * IP filter This pattern if for a frame containing a ip packet:
8690  * AA:AA:AA:AA:AA:AA:BB:BB:BB:BB:BB:BB:CC:CC:DD:-:-:-:-:-:-:-:-:EE:-:-:FF:FF:FF:FF:GG:GG:GG:GG:HH:HH:II:II
8691  *
8692  * A: Ethernet destination address
8693  * B: Ethernet source address
8694  * C: Ethernet protocol type
8695  * D: IP header VER+Hlen, use: 0x45 (4 is for ver 4, 5 is for len 20)
8696  * E: IP protocol
8697  * F: IP source address ( 192.168.0.4: C0:A8:00:2C )
8698  * G: IP destination address ( 192.168.0.4: C0:A8:00:2C )
8699  * H: Source port (1024: 04:00)
8700  * I: Destination port (1024: 04:00)
8701  */
8702
8703 static int rtw_wowlan_set_pattern(struct net_device *dev,
8704                                   struct iw_request_info *info,
8705                                   union iwreq_data *wrqu, char *extra)
8706 {
8707         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8708         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
8709         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8710         struct wowlan_ioctl_param poidparam;
8711         int ret = 0, len = 0, i = 0;
8712         u32 start_time = rtw_get_current_time();
8713         u8 input[wrqu->data.length];
8714         u8 index = 0;
8715
8716         poidparam.subcode = 0;
8717
8718         if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
8719             check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
8720                 ret = -EFAULT;
8721                 RTW_INFO("Please Connect With AP First!!\n");
8722                 goto _rtw_wowlan_set_pattern_exit;
8723         }
8724
8725         if (wrqu->data.length <= 0) {
8726                 ret = -EFAULT;
8727                 RTW_INFO("ERROR: parameter length <= 0\n");
8728                 goto _rtw_wowlan_set_pattern_exit;
8729         } else {
8730                 /* set pattern */
8731                 if (copy_from_user(input,
8732                                    wrqu->data.pointer, wrqu->data.length))
8733                         return -EFAULT;
8734                 /* leave PS first */
8735                 rtw_ps_deny(padapter, PS_DENY_IOCTL);
8736                 LeaveAllPowerSaveModeDirect(padapter);
8737                 if (strncmp(input, "pattern=", 8) == 0) {
8738                         if (pwrpriv->wowlan_pattern_idx >= MAX_WKFM_NUM) {
8739                                 RTW_INFO("WARNING: priv-pattern is full(idx: %d)\n",
8740                                          pwrpriv->wowlan_pattern_idx);
8741                                 RTW_INFO("WARNING: please clean priv-pattern first\n");
8742                                 ret = -EINVAL;
8743                                 goto _rtw_wowlan_set_pattern_exit;
8744                         } else {
8745                                 index = pwrpriv->wowlan_pattern_idx;
8746                                 ret = rtw_wowlan_parser_pattern_cmd(input,
8747                                             pwrpriv->patterns[index].content,
8748                                             &pwrpriv->patterns[index].len,
8749                                             pwrpriv->patterns[index].mask);
8750
8751                                 if (ret == _TRUE)
8752                                         pwrpriv->wowlan_pattern_idx++;
8753                         }
8754                 } else if (strncmp(input, "clean", 5) == 0) {
8755                         poidparam.subcode = WOWLAN_PATTERN_CLEAN;
8756                         rtw_hal_set_hwreg(padapter,
8757                                           HW_VAR_WOWLAN, (u8 *)&poidparam);
8758                 } else if (strncmp(input, "show", 4) == 0) {
8759                         for (i = 0 ; i < MAX_WKFM_NUM ; i++) {
8760                                 RTW_INFO("=======[%d]=======\n", i);
8761                                 rtw_read_from_frame_mask(padapter, i);
8762                         }
8763
8764                         RTW_INFO("********[RTK priv-patterns]*********\n");
8765                         for (i = 0 ; i < MAX_WKFM_NUM ; i++)
8766                                 rtw_dump_priv_pattern(padapter, i);
8767                 } else {
8768                         RTW_INFO("ERROR: incorrect parameter!\n");
8769                         ret = -EINVAL;
8770                 }
8771                 rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
8772         }
8773 _rtw_wowlan_set_pattern_exit:
8774         return ret;
8775 }
8776 #endif /* CONFIG_WOWLAN */
8777
8778 #ifdef CONFIG_AP_WOWLAN
8779 static int rtw_ap_wowlan_ctrl(struct net_device *dev,
8780                               struct iw_request_info *info,
8781                               union iwreq_data *wrqu, char *extra)
8782 {
8783         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8784         struct wowlan_ioctl_param poidparam;
8785         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
8786         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8787         struct sta_info *psta = NULL;
8788         int ret = 0;
8789         u32 start_time = rtw_get_current_time();
8790         poidparam.subcode = 0;
8791
8792         RTW_INFO("+rtw_ap_wowlan_ctrl: %s\n", extra);
8793
8794         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
8795                 RTW_INFO("[%s] It is not AP mode!!\n", __func__);
8796                 goto _rtw_ap_wowlan_ctrl_exit_free;
8797         }
8798
8799         if (_rtw_memcmp(extra, "enable", 6)) {
8800
8801                 pwrctrlpriv->wowlan_ap_mode = _TRUE;
8802
8803                 rtw_suspend_common(padapter);
8804         } else if (_rtw_memcmp(extra, "disable", 7)) {
8805 #ifdef CONFIG_USB_HCI
8806                 RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
8807                 RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
8808 #endif
8809                 rtw_resume_common(padapter);
8810         } else {
8811                 RTW_INFO("[%s] Invalid Parameter.\n", __func__);
8812                 goto _rtw_ap_wowlan_ctrl_exit_free;
8813         }
8814         /* mutex_lock(&ioctl_mutex); */
8815 _rtw_ap_wowlan_ctrl_exit_free:
8816         RTW_INFO("-rtw_ap_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
8817         RTW_PRINT("%s in %d ms\n", __func__,
8818                   rtw_get_passing_time_ms(start_time));
8819 _rtw_ap_wowlan_ctrl_exit:
8820         return ret;
8821 }
8822 #endif /* CONFIG_AP_WOWLAN */
8823
8824 static int rtw_pm_set(struct net_device *dev,
8825                       struct iw_request_info *info,
8826                       union iwreq_data *wrqu, char *extra)
8827 {
8828         int ret = 0;
8829         unsigned        mode = 0;
8830         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8831
8832         RTW_INFO("[%s] extra = %s\n", __FUNCTION__, extra);
8833
8834         if (_rtw_memcmp(extra, "lps=", 4)) {
8835                 sscanf(extra + 4, "%u", &mode);
8836                 ret = rtw_pm_set_lps(padapter, mode);
8837         } else if (_rtw_memcmp(extra, "ips=", 4)) {
8838                 sscanf(extra + 4, "%u", &mode);
8839                 ret = rtw_pm_set_ips(padapter, mode);
8840         } else
8841                 ret = -EINVAL;
8842
8843         return ret;
8844 }
8845 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
8846
8847 int rtw_vendor_ie_get_raw_data(struct net_device *dev, u32 vendor_ie_num,
8848                                                            char *extra, u32 length)
8849 {
8850         int j;
8851         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8852         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8853         u32 vendor_ie_mask = 0;
8854         char *pstring;
8855
8856         if (vendor_ie_num >= WLAN_MAX_VENDOR_IE_NUM) {
8857                 RTW_INFO("[%s] only support %d vendor ie\n", __func__ ,
8858                                  WLAN_MAX_VENDOR_IE_NUM);
8859                 return -EFAULT;
8860         }
8861
8862         if (pmlmepriv->vendor_ielen[vendor_ie_num] == 0) {
8863                 RTW_INFO("[%s]  Fail, vendor_ie_num: %d is not set\n", __func__,
8864                                  vendor_ie_num);
8865                 return -EFAULT;
8866         }
8867
8868         if (length < 2 * pmlmepriv->vendor_ielen[vendor_ie_num] + 5) {
8869                 RTW_INFO("[%s]  Fail, buffer size is too small\n", __func__);
8870                 return -EFAULT;
8871         }
8872
8873         vendor_ie_mask = pmlmepriv->vendor_ie_mask[vendor_ie_num];
8874         _rtw_memset(extra, 0, length);
8875
8876         pstring = extra;
8877         pstring += sprintf(pstring, "%d,%x,", vendor_ie_num, vendor_ie_mask);
8878
8879         for (j = 0; j < pmlmepriv->vendor_ielen[vendor_ie_num]; j++)
8880                 pstring += sprintf(pstring, "%02x", pmlmepriv->vendor_ie[vendor_ie_num][j]);
8881
8882         length = pstring - extra;
8883         return length;
8884 }
8885
8886 int rtw_vendor_ie_get_data(struct net_device *dev, int vendor_ie_num, char *extra)
8887 {
8888         int j;
8889         char *pstring;
8890         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8891         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8892         u32 vendor_ie_mask = 0;
8893         __u16 length = 0;
8894
8895         vendor_ie_mask = pmlmepriv->vendor_ie_mask[vendor_ie_num];
8896         pstring = extra;
8897         pstring += sprintf(pstring , "\nVendor IE num %d , Mask:%x " , vendor_ie_num , vendor_ie_mask);
8898
8899         if (vendor_ie_mask & WIFI_BEACON_VENDOR_IE_BIT)
8900                 pstring += sprintf(pstring , "[Beacon]");
8901         if (vendor_ie_mask & WIFI_PROBEREQ_VENDOR_IE_BIT)
8902                 pstring += sprintf(pstring , "[Probe Req]");
8903         if (vendor_ie_mask & WIFI_PROBERESP_VENDOR_IE_BIT)
8904                 pstring += sprintf(pstring , "[Probe Resp]");
8905         if (vendor_ie_mask & WIFI_ASSOCREQ_VENDOR_IE_BIT)
8906                 pstring += sprintf(pstring , "[Assoc Req]");
8907         if (vendor_ie_mask & WIFI_ASSOCRESP_VENDOR_IE_BIT)
8908                 pstring += sprintf(pstring , "[Assoc Resp]");
8909
8910         pstring += sprintf(pstring , "\nVendor IE:\n");
8911         for (j = 0 ; j < pmlmepriv->vendor_ielen[vendor_ie_num]  ; j++)
8912                 pstring += sprintf(pstring , "%02x" , pmlmepriv->vendor_ie[vendor_ie_num][j]);
8913
8914         length = pstring - extra;
8915         return length;
8916
8917 }
8918
8919 int rtw_vendor_ie_get(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
8920 {
8921         int ret = 0, vendor_ie_num = 0, cmdlen;
8922         struct iw_point *p;
8923         u8 *ptmp;
8924
8925         p = &wrqu->data;
8926         cmdlen = p->length;
8927         if (0 == cmdlen)
8928                 return -EINVAL;
8929
8930         ptmp = (u8 *)rtw_malloc(cmdlen);
8931         if (NULL == ptmp)
8932                 return -ENOMEM;
8933
8934         if (copy_from_user(ptmp, p->pointer, cmdlen)) {
8935                 ret = -EFAULT;
8936                 goto exit;
8937         }
8938         ret = sscanf(ptmp , "%d", &vendor_ie_num);
8939         if (vendor_ie_num > WLAN_MAX_VENDOR_IE_NUM - 1) {
8940                 ret = -EFAULT;
8941                 goto exit;
8942         }
8943
8944         wrqu->data.length = rtw_vendor_ie_get_data(dev, vendor_ie_num, extra);
8945
8946 exit:
8947         rtw_mfree(ptmp, cmdlen);
8948
8949         return 0;
8950 }
8951
8952 int rtw_vendor_ie_set(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
8953 {
8954         int ret = 0, i , len = 0 , totoal_ie_len = 0 , total_ie_len_byte = 0;
8955         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8956         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8957         u32 vendor_ie_mask = 0;
8958         u32 vendor_ie_num = 0;
8959         u32 id, elen;
8960
8961         ret = sscanf(extra, "%d,%x,%*s", &vendor_ie_num , &vendor_ie_mask);
8962         if (strrchr(extra , ','))
8963                 extra = strrchr(extra , ',') + 1;
8964         else
8965                 return -EINVAL;
8966         totoal_ie_len = strlen(extra);
8967         RTW_INFO("[%s] vendor_ie_num = %d , vendor_ie_mask = %x , vendor_ie = %s , len = %d\n", __func__ , vendor_ie_num , vendor_ie_mask , extra  , totoal_ie_len);
8968
8969         if (vendor_ie_num  > WLAN_MAX_VENDOR_IE_NUM - 1) {
8970                 RTW_INFO("[%s] only support %d vendor ie\n", __func__ , WLAN_MAX_VENDOR_IE_NUM);
8971                 return -EFAULT;
8972         }
8973
8974         if (totoal_ie_len > WLAN_MAX_VENDOR_IE_LEN) {
8975                 RTW_INFO("[%s] Fail , not support ie length extend %d\n", __func__ , WLAN_MAX_VENDOR_IE_LEN);
8976                 return -EFAULT;
8977         }
8978
8979         if (vendor_ie_mask == 0) {
8980                 RTW_INFO("[%s] Clear vendor_ie_num %d group\n", __func__ , vendor_ie_num);
8981                 goto _clear_path;
8982         }
8983
8984         if (totoal_ie_len % 2 != 0) {
8985                 RTW_INFO("[%s]  Fail , IE length = %zu is odd\n" , __func__ , strlen(extra));
8986                 return -EFAULT;
8987         }
8988
8989         if (totoal_ie_len > 0) {
8990                 for (i = 0  ; i < strlen(extra) ; i += 2) {
8991                         pmlmepriv->vendor_ie[vendor_ie_num][len] = key_2char2num(extra[i] , extra[i + 1]);
8992                         if (len == 0) {
8993                                 id = pmlmepriv->vendor_ie[vendor_ie_num][len];
8994                                 if (id != WLAN_EID_VENDOR_SPECIFIC) {
8995                                         RTW_INFO("[%s] Fail , VENDOR SPECIFIC IE ID \"%x\" was not correct\n", __func__ , id);
8996                                         goto _clear_path;
8997                                 }
8998                         } else if (len == 1) {
8999                                 total_ie_len_byte = (totoal_ie_len / 2) - 2;
9000                                 elen = pmlmepriv->vendor_ie[vendor_ie_num][len];
9001                                 if (elen != total_ie_len_byte) {
9002                                         RTW_INFO("[%s] Fail , Input IE length = \"%d\"(hex:%x) bytes , not match input total IE context length \"%d\" bytes\n", __func__ , elen , elen ,
9003                                                  total_ie_len_byte);
9004                                         goto _clear_path;
9005                                 }
9006                         }
9007                         len++;
9008                 }
9009                 pmlmepriv->vendor_ielen[vendor_ie_num] = len;
9010         } else
9011                 pmlmepriv->vendor_ielen[vendor_ie_num] = 0;
9012
9013
9014
9015         if (vendor_ie_mask & WIFI_BEACON_VENDOR_IE_BIT)
9016                 RTW_INFO("[%s] Beacon append vendor ie\n", __func__);
9017         if (vendor_ie_mask & WIFI_PROBEREQ_VENDOR_IE_BIT)
9018                 RTW_INFO("[%s] Probe Req append vendor ie\n", __func__);
9019         if (vendor_ie_mask & WIFI_PROBERESP_VENDOR_IE_BIT)
9020                 RTW_INFO("[%s] Probe Resp  append vendor ie\n", __func__);
9021         if (vendor_ie_mask & WIFI_ASSOCREQ_VENDOR_IE_BIT)
9022                 RTW_INFO("[%s] Assoc Req append vendor ie\n", __func__);
9023         if (vendor_ie_mask & WIFI_ASSOCRESP_VENDOR_IE_BIT)
9024                 RTW_INFO("[%s] Assoc Resp append vendor ie\n", __func__);
9025
9026         pmlmepriv->vendor_ie_mask[vendor_ie_num] = vendor_ie_mask;
9027
9028         return ret;
9029
9030 _clear_path:
9031         _rtw_memset(pmlmepriv->vendor_ie[vendor_ie_num] , 0 , sizeof(u32) * WLAN_MAX_VENDOR_IE_LEN);
9032         pmlmepriv->vendor_ielen[vendor_ie_num] = 0;
9033         pmlmepriv->vendor_ie_mask[vendor_ie_num] = 0;
9034         return -EFAULT;
9035 }
9036 #endif
9037
9038 static int rtw_mp_efuse_get(struct net_device *dev,
9039                             struct iw_request_info *info,
9040                             union iwreq_data *wdata, char *extra)
9041 {
9042         PADAPTER padapter = rtw_netdev_priv(dev);
9043         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
9044
9045         PEFUSE_HAL pEfuseHal;
9046         struct iw_point *wrqu;
9047
9048         u8      *PROMContent = pHalData->efuse_eeprom_data;
9049         u8 ips_mode = IPS_NUM; /* init invalid value */
9050         u8 lps_mode = PS_MODE_NUM; /* init invalid value */
9051         struct pwrctrl_priv *pwrctrlpriv ;
9052         u8 *data = NULL;
9053         u8 *rawdata = NULL;
9054         char *pch, *ptmp, *token, *tmp[3] = {0x00, 0x00, 0x00};
9055         u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
9056         u16 max_available_len = 0, raw_cursize = 0, raw_maxsize = 0;
9057         int err;
9058         u8 BTStatus;
9059 #ifdef CONFIG_IOL
9060         u8 org_fw_iol = padapter->registrypriv.fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
9061 #endif
9062
9063         wrqu = (struct iw_point *)wdata;
9064         pwrctrlpriv = adapter_to_pwrctl(padapter);
9065         pEfuseHal = &pHalData->EfuseHal;
9066
9067         err = 0;
9068         data = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
9069         if (data == NULL) {
9070                 err = -ENOMEM;
9071                 goto exit;
9072         }
9073         rawdata = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
9074         if (rawdata == NULL) {
9075                 err = -ENOMEM;
9076                 goto exit;
9077         }
9078
9079         if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
9080                 err = -EFAULT;
9081                 goto exit;
9082         }
9083 #ifdef CONFIG_LPS
9084         lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
9085         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
9086 #endif
9087
9088 #ifdef CONFIG_IPS
9089         ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
9090         rtw_pm_set_ips(padapter, IPS_NONE);
9091 #endif
9092
9093         pch = extra;
9094         RTW_INFO("%s: in=%s\n", __FUNCTION__, extra);
9095
9096         i = 0;
9097         /* mac 16 "00e04c871200" rmap,00,2 */
9098         while ((token = strsep(&pch, ",")) != NULL) {
9099                 if (i > 2)
9100                         break;
9101                 tmp[i] = token;
9102                 i++;
9103         }
9104 #ifdef CONFIG_IOL
9105         padapter->registrypriv.fw_iol = 0;/* 0:Disable, 1:enable, 2:by usb speed */
9106 #endif
9107
9108         if (strcmp(tmp[0], "status") == 0) {
9109                 sprintf(extra, "Load File efuse=%s,Load File MAC=%s"
9110                         , pHalData->efuse_file_status == EFUSE_FILE_FAILED ? "FAIL" : "OK"
9111                         , pHalData->macaddr_file_status == MACADDR_FILE_FAILED ? "FAIL" : "OK"
9112                        );
9113                 goto exit;
9114         } else if (strcmp(tmp[0], "drvmap") == 0) {
9115                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, _FALSE);
9116
9117                 sprintf(extra, "\n");
9118                 for (i = 0; i < mapLen; i += 16) {
9119                         /*RTW_INFO("0x%02x\t", i);*/
9120                         sprintf(extra, "%s0x%02x\t", extra, i);
9121                         for (j = 0; j < 8; j++) {
9122                                 /*                              RTW_INFO("%02X ", data[i+j]); */
9123                                 sprintf(extra, "%s%02X ", extra, PROMContent[i + j]);
9124                         }
9125                         /*                      RTW_INFO("\t"); */
9126                         sprintf(extra, "%s\t", extra);
9127                         for (; j < 16; j++) {
9128                                 /*                              RTW_INFO("%02X ", data[i+j]); */
9129                                 sprintf(extra, "%s%02X ", extra, PROMContent[i + j]);
9130                         }
9131                         /*                      RTW_INFO("\n"); */
9132                         sprintf(extra, "%s\n", extra);
9133                 }
9134                 /*              RTW_INFO("\n"); */
9135         } else if (strcmp(tmp[0], "realmap") == 0) {
9136                 static u8 order = 0;
9137                 u8 *efuse;
9138                 u32 shift, cnt;
9139                 u32 blksz = 0x200; /* The size of one time show, default 512 */
9140
9141                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapLen, _FALSE);
9142                 efuse = pEfuseHal->fakeEfuseInitMap;
9143                 if (rtw_efuse_mask_map_read(padapter, 0, mapLen, efuse) == _FAIL) {
9144                         RTW_INFO("%s: read realmap Fail!!\n", __FUNCTION__);
9145                         err = -EFAULT;
9146                         goto exit;
9147                 }
9148
9149 #if 0
9150                 RTW_INFO("OFFSET\tVALUE(hex)\n");
9151                 for (i = 0; i < mapLen; i += 16) {
9152                         RTW_INFO("0x%02x\t", i);
9153                         for (j = 0; j < 8; j++)
9154                                 RTW_INFO("%02X ", efuse[i + j]);
9155                         RTW_INFO("\t");
9156                         for (; j < 16; j++)
9157                                 RTW_INFO("%02X ", efuse[i + j]);
9158                         RTW_INFO("\n");
9159                 }
9160                 RTW_INFO("\n");
9161 #endif
9162
9163                 shift = blksz * order;
9164                 efuse += shift;
9165                 cnt = mapLen - shift;
9166                 if (cnt > blksz) {
9167                         cnt = blksz;
9168                         order++;
9169                 } else
9170                         order = 0;
9171
9172                 sprintf(extra, "\n");
9173                 for (i = 0; i < cnt; i += 16) {
9174                         sprintf(extra, "%s0x%02x\t", extra, shift + i);
9175                         for (j = 0; j < 8; j++)
9176                                 sprintf(extra, "%s%02X ", extra, efuse[i + j]);
9177                         sprintf(extra, "%s\t", extra);
9178                         for (; j < 16; j++)
9179                                 sprintf(extra, "%s%02X ", extra, efuse[i + j]);
9180                         sprintf(extra, "%s\n", extra);
9181                 }
9182                 if ((shift + cnt) < mapLen)
9183                         sprintf(extra, "%s\t...more\n", extra);
9184         } else if (strcmp(tmp[0], "rmap") == 0) {
9185                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9186                         RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
9187                         err = -EINVAL;
9188                         goto exit;
9189                 }
9190
9191                 /* rmap addr cnts */
9192                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9193                 RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
9194
9195                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9196                 if (cnts == 0) {
9197                         RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
9198                         err = -EINVAL;
9199                         goto exit;
9200                 }
9201                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9202
9203                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (PVOID)&max_available_len, _FALSE);
9204                 if ((addr + cnts) > max_available_len) {
9205                         RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9206                         err = -EINVAL;
9207                         goto exit;
9208                 }
9209
9210                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
9211                         RTW_INFO("%s: rtw_efuse_mask_map_read error!\n", __func__);
9212                         err = -EFAULT;
9213                         goto exit;
9214                 }
9215
9216                 /*              RTW_INFO("%s: data={", __FUNCTION__); */
9217                 *extra = 0;
9218                 for (i = 0; i < cnts; i++) {
9219                         /*                      RTW_INFO("0x%02x ", data[i]); */
9220                         sprintf(extra, "%s0x%02X ", extra, data[i]);
9221                 }
9222                 /*              RTW_INFO("}\n"); */
9223         } else if (strcmp(tmp[0], "realraw") == 0) {
9224                 static u8 raw_order = 0;
9225                 u32 shift, cnt;
9226                 u32 blksz = 0x200; /* The size of one time show, default 512 */
9227
9228                 addr = 0;
9229                 mapLen = EFUSE_MAX_SIZE;
9230                 RTW_INFO("EFUSE_MAX_SIZE = %d\n", EFUSE_MAX_SIZE);
9231
9232                 if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL) {
9233                         RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
9234                         err = -EFAULT;
9235                         goto exit;
9236                 }
9237
9238                 shift = blksz * raw_order;
9239                 rawdata += shift;
9240                 cnt = mapLen - shift;
9241                 if (cnt > blksz) {
9242                         cnt = blksz;
9243                         raw_order++;
9244                 } else
9245                         raw_order = 0;
9246
9247                 sprintf(extra, "\n");
9248                 for (i = 0; i < cnt; i += 16) {
9249                         sprintf(extra, "%s0x%02x\t", extra, shift + i);
9250                         for (j = 0; j < 8; j++)
9251                                 sprintf(extra, "%s%02X ", extra, rawdata[i + j]);
9252                         sprintf(extra, "%s\t", extra);
9253                         for (; j < 16; j++)
9254                                 sprintf(extra, "%s%02X ", extra, rawdata[i + j]);
9255                         sprintf(extra, "%s\n", extra);
9256                 }
9257                 if ((shift + cnt) < mapLen)
9258                         sprintf(extra, "%s\t...more (left:%d/%d)\n", extra, mapLen-(shift + cnt), mapLen);
9259
9260         } else if (strcmp(tmp[0], "btrealraw") == 0) {
9261                 static u8 bt_raw_order = 0;
9262                 u32 shift, cnt;
9263                 u32 blksz = 0x200; /* The size of one time show, default 512 */
9264
9265                 mapLen = EFUSE_BT_REAL_CONTENT_LEN;
9266                 RTW_INFO("Real content len = %d\n", mapLen);
9267 #ifdef RTW_HALMAC
9268                 if (rtw_efuse_bt_access(padapter, _FALSE, 0, mapLen, rawdata) == _FAIL) {
9269                         RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
9270                         err = -EFAULT;
9271                         goto exit;
9272                 }
9273 #else
9274                 rtw_write8(padapter, 0x35, 0x1);
9275
9276                 if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL) {
9277                         RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
9278                         err = -EFAULT;
9279                         goto exit;
9280                 }
9281 #endif
9282                 _rtw_memset(extra, '\0', strlen(extra));
9283
9284                 shift = blksz * bt_raw_order;
9285                 rawdata += shift;
9286                 cnt = mapLen - shift;
9287                 if (cnt > blksz) {
9288                         cnt = blksz;
9289                         bt_raw_order++;
9290                 } else
9291                         bt_raw_order = 0;
9292
9293                 sprintf(extra, "\n");
9294                 for (i = 0; i < cnt; i += 16) {
9295                         sprintf(extra, "%s0x%02x\t", extra, shift + i);
9296                         for (j = 0; j < 8; j++)
9297                                 sprintf(extra, "%s%02X ", extra, rawdata[i + j]);
9298                         sprintf(extra, "%s\t", extra);
9299                         for (; j < 16; j++)
9300                                 sprintf(extra, "%s%02X ", extra, rawdata[i + j]);
9301                         sprintf(extra, "%s\n", extra);
9302
9303                 }
9304                 if ((shift + cnt) < mapLen)
9305                         sprintf(extra, "%s\t...more (left:%d/%d)\n", extra, mapLen-(shift + cnt), mapLen);
9306         } else if (strcmp(tmp[0], "mac") == 0) {
9307                 if (hal_efuse_macaddr_offset(padapter) == -1) {
9308                         err = -EFAULT;
9309                         goto exit;
9310                 }
9311
9312                 addr = hal_efuse_macaddr_offset(padapter);
9313                 cnts = 6;
9314
9315                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
9316                 if ((addr + cnts) > max_available_len) {
9317                         RTW_INFO("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9318                         err = -EFAULT;
9319                         goto exit;
9320                 }
9321
9322                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
9323                         RTW_INFO("%s: rtw_efuse_mask_map_read error!\n", __func__);
9324                         err = -EFAULT;
9325                         goto exit;
9326                 }
9327
9328                 /*              RTW_INFO("%s: MAC address={", __FUNCTION__); */
9329                 *extra = 0;
9330                 for (i = 0; i < cnts; i++) {
9331                         /*                      RTW_INFO("%02X", data[i]); */
9332                         sprintf(extra, "%s%02X", extra, data[i]);
9333                         if (i != (cnts - 1)) {
9334                                 /*                              RTW_INFO(":"); */
9335                                 sprintf(extra, "%s:", extra);
9336                         }
9337                 }
9338                 /*              RTW_INFO("}\n"); */
9339         } else if (strcmp(tmp[0], "vidpid") == 0) {
9340 #ifdef CONFIG_RTL8188E
9341 #ifdef CONFIG_USB_HCI
9342                 addr = EEPROM_VID_88EU;
9343 #endif
9344 #ifdef CONFIG_PCI_HCI
9345                 addr = EEPROM_VID_88EE;
9346 #endif
9347 #endif /* CONFIG_RTL8188E */
9348
9349 #ifdef CONFIG_RTL8192E
9350 #ifdef CONFIG_USB_HCI
9351                 addr = EEPROM_VID_8192EU;
9352 #endif
9353 #ifdef CONFIG_PCI_HCI
9354                 addr = EEPROM_VID_8192EE;
9355 #endif
9356 #endif /* CONFIG_RTL8192E */
9357 #ifdef CONFIG_RTL8723B
9358                 addr = EEPROM_VID_8723BU;
9359 #endif /* CONFIG_RTL8192E */
9360
9361 #ifdef CONFIG_RTL8188F
9362                 addr = EEPROM_VID_8188FU;
9363 #endif /* CONFIG_RTL8188F */
9364
9365 #ifdef CONFIG_RTL8703B
9366 #ifdef CONFIG_USB_HCI
9367                 addr = EEPROM_VID_8703BU;
9368 #endif
9369 #endif /* CONFIG_RTL8703B */
9370
9371 #ifdef CONFIG_RTL8723D
9372 #ifdef CONFIG_USB_HCI
9373                 addr = EEPROM_VID_8723DU;
9374 #endif /* CONFIG_USB_HCI */
9375 #endif /* CONFIG_RTL8723D */
9376
9377                 cnts = 4;
9378
9379                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
9380                 if ((addr + cnts) > max_available_len) {
9381                         RTW_INFO("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9382                         err = -EFAULT;
9383                         goto exit;
9384                 }
9385                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
9386                         RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9387                         err = -EFAULT;
9388                         goto exit;
9389                 }
9390
9391                 /*              RTW_INFO("%s: {VID,PID}={", __FUNCTION__); */
9392                 *extra = 0;
9393                 for (i = 0; i < cnts; i++) {
9394                         /*                      RTW_INFO("0x%02x", data[i]); */
9395                         sprintf(extra, "%s0x%02X", extra, data[i]);
9396                         if (i != (cnts - 1)) {
9397                                 /*                              RTW_INFO(","); */
9398                                 sprintf(extra, "%s,", extra);
9399                         }
9400                 }
9401                 /*              RTW_INFO("}\n"); */
9402         } else if (strcmp(tmp[0], "ableraw") == 0) {
9403 #ifdef RTW_HALMAC
9404                 raw_maxsize = efuse_GetavailableSize(padapter);
9405 #else
9406                 efuse_GetCurrentSize(padapter, &raw_cursize);
9407                 raw_maxsize = efuse_GetMaxSize(padapter);
9408 #endif
9409                 sprintf(extra, "[available raw size]= %d bytes\n", raw_maxsize - raw_cursize);
9410         } else if (strcmp(tmp[0], "btableraw") == 0) {
9411                 efuse_bt_GetCurrentSize(padapter, &raw_cursize);
9412                 raw_maxsize = efuse_bt_GetMaxSize(padapter);
9413                 sprintf(extra, "[available raw size]= %d bytes\n", raw_maxsize - raw_cursize);
9414         } else if (strcmp(tmp[0], "btfmap") == 0) {
9415
9416                 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
9417
9418                 mapLen = EFUSE_BT_MAX_MAP_LEN;
9419                 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
9420                         RTW_INFO("%s: rtw_BT_efuse_map_read Fail!!\n", __FUNCTION__);
9421                         err = -EFAULT;
9422                         goto exit;
9423                 }
9424
9425                 /*              RTW_INFO("OFFSET\tVALUE(hex)\n"); */
9426                 sprintf(extra, "\n");
9427                 for (i = 0; i < 512; i += 16) { /* set 512 because the iwpriv's extra size have limit 0x7FF */
9428                         /*                      RTW_INFO("0x%03x\t", i); */
9429                         sprintf(extra, "%s0x%03x\t", extra, i);
9430                         for (j = 0; j < 8; j++) {
9431                                 /*                              RTW_INFO("%02X ", pEfuseHal->BTEfuseInitMap[i+j]); */
9432                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i + j]);
9433                         }
9434                         /*                      RTW_INFO("\t"); */
9435                         sprintf(extra, "%s\t", extra);
9436                         for (; j < 16; j++) {
9437                                 /*                              RTW_INFO("%02X ", pEfuseHal->BTEfuseInitMap[i+j]); */
9438                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i + j]);
9439                         }
9440                         /*                      RTW_INFO("\n"); */
9441                         sprintf(extra, "%s\n", extra);
9442                 }
9443                 /*              RTW_INFO("\n"); */
9444         } else if (strcmp(tmp[0], "btbmap") == 0) {
9445                 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
9446
9447                 mapLen = EFUSE_BT_MAX_MAP_LEN;
9448                 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
9449                         RTW_INFO("%s: rtw_BT_efuse_map_read Fail!!\n", __FUNCTION__);
9450                         err = -EFAULT;
9451                         goto exit;
9452                 }
9453
9454                 /*              RTW_INFO("OFFSET\tVALUE(hex)\n"); */
9455                 sprintf(extra, "\n");
9456                 for (i = 512; i < 1024 ; i += 16) {
9457                         /*                      RTW_INFO("0x%03x\t", i); */
9458                         sprintf(extra, "%s0x%03x\t", extra, i);
9459                         for (j = 0; j < 8; j++) {
9460                                 /*                              RTW_INFO("%02X ", data[i+j]); */
9461                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i + j]);
9462                         }
9463                         /*                      RTW_INFO("\t"); */
9464                         sprintf(extra, "%s\t", extra);
9465                         for (; j < 16; j++) {
9466                                 /*                              RTW_INFO("%02X ", data[i+j]); */
9467                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i + j]);
9468                         }
9469                         /*                      RTW_INFO("\n"); */
9470                         sprintf(extra, "%s\n", extra);
9471                 }
9472                 /*              RTW_INFO("\n"); */
9473         } else if (strcmp(tmp[0], "btrmap") == 0) {
9474                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9475                         err = -EINVAL;
9476                         goto exit;
9477                 }
9478                 rtw_write8(padapter, 0xa3, 0x05); /* For 8723AB ,8821S ? */
9479                 BTStatus = rtw_read8(padapter, 0xa0);
9480
9481                 RTW_INFO("%s: Check 0xa0 BT Status =0x%x\n", __FUNCTION__, BTStatus);
9482                 if (BTStatus != 0x04) {
9483                         sprintf(extra, "BT Status not Active ,can't to read BT eFuse\n");
9484                         goto exit;
9485                 }
9486
9487                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9488                         err = -EINVAL;
9489                         goto exit;
9490                 }
9491
9492                 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
9493
9494                 /* rmap addr cnts */
9495                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9496                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9497
9498                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9499                 if (cnts == 0) {
9500                         RTW_INFO("%s: btrmap Fail!! cnts error!\n", __FUNCTION__);
9501                         err = -EINVAL;
9502                         goto exit;
9503                 }
9504                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9505
9506                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
9507                 if ((addr + cnts) > max_available_len) {
9508                         RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9509                         err = -EFAULT;
9510                         goto exit;
9511                 }
9512
9513                 if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
9514                         RTW_INFO("%s: rtw_BT_efuse_map_read error!!\n", __FUNCTION__);
9515                         err = -EFAULT;
9516                         goto exit;
9517                 }
9518
9519                 *extra = 0;
9520                 /*              RTW_INFO("%s: bt efuse data={", __FUNCTION__); */
9521                 for (i = 0; i < cnts; i++) {
9522                         /*                      RTW_INFO("0x%02x ", data[i]); */
9523                         sprintf(extra, "%s 0x%02X ", extra, data[i]);
9524                 }
9525                 /*              RTW_INFO("}\n"); */
9526                 RTW_INFO(FUNC_ADPT_FMT ": BT MAC=[%s]\n", FUNC_ADPT_ARG(padapter), extra);
9527         } else if (strcmp(tmp[0], "btffake") == 0) {
9528                 /*              RTW_INFO("OFFSET\tVALUE(hex)\n"); */
9529                 sprintf(extra, "\n");
9530                 for (i = 0; i < 512; i += 16) {
9531                         /*                      RTW_INFO("0x%03x\t", i); */
9532                         sprintf(extra, "%s0x%03x\t", extra, i);
9533                         for (j = 0; j < 8; j++) {
9534                                 /*                              RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
9535                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
9536                         }
9537                         /*                      RTW_INFO("\t"); */
9538                         sprintf(extra, "%s\t", extra);
9539                         for (; j < 16; j++) {
9540                                 /*                              RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
9541                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
9542                         }
9543                         /*                      RTW_INFO("\n"); */
9544                         sprintf(extra, "%s\n", extra);
9545                 }
9546                 /*              RTW_INFO("\n"); */
9547         } else if (strcmp(tmp[0], "btbfake") == 0) {
9548                 /*              RTW_INFO("OFFSET\tVALUE(hex)\n"); */
9549                 sprintf(extra, "\n");
9550                 for (i = 512; i < 1024; i += 16) {
9551                         /*                      RTW_INFO("0x%03x\t", i); */
9552                         sprintf(extra, "%s0x%03x\t", extra, i);
9553                         for (j = 0; j < 8; j++) {
9554                                 /*                              RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
9555                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
9556                         }
9557                         /*                      RTW_INFO("\t"); */
9558                         sprintf(extra, "%s\t", extra);
9559                         for (; j < 16; j++) {
9560                                 /*                              RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
9561                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
9562                         }
9563                         /*                      RTW_INFO("\n"); */
9564                         sprintf(extra, "%s\n", extra);
9565                 }
9566                 /*              RTW_INFO("\n"); */
9567         } else if (strcmp(tmp[0], "wlrfkmap") == 0) {
9568                 static u8 fk_order = 0;
9569                 u8 *efuse;
9570                 u32 shift, cnt;
9571                 u32 blksz = 0x200; /* The size of one time show, default 512 */
9572
9573                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapLen, _FALSE);
9574                 efuse = pEfuseHal->fakeEfuseModifiedMap;
9575
9576                 shift = blksz * fk_order;
9577                 efuse += shift;
9578                 cnt = mapLen - shift;
9579                 if (cnt > blksz) {
9580                         cnt = blksz;
9581                         fk_order++;
9582                 } else
9583                         fk_order = 0;
9584
9585                 sprintf(extra, "\n");
9586                 for (i = 0; i < cnt; i += 16) {
9587                         sprintf(extra, "%s0x%02x\t", extra, shift + i);
9588                         for (j = 0; j < 8; j++)
9589                                 sprintf(extra, "%s%02X ", extra, efuse[i + j]);
9590                         sprintf(extra, "%s\t", extra);
9591                         for (; j < 16; j++)
9592                                 sprintf(extra, "%s%02X ", extra, efuse[i + j]);
9593                         sprintf(extra, "%s\n", extra);
9594                 }
9595                 if ((shift + cnt) < mapLen)
9596                         sprintf(extra, "%s\t...more\n", extra);
9597
9598         } else if (strcmp(tmp[0], "wlrfkrmap") == 0) {
9599                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9600                         RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
9601                         err = -EINVAL;
9602                         goto exit;
9603                 }
9604                 /* rmap addr cnts */
9605                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9606                 RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
9607
9608                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9609                 if (cnts == 0) {
9610                         RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
9611                         err = -EINVAL;
9612                         goto exit;
9613                 }
9614                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9615
9616                 /*              RTW_INFO("%s: data={", __FUNCTION__); */
9617                 *extra = 0;
9618                 for (i = 0; i < cnts; i++) {
9619                         RTW_INFO("wlrfkrmap = 0x%02x\n", pEfuseHal->fakeEfuseModifiedMap[addr + i]);
9620                         sprintf(extra, "%s0x%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[addr + i]);
9621                 }
9622         } else if (strcmp(tmp[0], "btrfkrmap") == 0) {
9623                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9624                         RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
9625                         err = -EINVAL;
9626                         goto exit;
9627                 }
9628                 /* rmap addr cnts */
9629                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9630                 RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
9631
9632                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9633                 if (cnts == 0) {
9634                         RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
9635                         err = -EINVAL;
9636                         goto exit;
9637                 }
9638                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9639
9640                 /*              RTW_INFO("%s: data={", __FUNCTION__); */
9641                 *extra = 0;
9642                 for (i = 0; i < cnts; i++) {
9643                         RTW_INFO("wlrfkrmap = 0x%02x\n", pEfuseHal->fakeBTEfuseModifiedMap[addr + i]);
9644                         sprintf(extra, "%s0x%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[addr + i]);
9645                 }
9646         } else
9647                 sprintf(extra, "Command not found!");
9648
9649 exit:
9650         if (data)
9651                 rtw_mfree(data, EFUSE_BT_MAX_MAP_LEN);
9652         if (rawdata)
9653                 rtw_mfree(rawdata, EFUSE_BT_MAX_MAP_LEN);
9654         if (!err)
9655                 wrqu->length = strlen(extra);
9656
9657         if (padapter->registrypriv.mp_mode == 0) {
9658 #ifdef CONFIG_IPS
9659                 rtw_pm_set_ips(padapter, ips_mode);
9660 #endif /* CONFIG_IPS */
9661
9662 #ifdef CONFIG_LPS
9663                 rtw_pm_set_lps(padapter, lps_mode);
9664 #endif /* CONFIG_LPS */
9665         }
9666
9667 #ifdef CONFIG_IOL
9668         padapter->registrypriv.fw_iol = org_fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
9669 #endif
9670         return err;
9671 }
9672
9673 static int rtw_mp_efuse_set(struct net_device *dev,
9674                             struct iw_request_info *info,
9675                             union iwreq_data *wdata, char *extra)
9676 {
9677         struct iw_point *wrqu;
9678         PADAPTER padapter;
9679         struct pwrctrl_priv *pwrctrlpriv ;
9680         PHAL_DATA_TYPE pHalData;
9681         PEFUSE_HAL pEfuseHal;
9682
9683         u8 ips_mode = IPS_NUM; /* init invalid value */
9684         u8 lps_mode = PS_MODE_NUM; /* init invalid value */
9685         u32 i = 0, j = 0, jj, kk;
9686         u8 *setdata = NULL;
9687         u8 *ShadowMapBT = NULL;
9688         u8 *ShadowMapWiFi = NULL;
9689         u8 *setrawdata = NULL;
9690         char *pch, *ptmp, *token, *tmp[3] = {0x00, 0x00, 0x00};
9691         u16 addr = 0xFF, cnts = 0, BTStatus = 0 , max_available_len = 0;
9692         u16 wifimaplen;
9693         int err;
9694
9695         wrqu = (struct iw_point *)wdata;
9696         padapter = rtw_netdev_priv(dev);
9697         pwrctrlpriv = adapter_to_pwrctl(padapter);
9698         pHalData = GET_HAL_DATA(padapter);
9699         pEfuseHal = &pHalData->EfuseHal;
9700         err = 0;
9701
9702         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
9703                 return -EFAULT;
9704
9705         EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&wifimaplen, _FALSE);
9706
9707         setdata = rtw_zmalloc(1024);
9708         if (setdata == NULL) {
9709                 err = -ENOMEM;
9710                 goto exit;
9711         }
9712         ShadowMapBT = rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
9713         if (ShadowMapBT == NULL) {
9714                 err = -ENOMEM;
9715                 goto exit;
9716         }
9717         ShadowMapWiFi = rtw_malloc(wifimaplen);
9718         if (ShadowMapWiFi == NULL) {
9719                 err = -ENOMEM;
9720                 goto exit;
9721         }
9722         setrawdata = rtw_malloc(EFUSE_MAX_SIZE);
9723         if (setrawdata == NULL) {
9724                 err = -ENOMEM;
9725                 goto exit;
9726         }
9727
9728 #ifdef CONFIG_LPS
9729         lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
9730         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
9731 #endif
9732
9733 #ifdef CONFIG_IPS
9734         ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
9735         rtw_pm_set_ips(padapter, IPS_NONE);
9736 #endif
9737
9738         pch = extra;
9739         RTW_INFO("%s: in=%s\n", __FUNCTION__, extra);
9740
9741         i = 0;
9742         while ((token = strsep(&pch, ",")) != NULL) {
9743                 if (i > 2)
9744                         break;
9745                 tmp[i] = token;
9746                 i++;
9747         }
9748
9749         /* tmp[0],[1],[2] */
9750         /* wmap,addr,00e04c871200 */
9751         if (strcmp(tmp[0], "wmap") == 0) {
9752                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9753                         err = -EINVAL;
9754                         goto exit;
9755                 }
9756
9757 #ifndef RTW_HALMAC
9758                 /* unknown bug workaround, need to fix later */
9759                 addr = 0x1ff;
9760                 rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
9761                 rtw_msleep_os(10);
9762                 rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
9763                 rtw_msleep_os(10);
9764                 rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
9765                 rtw_msleep_os(10);
9766                 rtw_read8(padapter, EFUSE_CTRL);
9767 #endif /* RTW_HALMAC */
9768
9769                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9770                 addr &= 0xFFF;
9771
9772                 cnts = strlen(tmp[2]);
9773                 if (cnts % 2) {
9774                         err = -EINVAL;
9775                         goto exit;
9776                 }
9777                 cnts /= 2;
9778                 if (cnts == 0) {
9779                         err = -EINVAL;
9780                         goto exit;
9781                 }
9782
9783                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9784                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9785                 RTW_INFO("%s: map data=%s\n", __FUNCTION__, tmp[2]);
9786
9787                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9788                         setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9789
9790                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
9791
9792                 if ((addr + cnts) > max_available_len) {
9793                         RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9794                         err = -EFAULT;
9795                         goto exit;
9796                 }
9797
9798                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
9799                         RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
9800                         err = -EFAULT;
9801                         goto exit;
9802                 }
9803                 *extra = 0;
9804                 RTW_INFO("%s: after rtw_efuse_map_write to _rtw_memcmp\n", __func__);
9805                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, ShadowMapWiFi) == _SUCCESS) {
9806                         if (_rtw_memcmp((void *)ShadowMapWiFi , (void *)setdata, cnts)) {
9807                                 RTW_INFO("%s: WiFi write map afterf compare success\n", __FUNCTION__);
9808                                 sprintf(extra, "WiFi write map compare OK\n");
9809                                 err = 0;
9810                                 goto exit;
9811                         } else {
9812                                 sprintf(extra, "WiFi write map compare FAIL\n");
9813                                 RTW_INFO("%s: WiFi write map compare Fail\n", __FUNCTION__);
9814                                 err = 0;
9815                                 goto exit;
9816                         }
9817                 }
9818         } else if (strcmp(tmp[0], "wraw") == 0) {
9819                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9820                         err = -EINVAL;
9821                         goto exit;
9822                 }
9823
9824                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9825                 addr &= 0xFFF;
9826
9827                 cnts = strlen(tmp[2]);
9828                 if (cnts % 2) {
9829                         err = -EINVAL;
9830                         goto exit;
9831                 }
9832                 cnts /= 2;
9833                 if (cnts == 0) {
9834                         err = -EINVAL;
9835                         goto exit;
9836                 }
9837
9838                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9839                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9840                 RTW_INFO("%s: raw data=%s\n", __FUNCTION__, tmp[2]);
9841
9842                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9843                         setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9844
9845                 if (rtw_efuse_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL) {
9846                         RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9847                         err = -EFAULT;
9848                         goto exit;
9849                 }
9850         } else if (strcmp(tmp[0], "btwraw") == 0) {
9851                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9852                         err = -EINVAL;
9853                         goto exit;
9854                 }
9855
9856                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9857                 addr &= 0xFFF;
9858
9859                 cnts = strlen(tmp[2]);
9860                 if (cnts % 2) {
9861                         err = -EINVAL;
9862                         goto exit;
9863                 }
9864                 cnts /= 2;
9865                 if (cnts == 0) {
9866                         err = -EINVAL;
9867                         goto exit;
9868                 }
9869
9870                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9871                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9872                 RTW_INFO("%s: raw data=%s\n", __FUNCTION__, tmp[2]);
9873
9874                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9875                         setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9876 #ifdef RTW_HALMAC
9877                 if (rtw_efuse_bt_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL) {
9878                         RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9879                         err = -EFAULT;
9880                         goto exit;
9881                 }
9882 #else
9883                 rtw_write8(padapter, 0x35, 1); /* switch bank 1 (BT)*/
9884                 if (rtw_efuse_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL) {
9885                         RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9886                         rtw_write8(padapter, 0x35, 0); /* switch bank 0 (WiFi)*/
9887                         err = -EFAULT;
9888                         goto exit;
9889                 }
9890                 rtw_write8(padapter, 0x35, 0); /* switch bank 0 (WiFi)*/
9891 #endif
9892         } else if (strcmp(tmp[0], "mac") == 0) {
9893                 if (tmp[1] == NULL) {
9894                         err = -EINVAL;
9895                         goto exit;
9896                 }
9897
9898                 /* mac,00e04c871200 */
9899
9900                 if (hal_efuse_macaddr_offset(padapter) == -1) {
9901                         err = -EFAULT;
9902                         goto exit;
9903                 }
9904
9905                 addr = hal_efuse_macaddr_offset(padapter);
9906                 cnts = strlen(tmp[1]);
9907                 if (cnts % 2) {
9908                         err = -EINVAL;
9909                         goto exit;
9910                 }
9911                 cnts /= 2;
9912                 if (cnts == 0) {
9913                         err = -EINVAL;
9914                         goto exit;
9915                 }
9916                 if (cnts > 6) {
9917                         RTW_INFO("%s: error data for mac addr=\"%s\"\n", __FUNCTION__, tmp[1]);
9918                         err = -EFAULT;
9919                         goto exit;
9920                 }
9921
9922                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9923                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9924                 RTW_INFO("%s: MAC address=%s\n", __FUNCTION__, tmp[1]);
9925
9926                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9927                         setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
9928
9929                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
9930
9931                 if ((addr + cnts) > max_available_len) {
9932                         RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9933                         err = -EFAULT;
9934                         goto exit;
9935                 }
9936
9937                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
9938                         RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
9939                         err = -EFAULT;
9940                         goto exit;
9941                 }
9942         } else if (strcmp(tmp[0], "vidpid") == 0) {
9943                 if (tmp[1] == NULL) {
9944                         err = -EINVAL;
9945                         goto exit;
9946                 }
9947
9948                 /* pidvid,da0b7881               */
9949 #ifdef CONFIG_RTL8188E
9950 #ifdef CONFIG_USB_HCI
9951                 addr = EEPROM_VID_88EU;
9952 #endif
9953 #ifdef CONFIG_PCI_HCI
9954                 addr = EEPROM_VID_88EE;
9955 #endif
9956 #endif /* CONFIG_RTL8188E */
9957
9958 #ifdef CONFIG_RTL8192E
9959 #ifdef CONFIG_USB_HCI
9960                 addr = EEPROM_VID_8192EU;
9961 #endif
9962 #ifdef CONFIG_PCI_HCI
9963                 addr = EEPROM_VID_8192EE;
9964 #endif
9965 #endif /* CONFIG_RTL8188E */
9966
9967 #ifdef CONFIG_RTL8723B
9968                 addr = EEPROM_VID_8723BU;
9969 #endif
9970
9971 #ifdef CONFIG_RTL8188F
9972                 addr = EEPROM_VID_8188FU;
9973 #endif
9974
9975 #ifdef CONFIG_RTL8703B
9976 #ifdef CONFIG_USB_HCI
9977                 addr = EEPROM_VID_8703BU;
9978 #endif /* CONFIG_USB_HCI */
9979 #endif /* CONFIG_RTL8703B */
9980
9981 #ifdef CONFIG_RTL8723D
9982 #ifdef CONFIG_USB_HCI
9983                 addr = EEPROM_VID_8723DU;
9984 #endif /* CONFIG_USB_HCI */
9985 #endif /* CONFIG_RTL8723D */
9986
9987                 cnts = strlen(tmp[1]);
9988                 if (cnts % 2) {
9989                         err = -EINVAL;
9990                         goto exit;
9991                 }
9992                 cnts /= 2;
9993                 if (cnts == 0) {
9994                         err = -EINVAL;
9995                         goto exit;
9996                 }
9997
9998                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9999                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
10000                 RTW_INFO("%s: VID/PID=%s\n", __FUNCTION__, tmp[1]);
10001
10002                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
10003                         setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
10004
10005                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
10006                 if ((addr + cnts) > max_available_len) {
10007                         RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10008                         err = -EFAULT;
10009                         goto exit;
10010                 }
10011
10012                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
10013                         RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
10014                         err = -EFAULT;
10015                         goto exit;
10016                 }
10017         } else if (strcmp(tmp[0], "wldumpfake") == 0) {
10018                 if (wifimaplen > EFUSE_MAX_MAP_LEN)
10019                         cnts = EFUSE_MAX_MAP_LEN;
10020                 else
10021                         cnts = wifimaplen;
10022                 if (rtw_efuse_mask_map_read(padapter, 0, cnts, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS)
10023                         RTW_INFO("%s: WiFi hw efuse dump to Fake map success\n", __func__);
10024                 else {
10025                         RTW_INFO("%s: WiFi hw efuse dump to Fake map Fail\n", __func__);
10026                         err = -EFAULT;
10027                 }
10028         } else if (strcmp(tmp[0], "btwmap") == 0) {
10029                 rtw_write8(padapter, 0xa3, 0x05); /* For 8723AB ,8821S ? */
10030                 BTStatus = rtw_read8(padapter, 0xa0);
10031                 RTW_INFO("%s: btwmap before read 0xa0 BT Status =0x%x\n", __FUNCTION__, BTStatus);
10032                 if (BTStatus != 0x04) {
10033                         sprintf(extra, "BT Status not Active ,can't do Write\n");
10034                         goto exit;
10035                 }
10036
10037                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
10038                         err = -EINVAL;
10039                         goto exit;
10040                 }
10041
10042 #ifndef RTW_HALMAC
10043                 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
10044                 addr = 0x1ff;
10045                 rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
10046                 rtw_msleep_os(10);
10047                 rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
10048                 rtw_msleep_os(10);
10049                 rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
10050                 rtw_msleep_os(10);
10051                 rtw_read8(padapter, EFUSE_CTRL);
10052                 BTEfuse_PowerSwitch(padapter, 1, _FALSE);
10053 #endif /* RTW_HALMAC */
10054
10055                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10056                 addr &= 0xFFF;
10057
10058                 cnts = strlen(tmp[2]);
10059                 if (cnts % 2) {
10060                         err = -EINVAL;
10061                         goto exit;
10062                 }
10063                 cnts /= 2;
10064                 if (cnts == 0) {
10065                         err = -EINVAL;
10066                         goto exit;
10067                 }
10068
10069                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
10070                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
10071                 RTW_INFO("%s: BT data=%s\n", __FUNCTION__, tmp[2]);
10072
10073                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
10074                         setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
10075 #ifdef CONFIG_RTL8703B
10076                 if (cnts == 1 && addr == 0x189) {
10077                         setdata[1] = setdata[0];
10078                         setdata[0] = 0x00;
10079                         cnts += 1;
10080                         addr = 0x188;
10081                         RTW_INFO("addr 0x%x ,setdata=0x%X 0x%X\n", addr, setdata[0], setdata[1]);
10082                 } else if (cnts == 1 && addr == 0x161) {
10083                         setdata[1] = setdata[0];
10084                         setdata[0] = 0xFE;
10085                         cnts += 1;
10086                         addr = 0x160;
10087                         RTW_INFO("addr 0x%x ,setdata=0x%X 0x%X\n", addr, setdata[0], setdata[1]);
10088                 }
10089 #endif
10090 #ifndef RTW_HALMAC
10091                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_len, _FALSE);
10092                 if ((addr + cnts) > max_available_len) {
10093                         RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10094                         err = -EFAULT;
10095                         goto exit;
10096                 }
10097 #endif
10098                 if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
10099                         RTW_INFO("%s: rtw_BT_efuse_map_write error!!\n", __FUNCTION__);
10100                         err = -EFAULT;
10101                         goto exit;
10102                 }
10103                 *extra = 0;
10104                 RTW_INFO("%s: after rtw_BT_efuse_map_write to _rtw_memcmp\n", __FUNCTION__);
10105                 if ((rtw_BT_efuse_map_read(padapter, addr, cnts, ShadowMapBT) == _SUCCESS)) {
10106                         if (_rtw_memcmp((void *)ShadowMapBT , (void *)setdata, cnts)) {
10107                                 RTW_INFO("%s: BT write map compare OK BTStatus=0x%x\n", __FUNCTION__, BTStatus);
10108                                 sprintf(extra, "BT write map compare OK");
10109                                 err = 0;
10110                                 goto exit;
10111                         } else {
10112                                 sprintf(extra, "BT write map compare FAIL");
10113                                 RTW_INFO("%s: BT write map compare FAIL BTStatus=0x%x\n", __FUNCTION__, BTStatus);
10114                                 err = 0;
10115                                 goto exit;
10116                         }
10117                 }
10118         } else if (strcmp(tmp[0], "btwfake") == 0) {
10119                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
10120                         err = -EINVAL;
10121                         goto exit;
10122                 }
10123
10124                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10125                 addr &= 0xFFF;
10126
10127                 cnts = strlen(tmp[2]);
10128                 if (cnts % 2) {
10129                         err = -EINVAL;
10130                         goto exit;
10131                 }
10132                 cnts /= 2;
10133                 if (cnts == 0) {
10134                         err = -EINVAL;
10135                         goto exit;
10136                 }
10137
10138                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
10139                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
10140                 RTW_INFO("%s: BT tmp data=%s\n", __FUNCTION__, tmp[2]);
10141
10142                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
10143                         pEfuseHal->fakeBTEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
10144         } else if (strcmp(tmp[0], "btdumpfake") == 0) {
10145                 if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS)
10146                         RTW_INFO("%s: BT read all map success\n", __FUNCTION__);
10147                 else {
10148                         RTW_INFO("%s: BT read all map Fail!\n", __FUNCTION__);
10149                         err = -EFAULT;
10150                 }
10151         } else if (strcmp(tmp[0], "btfk2map") == 0) {
10152                 rtw_write8(padapter, 0xa3, 0x05);
10153                 BTStatus = rtw_read8(padapter, 0xa0);
10154                 RTW_INFO("%s: btwmap before read 0xa0 BT Status =0x%x\n", __FUNCTION__, BTStatus);
10155                 if (BTStatus != 0x04) {
10156                         sprintf(extra, "BT Status not Active Write FAIL\n");
10157                         goto exit;
10158                 }
10159 #ifndef RTW_HALMAC
10160                 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
10161                 addr = 0x1ff;
10162                 rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
10163                 rtw_msleep_os(10);
10164                 rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
10165                 rtw_msleep_os(10);
10166                 rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
10167                 rtw_msleep_os(10);
10168                 rtw_read8(padapter, EFUSE_CTRL);
10169                 BTEfuse_PowerSwitch(padapter, 1, _FALSE);
10170 #endif /* RTW_HALMAC */
10171                 _rtw_memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
10172
10173                 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
10174                         RTW_INFO("%s: rtw_BT_efuse_map_write error!\n", __FUNCTION__);
10175                         err = -EFAULT;
10176                         goto exit;
10177                 }
10178
10179                 RTW_INFO("pEfuseHal->fakeBTEfuseModifiedMap OFFSET\tVALUE(hex)\n");
10180                 for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16) {
10181                         printk("0x%02x\t", i);
10182                         for (j = 0; j < 8; j++)
10183                                 printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
10184                         printk("\t");
10185
10186                         for (; j < 16; j++)
10187                                 printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
10188                         printk("\n");
10189                 }
10190                 printk("\n");
10191 #if 1
10192                 err = -EFAULT;
10193                 RTW_INFO("%s: rtw_BT_efuse_map_read _rtw_memcmp\n", __FUNCTION__);
10194                 if ((rtw_BT_efuse_map_read(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS)) {
10195                         if (_rtw_memcmp((void *)pEfuseHal->fakeBTEfuseModifiedMap, (void *)pEfuseHal->fakeBTEfuseInitMap, EFUSE_BT_MAX_MAP_LEN)) {
10196                                 sprintf(extra, "BT write map compare OK");
10197                                 RTW_INFO("%s: BT write map afterf compare success BTStatus=0x%x\n", __FUNCTION__, BTStatus);
10198                                 err = 0;
10199                                 goto exit;
10200                         } else {
10201                                 sprintf(extra, "BT write map compare FAIL");
10202                                 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL)
10203                                         RTW_INFO("%s: rtw_BT_efuse_map_write compare error,retry = %d!\n", __FUNCTION__, i);
10204
10205                                 if (rtw_BT_efuse_map_read(padapter, EFUSE_BT, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS) {
10206                                         RTW_INFO("pEfuseHal->fakeBTEfuseInitMap OFFSET\tVALUE(hex)\n");
10207
10208                                         for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16) {
10209                                                 printk("0x%02x\t", i);
10210                                                 for (j = 0; j < 8; j++)
10211                                                         printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i + j]);
10212                                                 printk("\t");
10213                                                 for (; j < 16; j++)
10214                                                         printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i + j]);
10215                                                 printk("\n");
10216                                         }
10217                                         printk("\n");
10218                                 }
10219                                 RTW_INFO("%s: BT write map afterf compare not match to write efuse try write Map again , BTStatus=0x%x\n", __FUNCTION__, BTStatus);
10220                                 goto exit;
10221                         }
10222                 }
10223 #endif
10224
10225         } else if (strcmp(tmp[0], "wlfk2map") == 0) {
10226                 if (wifimaplen > EFUSE_MAX_MAP_LEN)
10227                         cnts = EFUSE_MAX_MAP_LEN;
10228                 else
10229                         cnts = wifimaplen;
10230                 if (rtw_efuse_map_write(padapter, 0x00, cnts, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
10231                         RTW_INFO("%s: rtw_efuse_map_write fakeEfuseModifiedMap error!\n", __FUNCTION__);
10232                         err = -EFAULT;
10233                         goto exit;
10234                 }
10235                 *extra = 0;
10236                 if (rtw_efuse_mask_map_read(padapter, 0x00, wifimaplen, ShadowMapWiFi) == _SUCCESS) {
10237                         if (_rtw_memcmp((void *)ShadowMapWiFi , (void *)pEfuseHal->fakeEfuseModifiedMap, cnts)) {
10238                                 RTW_INFO("%s: WiFi write map afterf compare OK\n", __FUNCTION__);
10239                                 sprintf(extra, "WiFi write map compare OK\n");
10240                                 err = 0;
10241                                 goto exit;
10242                         } else {
10243                                 sprintf(extra, "WiFi write map compare FAIL\n");
10244                                 RTW_INFO("%s: WiFi write map compare Fail\n", __FUNCTION__);
10245                                 err = 0;
10246                                 goto exit;
10247                         }
10248                 }
10249         } else if (strcmp(tmp[0], "wlwfake") == 0) {
10250                 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
10251                         err = -EINVAL;
10252                         goto exit;
10253                 }
10254
10255                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10256                 addr &= 0xFFF;
10257
10258                 cnts = strlen(tmp[2]);
10259                 if (cnts % 2) {
10260                         err = -EINVAL;
10261                         goto exit;
10262                 }
10263                 cnts /= 2;
10264                 if (cnts == 0) {
10265                         err = -EINVAL;
10266                         goto exit;
10267                 }
10268
10269                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
10270                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
10271                 RTW_INFO("%s: map tmp data=%s\n", __FUNCTION__, tmp[2]);
10272
10273                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
10274                         pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
10275                 _rtw_memset(extra, '\0', strlen(extra));
10276                 sprintf(extra, "wlwfake OK\n");
10277
10278         }
10279         else if (strcmp(tmp[0], "wfakemac") == 0) {
10280                 if (tmp[1] == NULL) {
10281                         err = -EINVAL;
10282                         goto exit;
10283                 }
10284                 /* wfakemac,00e04c871200 */
10285                 if (hal_efuse_macaddr_offset(padapter) == -1) {
10286                         err = -EFAULT;
10287                         goto exit;
10288                 }
10289
10290                 addr = hal_efuse_macaddr_offset(padapter);
10291                 cnts = strlen(tmp[1]);
10292                 if (cnts % 2) {
10293                         err = -EINVAL;
10294                         goto exit;
10295                 }
10296                 cnts /= 2;
10297                 if (cnts == 0) {
10298                         err = -EINVAL;
10299                         goto exit;
10300                 }
10301                 if (cnts > 6) {
10302                         RTW_INFO("%s: error data for mac addr=\"%s\"\n", __FUNCTION__, tmp[1]);
10303                         err = -EFAULT;
10304                         goto exit;
10305                 }
10306
10307                 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
10308                 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
10309                 RTW_INFO("%s: MAC address=%s\n", __FUNCTION__, tmp[1]);
10310
10311                 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
10312                         pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
10313
10314                 _rtw_memset(extra, '\0', strlen(extra));
10315                 sprintf(extra, "write mac addr to fake map OK\n");
10316         }
10317
10318 exit:
10319         if (setdata)
10320                 rtw_mfree(setdata, 1024);
10321         if (ShadowMapBT)
10322                 rtw_mfree(ShadowMapBT, EFUSE_BT_MAX_MAP_LEN);
10323         if (ShadowMapWiFi)
10324                 rtw_mfree(ShadowMapWiFi, wifimaplen);
10325         if (setrawdata)
10326                 rtw_mfree(setrawdata, EFUSE_MAX_SIZE);
10327
10328         wrqu->length = strlen(extra);
10329
10330         if (padapter->registrypriv.mp_mode == 0) {
10331 #ifdef CONFIG_IPS
10332                 rtw_pm_set_ips(padapter, ips_mode);
10333 #endif /* CONFIG_IPS */
10334
10335 #ifdef CONFIG_LPS
10336                 rtw_pm_set_lps(padapter, lps_mode);
10337 #endif /* CONFIG_LPS */
10338         }
10339
10340         return err;
10341 }
10342
10343
10344 #ifdef CONFIG_MP_INCLUDED
10345 static int rtw_priv_mp_set(struct net_device *dev,
10346                            struct iw_request_info *info,
10347                            union iwreq_data *wdata, char *extra)
10348 {
10349
10350         struct iw_point *wrqu = (struct iw_point *)wdata;
10351         u32 subcmd = wrqu->flags;
10352
10353         switch (subcmd) {
10354         case MP_START:
10355                 RTW_INFO("set case mp_start\n");
10356                 rtw_mp_start(dev, info, wrqu, extra);
10357                 break;
10358         case MP_STOP:
10359                 RTW_INFO("set case mp_stop\n");
10360                 rtw_mp_stop(dev, info, wrqu, extra);
10361                 break;
10362         case MP_BANDWIDTH:
10363                 RTW_INFO("set case mp_bandwidth\n");
10364                 rtw_mp_bandwidth(dev, info, wrqu, extra);
10365                 break;
10366         case MP_RESET_STATS:
10367                 RTW_INFO("set case MP_RESET_STATS\n");
10368                 rtw_mp_reset_stats(dev, info, wrqu, extra);
10369                 break;
10370         case MP_SetRFPathSwh:
10371                 RTW_INFO("set MP_SetRFPathSwitch\n");
10372                 rtw_mp_SetRFPath(dev, info, wdata, extra);
10373                 break;
10374         case CTA_TEST:
10375                 RTW_INFO("set CTA_TEST\n");
10376                 rtw_cta_test_start(dev, info, wdata, extra);
10377                 break;
10378         case MP_DISABLE_BT_COEXIST:
10379                 RTW_INFO("set case MP_DISABLE_BT_COEXIST\n");
10380                 rtw_mp_disable_bt_coexist(dev, info, wdata, extra);
10381                 break;
10382         default:
10383                 return -EIO;
10384         }
10385
10386         return 0;
10387 }
10388
10389 static int rtw_priv_mp_get(struct net_device *dev,
10390                            struct iw_request_info *info,
10391                            union iwreq_data *wdata, char *extra)
10392 {
10393
10394         struct iw_point *wrqu = (struct iw_point *)wdata;
10395         u32 subcmd = wrqu->flags;
10396
10397         switch (subcmd) {
10398         case WRITE_REG:
10399                 rtw_mp_write_reg(dev, info, wrqu, extra);
10400                 break;
10401         case WRITE_RF:
10402                 rtw_mp_write_rf(dev, info, wrqu, extra);
10403                 break;
10404         case MP_PHYPARA:
10405                 RTW_INFO("mp_get  MP_PHYPARA\n");
10406                 rtw_mp_phypara(dev, info, wrqu, extra);
10407                 break;
10408         case MP_CHANNEL:
10409                 RTW_INFO("set case mp_channel\n");
10410                 rtw_mp_channel(dev , info, wrqu, extra);
10411                 break;
10412         case READ_REG:
10413                 RTW_INFO("mp_get  READ_REG\n");
10414                 rtw_mp_read_reg(dev, info, wrqu, extra);
10415                 break;
10416         case READ_RF:
10417                 RTW_INFO("mp_get  READ_RF\n");
10418                 rtw_mp_read_rf(dev, info, wrqu, extra);
10419                 break;
10420         case MP_RATE:
10421                 RTW_INFO("set case mp_rate\n");
10422                 rtw_mp_rate(dev, info, wrqu, extra);
10423                 break;
10424         case MP_TXPOWER:
10425                 RTW_INFO("set case MP_TXPOWER\n");
10426                 rtw_mp_txpower(dev, info, wrqu, extra);
10427                 break;
10428         case MP_ANT_TX:
10429                 RTW_INFO("set case MP_ANT_TX\n");
10430                 rtw_mp_ant_tx(dev, info, wrqu, extra);
10431                 break;
10432         case MP_ANT_RX:
10433                 RTW_INFO("set case MP_ANT_RX\n");
10434                 rtw_mp_ant_rx(dev, info, wrqu, extra);
10435                 break;
10436         case MP_QUERY:
10437                 rtw_mp_trx_query(dev, info, wrqu, extra);
10438                 break;
10439         case MP_CTX:
10440                 RTW_INFO("set case MP_CTX\n");
10441                 rtw_mp_ctx(dev, info, wrqu, extra);
10442                 break;
10443         case MP_ARX:
10444                 RTW_INFO("set case MP_ARX\n");
10445                 rtw_mp_arx(dev, info, wrqu, extra);
10446                 break;
10447         case MP_DUMP:
10448                 RTW_INFO("set case MP_DUMP\n");
10449                 rtw_mp_dump(dev, info, wrqu, extra);
10450                 break;
10451         case MP_PSD:
10452                 RTW_INFO("set case MP_PSD\n");
10453                 rtw_mp_psd(dev, info, wrqu, extra);
10454                 break;
10455         case MP_THER:
10456                 RTW_INFO("set case MP_THER\n");
10457                 rtw_mp_thermal(dev, info, wrqu, extra);
10458                 break;
10459         case MP_PwrCtlDM:
10460                 RTW_INFO("set MP_PwrCtlDM\n");
10461                 rtw_mp_PwrCtlDM(dev, info, wrqu, extra);
10462                 break;
10463         case MP_QueryDrvStats:
10464                 RTW_INFO("mp_get MP_QueryDrvStats\n");
10465                 rtw_mp_QueryDrv(dev, info, wdata, extra);
10466                 break;
10467         case MP_PWRTRK:
10468                 RTW_INFO("set case MP_PWRTRK\n");
10469                 rtw_mp_pwrtrk(dev, info, wrqu, extra);
10470                 break;
10471         case EFUSE_SET:
10472                 RTW_INFO("set case efuse set\n");
10473                 rtw_mp_efuse_set(dev, info, wdata, extra);
10474                 break;
10475         case EFUSE_GET:
10476                 RTW_INFO("efuse get EFUSE_GET\n");
10477                 rtw_mp_efuse_get(dev, info, wdata, extra);
10478                 break;
10479         case MP_GET_TXPOWER_INX:
10480                 RTW_INFO("mp_get MP_GET_TXPOWER_INX\n");
10481                 rtw_mp_txpower_index(dev, info, wrqu, extra);
10482                 break;
10483         case MP_GETVER:
10484                 RTW_INFO("mp_get MP_GETVER\n");
10485                 rtw_mp_getver(dev, info, wdata, extra);
10486                 break;
10487         case MP_MON:
10488                 RTW_INFO("mp_get MP_MON\n");
10489                 rtw_mp_mon(dev, info, wdata, extra);
10490                 break;
10491         case EFUSE_MASK:
10492                 RTW_INFO("mp_get EFUSE_MASK\n");
10493                 rtw_efuse_mask_file(dev, info, wdata, extra);
10494                 break;
10495         case  EFUSE_FILE:
10496                 RTW_INFO("mp_get EFUSE_FILE\n");
10497                 rtw_efuse_file_map(dev, info, wdata, extra);
10498                 break;
10499         case  MP_TX:
10500                 RTW_INFO("mp_get MP_TX\n");
10501                 rtw_mp_tx(dev, info, wdata, extra);
10502                 break;
10503         case  MP_RX:
10504                 RTW_INFO("mp_get MP_RX\n");
10505                 rtw_mp_rx(dev, info, wdata, extra);
10506                 break;
10507         case MP_HW_TX_MODE:
10508                 RTW_INFO("mp_get MP_HW_TX_MODE\n");
10509                 rtw_mp_hwtx(dev, info, wdata, extra);
10510                 break;
10511         default:
10512                 return -EIO;
10513         }
10514
10515         return 0;
10516 }
10517 #endif /*#if defined(CONFIG_MP_INCLUDED)*/
10518
10519
10520 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
10521 #define DBG_MP_SDIO_INDIRECT_ACCESS 1
10522 static int rtw_mp_sd_iread(struct net_device *dev
10523                            , struct iw_request_info *info
10524                            , struct iw_point *wrqu
10525                            , char *extra)
10526 {
10527         char input[16];
10528         u8 width;
10529         unsigned long addr;
10530         u32 ret = 0;
10531         PADAPTER padapter = rtw_netdev_priv(dev);
10532
10533         if (wrqu->length > 16) {
10534                 RTW_INFO(FUNC_ADPT_FMT" wrqu->length:%d\n", FUNC_ADPT_ARG(padapter), wrqu->length);
10535                 ret = -EINVAL;
10536                 goto exit;
10537         }
10538
10539         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
10540                 RTW_INFO(FUNC_ADPT_FMT" copy_from_user fail\n", FUNC_ADPT_ARG(padapter));
10541                 ret = -EFAULT;
10542                 goto exit;
10543         }
10544
10545         _rtw_memset(extra, 0, wrqu->length);
10546
10547         if (sscanf(input, "%hhu,%lx", &width, &addr) != 2) {
10548                 RTW_INFO(FUNC_ADPT_FMT" sscanf fail\n", FUNC_ADPT_ARG(padapter));
10549                 ret = -EINVAL;
10550                 goto exit;
10551         }
10552
10553         if (addr > 0x3FFF) {
10554                 RTW_INFO(FUNC_ADPT_FMT" addr:0x%lx\n", FUNC_ADPT_ARG(padapter), addr);
10555                 ret = -EINVAL;
10556                 goto exit;
10557         }
10558
10559         if (DBG_MP_SDIO_INDIRECT_ACCESS)
10560                 RTW_INFO(FUNC_ADPT_FMT" width:%u, addr:0x%lx\n", FUNC_ADPT_ARG(padapter), width, addr);
10561
10562         switch (width) {
10563         case 1:
10564                 sprintf(extra, "0x%02x", rtw_sd_iread8(padapter, addr));
10565                 wrqu->length = strlen(extra);
10566                 break;
10567         case 2:
10568                 sprintf(extra, "0x%04x", rtw_sd_iread16(padapter, addr));
10569                 wrqu->length = strlen(extra);
10570                 break;
10571         case 4:
10572                 sprintf(extra, "0x%08x", rtw_sd_iread32(padapter, addr));
10573                 wrqu->length = strlen(extra);
10574                 break;
10575         default:
10576                 wrqu->length = 0;
10577                 ret = -EINVAL;
10578                 break;
10579         }
10580
10581 exit:
10582         return ret;
10583 }
10584
10585 static int rtw_mp_sd_iwrite(struct net_device *dev
10586                             , struct iw_request_info *info
10587                             , struct iw_point *wrqu
10588                             , char *extra)
10589 {
10590         char width;
10591         unsigned long addr, data;
10592         int ret = 0;
10593         PADAPTER padapter = rtw_netdev_priv(dev);
10594         char input[32];
10595
10596         if (wrqu->length > 32) {
10597                 RTW_INFO(FUNC_ADPT_FMT" wrqu->length:%d\n", FUNC_ADPT_ARG(padapter), wrqu->length);
10598                 ret = -EINVAL;
10599                 goto exit;
10600         }
10601
10602         if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
10603                 RTW_INFO(FUNC_ADPT_FMT" copy_from_user fail\n", FUNC_ADPT_ARG(padapter));
10604                 ret = -EFAULT;
10605                 goto exit;
10606         }
10607
10608         _rtw_memset(extra, 0, wrqu->length);
10609
10610         if (sscanf(input, "%hhu,%lx,%lx", &width, &addr, &data) != 3) {
10611                 RTW_INFO(FUNC_ADPT_FMT" sscanf fail\n", FUNC_ADPT_ARG(padapter));
10612                 ret = -EINVAL;
10613                 goto exit;
10614         }
10615
10616         if (addr > 0x3FFF) {
10617                 RTW_INFO(FUNC_ADPT_FMT" addr:0x%lx\n", FUNC_ADPT_ARG(padapter), addr);
10618                 ret = -EINVAL;
10619                 goto exit;
10620         }
10621
10622         if (DBG_MP_SDIO_INDIRECT_ACCESS)
10623                 RTW_INFO(FUNC_ADPT_FMT" width:%u, addr:0x%lx, data:0x%lx\n", FUNC_ADPT_ARG(padapter), width, addr, data);
10624
10625         switch (width) {
10626         case 1:
10627                 if (data > 0xFF) {
10628                         ret = -EINVAL;
10629                         break;
10630                 }
10631                 rtw_sd_iwrite8(padapter, addr, data);
10632                 break;
10633         case 2:
10634                 if (data > 0xFFFF) {
10635                         ret = -EINVAL;
10636                         break;
10637                 }
10638                 rtw_sd_iwrite16(padapter, addr, data);
10639                 break;
10640         case 4:
10641                 rtw_sd_iwrite32(padapter, addr, data);
10642                 break;
10643         default:
10644                 wrqu->length = 0;
10645                 ret = -EINVAL;
10646                 break;
10647         }
10648
10649 exit:
10650         return ret;
10651 }
10652 #endif /* CONFIG_SDIO_INDIRECT_ACCESS */
10653
10654 static int rtw_priv_set(struct net_device *dev,
10655                         struct iw_request_info *info,
10656                         union iwreq_data *wdata, char *extra)
10657 {
10658         struct iw_point *wrqu = (struct iw_point *)wdata;
10659         u32 subcmd = wrqu->flags;
10660         PADAPTER padapter = rtw_netdev_priv(dev);
10661
10662         if (padapter == NULL)
10663                 return -ENETDOWN;
10664
10665         if (padapter->bup == _FALSE) {
10666                 RTW_INFO(" %s fail =>(padapter->bup == _FALSE )\n", __FUNCTION__);
10667                 return -ENETDOWN;
10668         }
10669
10670         if (RTW_CANNOT_RUN(padapter)) {
10671                 RTW_INFO("%s fail =>(bSurpriseRemoved == _TRUE) || ( bDriverStopped == _TRUE)\n", __func__);
10672                 return -ENETDOWN;
10673         }
10674
10675         if (extra == NULL) {
10676                 wrqu->length = 0;
10677                 return -EIO;
10678         }
10679
10680         if (subcmd < MP_NULL) {
10681                 rtw_priv_mp_set(dev, info, wdata, extra);
10682                 return 0;
10683         }
10684
10685         switch (subcmd) {
10686 #ifdef CONFIG_WOWLAN
10687         case MP_WOW_ENABLE:
10688                 RTW_INFO("set case MP_WOW_ENABLE: %s\n", extra);
10689
10690                 rtw_wowlan_ctrl(dev, info, wdata, extra);
10691                 break;
10692         case MP_WOW_SET_PATTERN:
10693                 RTW_INFO("set case MP_WOW_SET_PATTERN: %s\n", extra);
10694                 rtw_wowlan_set_pattern(dev, info, wdata, extra);
10695                 break;
10696 #endif
10697 #ifdef CONFIG_AP_WOWLAN
10698         case MP_AP_WOW_ENABLE:
10699                 RTW_INFO("set case MP_AP_WOW_ENABLE: %s\n", extra);
10700                 rtw_ap_wowlan_ctrl(dev, info, wdata, extra);
10701                 break;
10702 #endif
10703 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
10704         case VENDOR_IE_SET:
10705                 RTW_INFO("set case VENDOR_IE_SET\n");
10706                 rtw_vendor_ie_set(dev , info , wdata , extra);
10707                 break;
10708 #endif
10709         default:
10710                 return -EIO;
10711         }
10712
10713         return 0;
10714 }
10715
10716
10717 static int rtw_priv_get(struct net_device *dev,
10718                         struct iw_request_info *info,
10719                         union iwreq_data *wdata, char *extra)
10720 {
10721         struct iw_point *wrqu = (struct iw_point *)wdata;
10722         u32 subcmd = wrqu->flags;
10723         PADAPTER padapter = rtw_netdev_priv(dev);
10724
10725
10726         if (padapter == NULL)
10727                 return -ENETDOWN;
10728
10729         if (padapter->bup == _FALSE) {
10730                 RTW_INFO(" %s fail =>(padapter->bup == _FALSE )\n", __FUNCTION__);
10731                 return -ENETDOWN;
10732         }
10733
10734         if (RTW_CANNOT_RUN(padapter)) {
10735                 RTW_INFO("%s fail =>(padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE)\n", __func__);
10736                 return -ENETDOWN;
10737         }
10738
10739         if (extra == NULL) {
10740                 wrqu->length = 0;
10741                 return -EIO;
10742         }
10743
10744         if (subcmd < MP_NULL) {
10745                 rtw_priv_mp_get(dev, info, wdata, extra);
10746                 return 0;
10747         }
10748
10749         switch (subcmd) {
10750 #if defined(CONFIG_RTL8723B)
10751         case MP_SetBT:
10752                 RTW_INFO("set MP_SetBT\n");
10753                 rtw_mp_SetBT(dev, info, wdata, extra);
10754                 break;
10755 #endif
10756 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
10757         case MP_SD_IREAD:
10758                 rtw_mp_sd_iread(dev, info, wrqu, extra);
10759                 break;
10760         case MP_SD_IWRITE:
10761                 rtw_mp_sd_iwrite(dev, info, wrqu, extra);
10762                 break;
10763 #endif
10764 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
10765         case VENDOR_IE_GET:
10766                 RTW_INFO("get case VENDOR_IE_GET\n");
10767                 rtw_vendor_ie_get(dev , info , wdata , extra);
10768                 break;
10769 #endif
10770         default:
10771                 return -EIO;
10772         }
10773
10774         rtw_msleep_os(10); /* delay 5ms for sending pkt before exit adb shell operation */
10775         return 0;
10776 }
10777
10778
10779
10780 static int rtw_wx_tdls_wfd_enable(struct net_device *dev,
10781                                   struct iw_request_info *info,
10782                                   union iwreq_data *wrqu, char *extra)
10783 {
10784         int ret = 0;
10785
10786 #ifdef CONFIG_TDLS
10787 #ifdef CONFIG_WFD
10788
10789         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10790
10791         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10792
10793         if (extra[0] == '0')
10794                 rtw_tdls_wfd_enable(padapter, 0);
10795         else
10796                 rtw_tdls_wfd_enable(padapter, 1);
10797
10798 #endif /* CONFIG_WFD */
10799 #endif /* CONFIG_TDLS */
10800
10801         return ret;
10802 }
10803
10804 static int rtw_tdls_weaksec(struct net_device *dev,
10805                             struct iw_request_info *info,
10806                             union iwreq_data *wrqu, char *extra)
10807 {
10808         int ret = 0;
10809
10810 #ifdef CONFIG_TDLS
10811
10812         u8 i, j;
10813         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10814
10815         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10816
10817         if (extra[0] == '0')
10818                 padapter->wdinfo.wfd_tdls_weaksec = 0;
10819         else
10820                 padapter->wdinfo.wfd_tdls_weaksec = 1;
10821
10822 #endif /* CONFIG_TDLS */
10823
10824         return ret;
10825 }
10826
10827
10828 static int rtw_tdls_enable(struct net_device *dev,
10829                            struct iw_request_info *info,
10830                            union iwreq_data *wrqu, char *extra)
10831 {
10832         int ret = 0;
10833
10834 #ifdef CONFIG_TDLS
10835
10836         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10837         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
10838         _irqL    irqL;
10839         _list   *plist, *phead;
10840         s32     index;
10841         struct sta_info *psta = NULL;
10842         struct  sta_priv *pstapriv = &padapter->stapriv;
10843         u8 tdls_sta[NUM_STA][ETH_ALEN];
10844         u8 empty_hwaddr[ETH_ALEN] = { 0x00 };
10845         struct tdls_txmgmt txmgmt;
10846
10847         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10848
10849         _rtw_memset(tdls_sta, 0x00, sizeof(tdls_sta));
10850         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10851
10852         if (extra[0] == '0') {
10853                 ptdlsinfo->tdls_enable = 0;
10854
10855                 if (pstapriv->asoc_sta_count == 1)
10856                         return ret;
10857
10858                 _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
10859                 for (index = 0; index < NUM_STA; index++) {
10860                         phead = &(pstapriv->sta_hash[index]);
10861                         plist = get_next(phead);
10862
10863                         while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
10864                                 psta = LIST_CONTAINOR(plist, struct sta_info , hash_list);
10865
10866                                 plist = get_next(plist);
10867
10868                                 if (psta->tdls_sta_state != TDLS_STATE_NONE)
10869                                         _rtw_memcpy(tdls_sta[index], psta->hwaddr, ETH_ALEN);
10870                         }
10871                 }
10872                 _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
10873
10874                 for (index = 0; index < NUM_STA; index++) {
10875                         if (!_rtw_memcmp(tdls_sta[index], empty_hwaddr, ETH_ALEN)) {
10876                                 RTW_INFO("issue tear down to "MAC_FMT"\n", MAC_ARG(tdls_sta[index]));
10877                                 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
10878                                 _rtw_memcpy(txmgmt.peer, tdls_sta[index], ETH_ALEN);
10879                                 issue_tdls_teardown(padapter, &txmgmt, _TRUE);
10880                         }
10881                 }
10882                 rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);
10883                 rtw_reset_tdls_info(padapter);
10884         }       else if (extra[0] == '1')
10885                 ptdlsinfo->tdls_enable = 1;
10886 #endif /* CONFIG_TDLS */
10887
10888         return ret;
10889 }
10890
10891 static int rtw_tdls_setup(struct net_device *dev,
10892                           struct iw_request_info *info,
10893                           union iwreq_data *wrqu, char *extra)
10894 {
10895         int ret = 0;
10896 #ifdef CONFIG_TDLS
10897         u8 i, j;
10898         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10899         struct tdls_txmgmt txmgmt;
10900 #ifdef CONFIG_WFD
10901         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
10902 #endif /* CONFIG_WFD */
10903
10904         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10905
10906         if (wrqu->data.length - 1 != 17) {
10907                 RTW_INFO("[%s] length:%d != 17\n", __FUNCTION__, (wrqu->data.length - 1));
10908                 return ret;
10909         }
10910
10911         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10912         for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
10913                 txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10914
10915 #ifdef CONFIG_WFD
10916         if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {
10917                 /* Weak Security situation with AP. */
10918                 if (0 == pwdinfo->wfd_tdls_weaksec)     {
10919                         /* Can't send the tdls setup request out!! */
10920                         RTW_INFO("[%s] Current link is not AES, "
10921                                 "SKIP sending the tdls setup request!!\n", __FUNCTION__);
10922                 } else
10923                         issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
10924         } else
10925 #endif /* CONFIG_WFD */
10926         {
10927                 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
10928         }
10929 #endif /* CONFIG_TDLS */
10930
10931         return ret;
10932 }
10933
10934 static int rtw_tdls_teardown(struct net_device *dev,
10935                              struct iw_request_info *info,
10936                              union iwreq_data *wrqu, char *extra)
10937 {
10938         int ret = 0;
10939
10940 #ifdef CONFIG_TDLS
10941
10942         u8 i, j;
10943         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10944         struct sta_info *ptdls_sta = NULL;
10945         struct tdls_txmgmt txmgmt;
10946
10947         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10948
10949         if (wrqu->data.length - 1 != 17 && wrqu->data.length - 1 != 19) {
10950                 RTW_INFO("[%s] length:%d != 17 or 19\n",
10951                          __FUNCTION__, (wrqu->data.length - 1));
10952                 return ret;
10953         }
10954
10955         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10956         for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
10957                 txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10958
10959         ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), txmgmt.peer);
10960
10961         if (ptdls_sta != NULL) {
10962                 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
10963                 if (wrqu->data.length - 1 == 19)
10964                         issue_tdls_teardown(padapter, &txmgmt, _FALSE);
10965                 else
10966                         issue_tdls_teardown(padapter, &txmgmt, _TRUE);
10967         } else
10968                 RTW_INFO("TDLS peer not found\n");
10969 #endif /* CONFIG_TDLS */
10970
10971         return ret;
10972 }
10973
10974 static int rtw_tdls_discovery(struct net_device *dev,
10975                               struct iw_request_info *info,
10976                               union iwreq_data *wrqu, char *extra)
10977 {
10978         int ret = 0;
10979
10980 #ifdef CONFIG_TDLS
10981
10982         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10983         struct tdls_txmgmt      txmgmt;
10984         int i = 0, j = 0;
10985
10986         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10987
10988         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10989         for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
10990                 txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10991
10992         issue_tdls_dis_req(padapter, &txmgmt);
10993
10994 #endif /* CONFIG_TDLS */
10995
10996         return ret;
10997 }
10998
10999 static int rtw_tdls_ch_switch(struct net_device *dev,
11000                               struct iw_request_info *info,
11001                               union iwreq_data *wrqu, char *extra)
11002 {
11003         int ret = 0;
11004
11005 #ifdef CONFIG_TDLS
11006 #ifdef CONFIG_TDLS_CH_SW
11007         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11008         struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
11009         u8 i, j;
11010         struct sta_info *ptdls_sta = NULL;
11011         u8 take_care_iqk;
11012
11013         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
11014
11015         if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
11016                 RTW_INFO("TDLS channel switch is not allowed\n");
11017                 return ret;
11018         }
11019
11020         for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
11021                 pchsw_info->addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
11022
11023         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pchsw_info->addr);
11024         if (ptdls_sta == NULL)
11025                 return ret;
11026
11027         pchsw_info->ch_sw_state |= TDLS_CH_SW_INITIATOR_STATE;
11028
11029         if (ptdls_sta != NULL) {
11030                 if (pchsw_info->off_ch_num == 0)
11031                         pchsw_info->off_ch_num = 11;
11032         } else
11033                 RTW_INFO("TDLS peer not found\n");
11034
11035         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
11036
11037         rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
11038         if (take_care_iqk == _TRUE) {
11039                 u8 central_chnl;
11040                 u8 bw_mode;
11041
11042                 bw_mode = (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20;
11043                 central_chnl = rtw_get_center_ch(pchsw_info->off_ch_num, bw_mode, pchsw_info->ch_offset);
11044                 if (rtw_hal_ch_sw_iqk_info_search(padapter, central_chnl, bw_mode) >= 0)
11045                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_START);
11046                 else
11047                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_PREPARE);
11048         } else
11049                 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_START);
11050
11051         /* issue_tdls_ch_switch_req(padapter, ptdls_sta); */
11052         /* RTW_INFO("issue tdls ch switch req\n"); */
11053
11054 #endif /* CONFIG_TDLS_CH_SW */
11055 #endif /* CONFIG_TDLS */
11056
11057         return ret;
11058 }
11059
11060 static int rtw_tdls_ch_switch_off(struct net_device *dev,
11061                                   struct iw_request_info *info,
11062                                   union iwreq_data *wrqu, char *extra)
11063 {
11064         int ret = 0;
11065
11066 #ifdef CONFIG_TDLS
11067 #ifdef CONFIG_TDLS_CH_SW
11068
11069         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11070         struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
11071         u8 i, j, mac_addr[ETH_ALEN];
11072         struct sta_info *ptdls_sta = NULL;
11073         struct tdls_txmgmt txmgmt;
11074
11075         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
11076
11077         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
11078
11079         if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
11080                 RTW_INFO("TDLS channel switch is not allowed\n");
11081                 return ret;
11082         }
11083
11084         if (wrqu->data.length >= 17) {
11085                 for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
11086                         mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
11087                 ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
11088         }
11089
11090         if (ptdls_sta == NULL)
11091                 return ret;
11092
11093         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_END_TO_BASE_CHNL);
11094
11095         pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |
11096                                      TDLS_CH_SWITCH_ON_STATE |
11097                                      TDLS_PEER_AT_OFF_STATE);
11098         _rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN);
11099
11100         ptdls_sta->ch_switch_time = 0;
11101         ptdls_sta->ch_switch_timeout = 0;
11102         _cancel_timer_ex(&ptdls_sta->ch_sw_timer);
11103         _cancel_timer_ex(&ptdls_sta->delay_timer);
11104         _cancel_timer_ex(&ptdls_sta->stay_on_base_chnl_timer);
11105         _cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);
11106
11107         rtw_pm_set_lps(padapter, PS_MODE_MAX);
11108 #endif /* CONFIG_TDLS_CH_SW */
11109 #endif /* CONFIG_TDLS */
11110
11111         return ret;
11112 }
11113
11114 static int rtw_tdls_dump_ch(struct net_device *dev,
11115                             struct iw_request_info *info,
11116                             union iwreq_data *wrqu, char *extra)
11117 {
11118         int ret = 0;
11119
11120 #ifdef CONFIG_TDLS
11121 #ifdef CONFIG_TDLS_CH_SW
11122         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11123         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11124
11125         RTW_INFO("[%s] dump_stack:%s\n", __FUNCTION__, extra);
11126
11127         extra[wrqu->data.length] = 0x00;
11128         ptdlsinfo->chsw_info.dump_stack = rtw_atoi(extra);
11129
11130         return ret;
11131
11132 #endif
11133 #endif /* CONFIG_TDLS */
11134
11135         return ret;
11136 }
11137
11138 static int rtw_tdls_off_ch_num(struct net_device *dev,
11139                                struct iw_request_info *info,
11140                                union iwreq_data *wrqu, char *extra)
11141 {
11142         int ret = 0;
11143
11144 #ifdef CONFIG_TDLS
11145 #ifdef CONFIG_TDLS_CH_SW
11146         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11147         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11148
11149         RTW_INFO("[%s] off_ch_num:%s\n", __FUNCTION__, extra);
11150
11151         extra[wrqu->data.length] = 0x00;
11152         ptdlsinfo->chsw_info.off_ch_num = rtw_atoi(extra);
11153
11154         return ret;
11155
11156 #endif
11157 #endif /* CONFIG_TDLS */
11158
11159         return ret;
11160 }
11161
11162 static int rtw_tdls_ch_offset(struct net_device *dev,
11163                               struct iw_request_info *info,
11164                               union iwreq_data *wrqu, char *extra)
11165 {
11166         int ret = 0;
11167
11168 #ifdef CONFIG_TDLS
11169 #ifdef CONFIG_TDLS_CH_SW
11170         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11171         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11172
11173         RTW_INFO("[%s] ch_offset:%s\n", __FUNCTION__, extra);
11174
11175         extra[wrqu->data.length] = 0x00;
11176         switch (rtw_atoi(extra)) {
11177         case SCA:
11178                 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
11179                 break;
11180
11181         case SCB:
11182                 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
11183                 break;
11184
11185         default:
11186                 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
11187                 break;
11188         }
11189
11190         return ret;
11191
11192 #endif
11193 #endif /* CONFIG_TDLS */
11194
11195         return ret;
11196 }
11197
11198 static int rtw_tdls_pson(struct net_device *dev,
11199                          struct iw_request_info *info,
11200                          union iwreq_data *wrqu, char *extra)
11201 {
11202         int ret = 0;
11203
11204 #ifdef CONFIG_TDLS
11205
11206         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11207         u8 i, j, mac_addr[ETH_ALEN];
11208         struct sta_info *ptdls_sta = NULL;
11209
11210         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
11211
11212         for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
11213                 mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
11214
11215         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
11216
11217         issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 1, 3, 500);
11218
11219 #endif /* CONFIG_TDLS */
11220
11221         return ret;
11222 }
11223
11224 static int rtw_tdls_psoff(struct net_device *dev,
11225                           struct iw_request_info *info,
11226                           union iwreq_data *wrqu, char *extra)
11227 {
11228         int ret = 0;
11229
11230 #ifdef CONFIG_TDLS
11231
11232         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11233         u8 i, j, mac_addr[ETH_ALEN];
11234         struct sta_info *ptdls_sta = NULL;
11235
11236         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
11237
11238         for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
11239                 mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
11240
11241         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
11242
11243         if (ptdls_sta)
11244                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 3, 500);
11245
11246 #endif /* CONFIG_TDLS */
11247
11248         return ret;
11249 }
11250
11251 static int rtw_tdls_setip(struct net_device *dev,
11252                           struct iw_request_info *info,
11253                           union iwreq_data *wrqu, char *extra)
11254 {
11255         int ret = 0;
11256
11257 #ifdef CONFIG_TDLS
11258 #ifdef CONFIG_WFD
11259
11260         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11261         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11262         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
11263         u8 i = 0, j = 0, k = 0, tag = 0;
11264
11265         RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
11266
11267         while (i < 4) {
11268                 for (j = 0; j < 4; j++) {
11269                         if (*(extra + j + tag) == '.' || *(extra + j + tag) == '\0') {
11270                                 if (j == 1)
11271                                         pwfd_info->ip_address[i] = convert_ip_addr('0', '0', *(extra + (j - 1) + tag));
11272                                 if (j == 2)
11273                                         pwfd_info->ip_address[i] = convert_ip_addr('0', *(extra + (j - 2) + tag), *(extra + (j - 1) + tag));
11274                                 if (j == 3)
11275                                         pwfd_info->ip_address[i] = convert_ip_addr(*(extra + (j - 3) + tag), *(extra + (j - 2) + tag), *(extra + (j - 1) + tag));
11276
11277                                 tag += j + 1;
11278                                 break;
11279                         }
11280                 }
11281                 i++;
11282         }
11283
11284         RTW_INFO("[%s] Set IP = %u.%u.%u.%u\n", __FUNCTION__,
11285                  ptdlsinfo->wfd_info->ip_address[0],
11286                  ptdlsinfo->wfd_info->ip_address[1],
11287                  ptdlsinfo->wfd_info->ip_address[2],
11288                  ptdlsinfo->wfd_info->ip_address[3]);
11289
11290 #endif /* CONFIG_WFD */
11291 #endif /* CONFIG_TDLS */
11292
11293         return ret;
11294 }
11295
11296 static int rtw_tdls_getip(struct net_device *dev,
11297                           struct iw_request_info *info,
11298                           union iwreq_data *wrqu, char *extra)
11299 {
11300         int ret = 0;
11301
11302 #ifdef CONFIG_TDLS
11303 #ifdef CONFIG_WFD
11304
11305         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11306         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11307         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
11308
11309         RTW_INFO("[%s]\n", __FUNCTION__);
11310
11311         sprintf(extra, "\n\n%u.%u.%u.%u\n",
11312                 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
11313                 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
11314
11315         RTW_INFO("[%s] IP=%u.%u.%u.%u\n", __FUNCTION__,
11316                  pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
11317                  pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
11318
11319         wrqu->data.length = strlen(extra);
11320
11321 #endif /* CONFIG_WFD */
11322 #endif /* CONFIG_TDLS */
11323
11324         return ret;
11325 }
11326
11327 static int rtw_tdls_getport(struct net_device *dev,
11328                             struct iw_request_info *info,
11329                             union iwreq_data *wrqu, char *extra)
11330 {
11331
11332         int ret = 0;
11333
11334 #ifdef CONFIG_TDLS
11335 #ifdef CONFIG_WFD
11336
11337         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11338         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11339         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
11340
11341         RTW_INFO("[%s]\n", __FUNCTION__);
11342
11343         sprintf(extra, "\n\n%d\n", pwfd_info->peer_rtsp_ctrlport);
11344         RTW_INFO("[%s] remote port = %d\n",
11345                  __FUNCTION__, pwfd_info->peer_rtsp_ctrlport);
11346
11347         wrqu->data.length = strlen(extra);
11348
11349 #endif /* CONFIG_WFD */
11350 #endif /* CONFIG_TDLS */
11351
11352         return ret;
11353
11354 }
11355
11356 /* WFDTDLS, for sigma test */
11357 static int rtw_tdls_dis_result(struct net_device *dev,
11358                                struct iw_request_info *info,
11359                                union iwreq_data *wrqu, char *extra)
11360 {
11361
11362         int ret = 0;
11363
11364 #ifdef CONFIG_TDLS
11365 #ifdef CONFIG_WFD
11366
11367         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11368         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11369
11370         RTW_INFO("[%s]\n", __FUNCTION__);
11371
11372         if (ptdlsinfo->dev_discovered == _TRUE) {
11373                 sprintf(extra, "\n\nDis=1\n");
11374                 ptdlsinfo->dev_discovered = _FALSE;
11375         }
11376
11377         wrqu->data.length = strlen(extra);
11378
11379 #endif /* CONFIG_WFD */
11380 #endif /* CONFIG_TDLS */
11381
11382         return ret;
11383
11384 }
11385
11386 /* WFDTDLS, for sigma test */
11387 static int rtw_wfd_tdls_status(struct net_device *dev,
11388                                struct iw_request_info *info,
11389                                union iwreq_data *wrqu, char *extra)
11390 {
11391
11392         int ret = 0;
11393
11394 #ifdef CONFIG_TDLS
11395
11396         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11397         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11398
11399         RTW_INFO("[%s]\n", __FUNCTION__);
11400
11401         sprintf(extra, "\nlink_established:%d\n"
11402                 "sta_cnt:%d\n"
11403                 "sta_maximum:%d\n"
11404                 "cur_channel:%d\n"
11405                 "tdls_enable:%d"
11406 #ifdef CONFIG_TDLS_CH_SW
11407                 "ch_sw_state:%08x\n"
11408                 "chsw_on:%d\n"
11409                 "off_ch_num:%d\n"
11410                 "cur_time:%d\n"
11411                 "ch_offset:%d\n"
11412                 "delay_swtich_back:%d"
11413 #endif
11414                 ,
11415                 ptdlsinfo->link_established, ptdlsinfo->sta_cnt,
11416                 ptdlsinfo->sta_maximum, ptdlsinfo->cur_channel,
11417                 ptdlsinfo->tdls_enable
11418 #ifdef CONFIG_TDLS_CH_SW
11419                 ,
11420                 ptdlsinfo->chsw_info.ch_sw_state,
11421                 ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on),
11422                 ptdlsinfo->chsw_info.off_ch_num,
11423                 ptdlsinfo->chsw_info.cur_time,
11424                 ptdlsinfo->chsw_info.ch_offset,
11425                 ptdlsinfo->chsw_info.delay_switch_back
11426 #endif
11427                );
11428
11429         wrqu->data.length = strlen(extra);
11430
11431 #endif /* CONFIG_TDLS */
11432
11433         return ret;
11434
11435 }
11436
11437 static int rtw_tdls_getsta(struct net_device *dev,
11438                            struct iw_request_info *info,
11439                            union iwreq_data *wrqu, char *extra)
11440 {
11441
11442         int ret = 0;
11443 #ifdef CONFIG_TDLS
11444         u8 i, j;
11445         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11446         u8 addr[ETH_ALEN] = {0};
11447         char charmac[17];
11448         struct sta_info *ptdls_sta = NULL;
11449
11450         RTW_INFO("[%s] %s %d\n", __FUNCTION__,
11451                  (char *)wrqu->data.pointer, wrqu->data.length - 1);
11452
11453         if (copy_from_user(charmac, wrqu->data.pointer + 9, 17)) {
11454                 ret = -EFAULT;
11455                 goto exit;
11456         }
11457
11458         RTW_INFO("[%s] %d, charmac:%s\n", __FUNCTION__, __LINE__, charmac);
11459         for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
11460                 addr[i] = key_2char2num(*(charmac + j), *(charmac + j + 1));
11461
11462         RTW_INFO("[%s] %d, charmac:%s, addr:"MAC_FMT"\n",
11463                  __FUNCTION__, __LINE__, charmac, MAC_ARG(addr));
11464         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, addr);
11465         if (ptdls_sta) {
11466                 sprintf(extra, "\n\ntdls_sta_state=0x%08x\n", ptdls_sta->tdls_sta_state);
11467                 RTW_INFO("\n\ntdls_sta_state=%d\n", ptdls_sta->tdls_sta_state);
11468         } else {
11469                 sprintf(extra, "\n\nNot found this sta\n");
11470                 RTW_INFO("\n\nNot found this sta\n");
11471         }
11472         wrqu->data.length = strlen(extra);
11473
11474 #endif /* CONFIG_TDLS */
11475 exit:
11476         return ret;
11477
11478 }
11479
11480 static int rtw_tdls_get_best_ch(struct net_device *dev,
11481                                 struct iw_request_info *info,
11482                                 union iwreq_data *wrqu, char *extra)
11483 {
11484 #ifdef CONFIG_FIND_BEST_CHANNEL
11485         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11486         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
11487         u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0;
11488
11489         for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
11490                 if (pmlmeext->channel_set[i].ChannelNum == 1)
11491                         index_24G = i;
11492                 if (pmlmeext->channel_set[i].ChannelNum == 36)
11493                         index_5G = i;
11494         }
11495
11496         for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
11497                 /* 2.4G */
11498                 if (pmlmeext->channel_set[i].ChannelNum == 6 || pmlmeext->channel_set[i].ChannelNum == 11) {
11499                         if (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count) {
11500                                 index_24G = i;
11501                                 best_channel_24G = pmlmeext->channel_set[i].ChannelNum;
11502                         }
11503                 }
11504
11505                 /* 5G */
11506                 if (pmlmeext->channel_set[i].ChannelNum >= 36
11507                     && pmlmeext->channel_set[i].ChannelNum < 140) {
11508                         /* Find primary channel */
11509                         if (((pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0)
11510                             && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
11511                                 index_5G = i;
11512                                 best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
11513                         }
11514                 }
11515
11516                 if (pmlmeext->channel_set[i].ChannelNum >= 149
11517                     && pmlmeext->channel_set[i].ChannelNum < 165) {
11518                         /* Find primary channel */
11519                         if (((pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0)
11520                             && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
11521                                 index_5G = i;
11522                                 best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
11523                         }
11524                 }
11525 #if 1 /* debug */
11526                 RTW_INFO("The rx cnt of channel %3d = %d\n",
11527                          pmlmeext->channel_set[i].ChannelNum,
11528                          pmlmeext->channel_set[i].rx_count);
11529 #endif
11530         }
11531
11532         sprintf(extra, "\nbest_channel_24G = %d\n", best_channel_24G);
11533         RTW_INFO("best_channel_24G = %d\n", best_channel_24G);
11534
11535         if (index_5G != 0) {
11536                 sprintf(extra, "best_channel_5G = %d\n", best_channel_5G);
11537                 RTW_INFO("best_channel_5G = %d\n", best_channel_5G);
11538         }
11539
11540         wrqu->data.length = strlen(extra);
11541
11542 #endif
11543
11544         return 0;
11545
11546 }
11547
11548 static int rtw_tdls(struct net_device *dev,
11549                     struct iw_request_info *info,
11550                     union iwreq_data *wrqu, char *extra)
11551 {
11552         int ret = 0;
11553
11554 #ifdef CONFIG_TDLS
11555
11556         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11557
11558         RTW_INFO("[%s] extra = %s\n", __FUNCTION__, extra);
11559
11560         if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {
11561                 RTW_INFO("Discard tdls oper since hal doesn't support tdls\n");
11562                 return 0;
11563         }
11564
11565         if (padapter->tdlsinfo.tdls_enable == 0) {
11566                 RTW_INFO("tdls haven't enabled\n");
11567                 return 0;
11568         }
11569
11570         /* WFD Sigma will use the tdls enable command to let the driver know we want to test the tdls now! */
11571
11572         if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
11573                 if (_rtw_memcmp(extra, "wfdenable=", 10)) {
11574                         wrqu->data.length -= 10;
11575                         rtw_wx_tdls_wfd_enable(dev, info, wrqu, &extra[10]);
11576                         return ret;
11577                 }
11578         }
11579
11580         if (_rtw_memcmp(extra, "weaksec=", 8)) {
11581                 wrqu->data.length -= 8;
11582                 rtw_tdls_weaksec(dev, info, wrqu, &extra[8]);
11583                 return ret;
11584         } else if (_rtw_memcmp(extra, "tdlsenable=", 11)) {
11585                 wrqu->data.length -= 11;
11586                 rtw_tdls_enable(dev, info, wrqu, &extra[11]);
11587                 return ret;
11588         }
11589
11590         if (_rtw_memcmp(extra, "setup=", 6)) {
11591                 wrqu->data.length -= 6;
11592                 rtw_tdls_setup(dev, info, wrqu, &extra[6]);
11593         } else if (_rtw_memcmp(extra, "tear=", 5)) {
11594                 wrqu->data.length -= 5;
11595                 rtw_tdls_teardown(dev, info, wrqu, &extra[5]);
11596         } else if (_rtw_memcmp(extra, "dis=", 4)) {
11597                 wrqu->data.length -= 4;
11598                 rtw_tdls_discovery(dev, info, wrqu, &extra[4]);
11599         } else if (_rtw_memcmp(extra, "swoff=", 6)) {
11600                 wrqu->data.length -= 6;
11601                 rtw_tdls_ch_switch_off(dev, info, wrqu, &extra[6]);
11602         } else if (_rtw_memcmp(extra, "sw=", 3)) {
11603                 wrqu->data.length -= 3;
11604                 rtw_tdls_ch_switch(dev, info, wrqu, &extra[3]);
11605         } else if (_rtw_memcmp(extra, "dumpstack=", 10)) {
11606                 wrqu->data.length -= 10;
11607                 rtw_tdls_dump_ch(dev, info, wrqu, &extra[10]);
11608         } else if (_rtw_memcmp(extra, "offchnum=", 9)) {
11609                 wrqu->data.length -= 9;
11610                 rtw_tdls_off_ch_num(dev, info, wrqu, &extra[9]);
11611         } else if (_rtw_memcmp(extra, "choffset=", 9)) {
11612                 wrqu->data.length -= 9;
11613                 rtw_tdls_ch_offset(dev, info, wrqu, &extra[9]);
11614         } else if (_rtw_memcmp(extra, "pson=", 5)) {
11615                 wrqu->data.length -= 5;
11616                 rtw_tdls_pson(dev, info, wrqu, &extra[5]);
11617         } else if (_rtw_memcmp(extra, "psoff=", 6)) {
11618                 wrqu->data.length -= 6;
11619                 rtw_tdls_psoff(dev, info, wrqu, &extra[6]);
11620         }
11621
11622 #ifdef CONFIG_WFD
11623         if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
11624                 if (_rtw_memcmp(extra, "setip=", 6)) {
11625                         wrqu->data.length -= 6;
11626                         rtw_tdls_setip(dev, info, wrqu, &extra[6]);
11627                 } else if (_rtw_memcmp(extra, "tprobe=", 6))
11628                         issue_tunneled_probe_req((_adapter *)rtw_netdev_priv(dev));
11629         }
11630 #endif /* CONFIG_WFD */
11631
11632 #endif /* CONFIG_TDLS */
11633
11634         return ret;
11635 }
11636
11637
11638 static int rtw_tdls_get(struct net_device *dev,
11639                         struct iw_request_info *info,
11640                         union iwreq_data *wrqu, char *extra)
11641 {
11642         int ret = 0;
11643
11644 #ifdef CONFIG_TDLS
11645
11646         RTW_INFO("[%s] extra = %s\n", __FUNCTION__, (char *) wrqu->data.pointer);
11647
11648         if (_rtw_memcmp(wrqu->data.pointer, "ip", 2))
11649                 rtw_tdls_getip(dev, info, wrqu, extra);
11650         else if (_rtw_memcmp(wrqu->data.pointer, "port", 4))
11651                 rtw_tdls_getport(dev, info, wrqu, extra);
11652         /* WFDTDLS, for sigma test */
11653         else if (_rtw_memcmp(wrqu->data.pointer, "dis", 3))
11654                 rtw_tdls_dis_result(dev, info, wrqu, extra);
11655         else if (_rtw_memcmp(wrqu->data.pointer, "status", 6))
11656                 rtw_wfd_tdls_status(dev, info, wrqu, extra);
11657         else if (_rtw_memcmp(wrqu->data.pointer, "tdls_sta=", 9))
11658                 rtw_tdls_getsta(dev, info, wrqu, extra);
11659         else if (_rtw_memcmp(wrqu->data.pointer, "best_ch", 7))
11660                 rtw_tdls_get_best_ch(dev, info, wrqu, extra);
11661 #endif /* CONFIG_TDLS */
11662
11663         return ret;
11664 }
11665
11666
11667
11668
11669
11670 #ifdef CONFIG_INTEL_WIDI
11671 static int rtw_widi_set(struct net_device *dev,
11672                         struct iw_request_info *info,
11673                         union iwreq_data *wrqu, char *extra)
11674 {
11675         int ret = 0;
11676         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11677
11678         process_intel_widi_cmd(padapter, extra);
11679
11680         return ret;
11681 }
11682
11683 static int rtw_widi_set_probe_request(struct net_device *dev,
11684                                       struct iw_request_info *info,
11685                                       union iwreq_data *wrqu, char *extra)
11686 {
11687         int     ret = 0;
11688         u8      *pbuf = NULL;
11689         _adapter        *padapter = (_adapter *)rtw_netdev_priv(dev);
11690
11691         pbuf = rtw_malloc(sizeof(l2_msg_t));
11692         if (pbuf) {
11693                 if (copy_from_user(pbuf, wrqu->data.pointer, wrqu->data.length))
11694                         ret = -EFAULT;
11695                 /* _rtw_memcpy(pbuf, wrqu->data.pointer, wrqu->data.length); */
11696
11697                 if (wrqu->data.flags == 0)
11698                         intel_widi_wk_cmd(padapter, INTEL_WIDI_ISSUE_PROB_WK, pbuf, sizeof(l2_msg_t));
11699                 else if (wrqu->data.flags == 1)
11700                         rtw_set_wfd_rds_sink_info(padapter, (l2_msg_t *)pbuf);
11701         }
11702         return ret;
11703 }
11704 #endif /* CONFIG_INTEL_WIDI */
11705
11706 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
11707
11708 #if defined(CONFIG_RTL8188E)
11709         #include <rtl8188e_hal.h>
11710         extern void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
11711         #define cal_txdesc_chksum rtl8188e_cal_txdesc_chksum
11712         #ifdef CONFIG_SDIO_HCI || defined(CONFIG_GSPI_HCI)
11713                 extern void rtl8188es_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
11714                 #define fill_default_txdesc rtl8188es_fill_default_txdesc
11715         #endif /* CONFIG_SDIO_HCI */
11716 #endif /* CONFIG_RTL8188E */
11717 #if defined(CONFIG_RTL8723B)
11718         extern void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc);
11719         #define cal_txdesc_chksum rtl8723b_cal_txdesc_chksum
11720         extern void rtl8723b_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
11721         #define fill_default_txdesc rtl8723b_fill_default_txdesc
11722 #endif /* CONFIG_RTL8723B */
11723
11724 #if defined(CONFIG_RTL8703B)
11725         /* extern void rtl8703b_cal_txdesc_chksum(struct tx_desc *ptxdesc); */
11726         #define cal_txdesc_chksum rtl8703b_cal_txdesc_chksum
11727         /* extern void rtl8703b_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf); */
11728         #define fill_default_txdesc rtl8703b_fill_default_txdesc
11729 #endif /* CONFIG_RTL8703B */
11730
11731 #if defined(CONFIG_RTL8723D)
11732         /* extern void rtl8723d_cal_txdesc_chksum(struct tx_desc *ptxdesc); */
11733         #define cal_txdesc_chksum rtl8723d_cal_txdesc_chksum
11734         /* extern void rtl8723d_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf); */
11735         #define fill_default_txdesc rtl8723d_fill_default_txdesc
11736 #endif /* CONFIG_RTL8723D */
11737
11738 #if defined(CONFIG_RTL8192E)
11739         extern void rtl8192e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
11740         #define cal_txdesc_chksum rtl8192e_cal_txdesc_chksum
11741         #ifdef CONFIG_SDIO_HCI || defined(CONFIG_GSPI_HCI)
11742                 extern void rtl8192es_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
11743                 #define fill_default_txdesc rtl8192es_fill_default_txdesc
11744         #endif /* CONFIG_SDIO_HCI */
11745 #endif /* CONFIG_RTL8192E */
11746
11747 static s32 initLoopback(PADAPTER padapter)
11748 {
11749         PLOOPBACKDATA ploopback;
11750
11751
11752         if (padapter->ploopback == NULL) {
11753                 ploopback = (PLOOPBACKDATA)rtw_zmalloc(sizeof(LOOPBACKDATA));
11754                 if (ploopback == NULL)
11755                         return -ENOMEM;
11756
11757                 _rtw_init_sema(&ploopback->sema, 0);
11758                 ploopback->bstop = _TRUE;
11759                 ploopback->cnt = 0;
11760                 ploopback->size = 300;
11761                 _rtw_memset(ploopback->msg, 0, sizeof(ploopback->msg));
11762
11763                 padapter->ploopback = ploopback;
11764         }
11765
11766         return 0;
11767 }
11768
11769 static void freeLoopback(PADAPTER padapter)
11770 {
11771         PLOOPBACKDATA ploopback;
11772
11773
11774         ploopback = padapter->ploopback;
11775         if (ploopback) {
11776                 rtw_mfree((u8 *)ploopback, sizeof(LOOPBACKDATA));
11777                 padapter->ploopback = NULL;
11778         }
11779 }
11780
11781 static s32 initpseudoadhoc(PADAPTER padapter)
11782 {
11783         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
11784         s32 err;
11785
11786         networkType = Ndis802_11IBSS;
11787         err = rtw_set_802_11_infrastructure_mode(padapter, networkType);
11788         if (err == _FALSE)
11789                 return _FAIL;
11790
11791         err = rtw_setopmode_cmd(padapter, networkType, _TRUE);
11792         if (err == _FAIL)
11793                 return _FAIL;
11794
11795         return _SUCCESS;
11796 }
11797
11798 static s32 createpseudoadhoc(PADAPTER padapter)
11799 {
11800         NDIS_802_11_AUTHENTICATION_MODE authmode;
11801         struct mlme_priv *pmlmepriv;
11802         NDIS_802_11_SSID *passoc_ssid;
11803         WLAN_BSSID_EX *pdev_network;
11804         u8 *pibss;
11805         u8 ssid[] = "pseduo_ad-hoc";
11806         s32 err;
11807         _irqL irqL;
11808
11809
11810         pmlmepriv = &padapter->mlmepriv;
11811
11812         authmode = Ndis802_11AuthModeOpen;
11813         err = rtw_set_802_11_authentication_mode(padapter, authmode);
11814         if (err == _FALSE)
11815                 return _FAIL;
11816
11817         passoc_ssid = &pmlmepriv->assoc_ssid;
11818         _rtw_memset(passoc_ssid, 0, sizeof(NDIS_802_11_SSID));
11819         passoc_ssid->SsidLength = sizeof(ssid) - 1;
11820         _rtw_memcpy(passoc_ssid->Ssid, ssid, passoc_ssid->SsidLength);
11821
11822         pdev_network = &padapter->registrypriv.dev_network;
11823         pibss = padapter->registrypriv.dev_network.MacAddress;
11824         _rtw_memcpy(&pdev_network->Ssid, passoc_ssid, sizeof(NDIS_802_11_SSID));
11825
11826         rtw_update_registrypriv_dev_network(padapter);
11827         rtw_generate_random_ibss(pibss);
11828
11829         _enter_critical_bh(&pmlmepriv->lock, &irqL);
11830         /*pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;*/
11831         init_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
11832
11833         _exit_critical_bh(&pmlmepriv->lock, &irqL);
11834
11835 #if 0
11836         err = rtw_create_ibss_cmd(padapter, 0);
11837         if (err == _FAIL)
11838                 return _FAIL;
11839 #else
11840         {
11841                 struct wlan_network *pcur_network;
11842                 struct sta_info *psta;
11843
11844                 /* 3  create a new psta */
11845                 pcur_network = &pmlmepriv->cur_network;
11846
11847                 /* clear psta in the cur_network, if any */
11848                 psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
11849                 if (psta)
11850                         rtw_free_stainfo(padapter, psta);
11851
11852                 psta = rtw_alloc_stainfo(&padapter->stapriv, pibss);
11853                 if (psta == NULL)
11854                         return _FAIL;
11855
11856                 /* 3  join psudo AdHoc */
11857                 pcur_network->join_res = 1;
11858                 pcur_network->aid = psta->aid = 1;
11859                 _rtw_memcpy(&pcur_network->network, pdev_network, get_WLAN_BSSID_EX_sz(pdev_network));
11860
11861                 /* set msr to WIFI_FW_ADHOC_STATE */
11862                 padapter->hw_port = HW_PORT0;
11863                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
11864
11865         }
11866 #endif
11867
11868         return _SUCCESS;
11869 }
11870
11871 static struct xmit_frame *createloopbackpkt(PADAPTER padapter, u32 size)
11872 {
11873         struct xmit_priv *pxmitpriv;
11874         struct xmit_frame *pframe;
11875         struct xmit_buf *pxmitbuf;
11876         struct pkt_attrib *pattrib;
11877         struct tx_desc *desc;
11878         u8 *pkt_start, *pkt_end, *ptr;
11879         struct rtw_ieee80211_hdr *hdr;
11880         s32 bmcast;
11881         _irqL irqL;
11882
11883
11884         if ((TXDESC_SIZE + WLANHDR_OFFSET + size) > MAX_XMITBUF_SZ)
11885                 return NULL;
11886
11887         pxmitpriv = &padapter->xmitpriv;
11888         pframe = NULL;
11889
11890         /* 2 1. allocate xmit frame */
11891         pframe = rtw_alloc_xmitframe(pxmitpriv);
11892         if (pframe == NULL)
11893                 return NULL;
11894         pframe->padapter = padapter;
11895
11896         /* 2 2. allocate xmit buffer */
11897         _enter_critical_bh(&pxmitpriv->lock, &irqL);
11898         pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
11899         _exit_critical_bh(&pxmitpriv->lock, &irqL);
11900         if (pxmitbuf == NULL) {
11901                 rtw_free_xmitframe(pxmitpriv, pframe);
11902                 return NULL;
11903         }
11904
11905         pframe->pxmitbuf = pxmitbuf;
11906         pframe->buf_addr = pxmitbuf->pbuf;
11907         pxmitbuf->priv_data = pframe;
11908
11909         /* 2 3. update_attrib() */
11910         pattrib = &pframe->attrib;
11911
11912         /* init xmitframe attribute */
11913         _rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
11914
11915         pattrib->ether_type = 0x8723;
11916         _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
11917         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
11918         _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
11919         _rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
11920
11921         /*      pattrib->dhcp_pkt = 0;
11922          *      pattrib->pktlen = 0; */
11923         pattrib->ack_policy = 0;
11924         /*      pattrib->pkt_hdrlen = ETH_HLEN; */
11925         pattrib->hdrlen = WLAN_HDR_A3_LEN;
11926         pattrib->subtype = WIFI_DATA;
11927         pattrib->priority = 0;
11928         pattrib->qsel = pattrib->priority;
11929         /*      do_queue_select(padapter, pattrib); */
11930         pattrib->nr_frags = 1;
11931         pattrib->encrypt = 0;
11932         pattrib->bswenc = _FALSE;
11933         pattrib->qos_en = _FALSE;
11934
11935         bmcast = IS_MCAST(pattrib->ra);
11936         if (bmcast) {
11937                 pattrib->mac_id = 1;
11938                 pattrib->psta = rtw_get_bcmc_stainfo(padapter);
11939         } else {
11940                 pattrib->mac_id = 0;
11941                 pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
11942         }
11943
11944         pattrib->pktlen = size;
11945         pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
11946
11947         /* 2 4. fill TX descriptor */
11948         desc = (struct tx_desc *)pframe->buf_addr;
11949         _rtw_memset(desc, 0, TXDESC_SIZE);
11950
11951         fill_default_txdesc(pframe, (u8 *)desc);
11952
11953         /* Hw set sequence number */
11954         ((PTXDESC)desc)->hwseq_en = 0; /* HWSEQ_EN, 0:disable, 1:enable
11955  * ((PTXDESC)desc)->hwseq_sel = 0;  */ /* HWSEQ_SEL */
11956
11957         ((PTXDESC)desc)->disdatafb = 1;
11958
11959         /* convert to little endian */
11960         desc->txdw0 = cpu_to_le32(desc->txdw0);
11961         desc->txdw1 = cpu_to_le32(desc->txdw1);
11962         desc->txdw2 = cpu_to_le32(desc->txdw2);
11963         desc->txdw3 = cpu_to_le32(desc->txdw3);
11964         desc->txdw4 = cpu_to_le32(desc->txdw4);
11965         desc->txdw5 = cpu_to_le32(desc->txdw5);
11966         desc->txdw6 = cpu_to_le32(desc->txdw6);
11967         desc->txdw7 = cpu_to_le32(desc->txdw7);
11968 #ifdef CONFIG_PCI_HCI
11969         desc->txdw8 = cpu_to_le32(desc->txdw8);
11970         desc->txdw9 = cpu_to_le32(desc->txdw9);
11971         desc->txdw10 = cpu_to_le32(desc->txdw10);
11972         desc->txdw11 = cpu_to_le32(desc->txdw11);
11973         desc->txdw12 = cpu_to_le32(desc->txdw12);
11974         desc->txdw13 = cpu_to_le32(desc->txdw13);
11975         desc->txdw14 = cpu_to_le32(desc->txdw14);
11976         desc->txdw15 = cpu_to_le32(desc->txdw15);
11977 #endif
11978
11979         cal_txdesc_chksum(desc);
11980
11981         /* 2 5. coalesce */
11982         pkt_start = pframe->buf_addr + TXDESC_SIZE;
11983         pkt_end = pkt_start + pattrib->last_txcmdsz;
11984
11985         /* 3 5.1. make wlan header, make_wlanhdr() */
11986         hdr = (struct rtw_ieee80211_hdr *)pkt_start;
11987         SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
11988         _rtw_memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /* DA */
11989         _rtw_memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /* SA */
11990         _rtw_memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /* RA, BSSID */
11991
11992         /* 3 5.2. make payload */
11993         ptr = pkt_start + pattrib->hdrlen;
11994         get_random_bytes(ptr, pkt_end - ptr);
11995
11996         pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
11997         pxmitbuf->ptail += pxmitbuf->len;
11998
11999         return pframe;
12000 }
12001
12002 static void freeloopbackpkt(PADAPTER padapter, struct xmit_frame *pframe)
12003 {
12004         struct xmit_priv *pxmitpriv;
12005         struct xmit_buf *pxmitbuf;
12006
12007
12008         pxmitpriv = &padapter->xmitpriv;
12009         pxmitbuf = pframe->pxmitbuf;
12010
12011         rtw_free_xmitframe(pxmitpriv, pframe);
12012         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
12013 }
12014
12015 static void printdata(u8 *pbuf, u32 len)
12016 {
12017         u32 i, val;
12018
12019
12020         for (i = 0; (i + 4) <= len; i += 4) {
12021                 printk("%08X", *(u32 *)(pbuf + i));
12022                 if ((i + 4) & 0x1F)
12023                         printk(" ");
12024                 else
12025                         printk("\n");
12026         }
12027
12028         if (i < len) {
12029 #ifdef CONFIG_BIG_ENDIAN
12030                 for (; i < len, i++)
12031                         printk("%02X", pbuf + i);
12032 #else /* CONFIG_LITTLE_ENDIAN */
12033 #if 0
12034                 val = 0;
12035                 _rtw_memcpy(&val, pbuf + i, len - i);
12036                 printk("%8X", val);
12037 #else
12038                 u8 str[9];
12039                 u8 n;
12040                 val = 0;
12041                 n = len - i;
12042                 _rtw_memcpy(&val, pbuf + i, n);
12043                 sprintf(str, "%08X", val);
12044                 n = (4 - n) * 2;
12045                 printk("%8s", str + n);
12046 #endif
12047 #endif /* CONFIG_LITTLE_ENDIAN */
12048         }
12049         printk("\n");
12050 }
12051
12052 static u8 pktcmp(PADAPTER padapter, u8 *txbuf, u32 txsz, u8 *rxbuf, u32 rxsz)
12053 {
12054         PHAL_DATA_TYPE phal;
12055         struct recv_stat *prxstat;
12056         struct recv_stat report;
12057         PRXREPORT prxreport;
12058         u32 drvinfosize;
12059         u32 rxpktsize;
12060         u8 fcssize;
12061         u8 ret = _FALSE;
12062
12063         prxstat = (struct recv_stat *)rxbuf;
12064         report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
12065         report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
12066         report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
12067         report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
12068         report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
12069         report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
12070
12071         prxreport = (PRXREPORT)&report;
12072         drvinfosize = prxreport->drvinfosize << 3;
12073         rxpktsize = prxreport->pktlen;
12074
12075         phal = GET_HAL_DATA(padapter);
12076         if (phal->ReceiveConfig & RCR_APPFCS)
12077                 fcssize = IEEE80211_FCS_LEN;
12078         else
12079                 fcssize = 0;
12080
12081         if ((txsz - TXDESC_SIZE) != (rxpktsize - fcssize)) {
12082                 RTW_INFO("%s: ERROR! size not match tx/rx=%d/%d !\n",
12083                          __func__, txsz - TXDESC_SIZE, rxpktsize - fcssize);
12084                 ret = _FALSE;
12085         } else {
12086                 ret = _rtw_memcmp(txbuf + TXDESC_SIZE, \
12087                                   rxbuf + RXDESC_SIZE + drvinfosize, \
12088                                   txsz - TXDESC_SIZE);
12089                 if (ret == _FALSE)
12090                         RTW_INFO("%s: ERROR! pkt content mismatch!\n", __func__);
12091         }
12092
12093         if (ret == _FALSE) {
12094                 RTW_INFO("\n%s: TX PKT total=%d, desc=%d, content=%d\n",
12095                          __func__, txsz, TXDESC_SIZE, txsz - TXDESC_SIZE);
12096                 RTW_INFO("%s: TX DESC size=%d\n", __func__, TXDESC_SIZE);
12097                 printdata(txbuf, TXDESC_SIZE);
12098                 RTW_INFO("%s: TX content size=%d\n", __func__, txsz - TXDESC_SIZE);
12099                 printdata(txbuf + TXDESC_SIZE, txsz - TXDESC_SIZE);
12100
12101                 RTW_INFO("\n%s: RX PKT read=%d offset=%d(%d,%d) content=%d\n",
12102                         __func__, rxsz, RXDESC_SIZE + drvinfosize, RXDESC_SIZE, drvinfosize, rxpktsize);
12103                 if (rxpktsize != 0) {
12104                         RTW_INFO("%s: RX DESC size=%d\n", __func__, RXDESC_SIZE);
12105                         printdata(rxbuf, RXDESC_SIZE);
12106                         RTW_INFO("%s: RX drvinfo size=%d\n", __func__, drvinfosize);
12107                         printdata(rxbuf + RXDESC_SIZE, drvinfosize);
12108                         RTW_INFO("%s: RX content size=%d\n", __func__, rxpktsize);
12109                         printdata(rxbuf + RXDESC_SIZE + drvinfosize, rxpktsize);
12110                 } else {
12111                         RTW_INFO("%s: RX data size=%d\n", __func__, rxsz);
12112                         printdata(rxbuf, rxsz);
12113                 }
12114         }
12115
12116         return ret;
12117 }
12118
12119 thread_return lbk_thread(thread_context context)
12120 {
12121         s32 err;
12122         PADAPTER padapter;
12123         PLOOPBACKDATA ploopback;
12124         struct xmit_frame *pxmitframe;
12125         u32 cnt, ok, fail, headerlen;
12126         u32 pktsize;
12127         u32 ff_hwaddr;
12128
12129
12130         padapter = (PADAPTER)context;
12131         ploopback = padapter->ploopback;
12132         if (ploopback == NULL)
12133                 return -1;
12134         cnt = 0;
12135         ok = 0;
12136         fail = 0;
12137
12138         daemonize("%s", "RTW_LBK_THREAD");
12139         allow_signal(SIGTERM);
12140
12141         do {
12142                 if (ploopback->size == 0) {
12143                         get_random_bytes(&pktsize, 4);
12144                         pktsize = (pktsize % 1535) + 1; /* 1~1535 */
12145                 } else
12146                         pktsize = ploopback->size;
12147
12148                 pxmitframe = createloopbackpkt(padapter, pktsize);
12149                 if (pxmitframe == NULL) {
12150                         sprintf(ploopback->msg, "loopback FAIL! 3. create Packet FAIL!");
12151                         break;
12152                 }
12153
12154                 ploopback->txsize = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
12155                 _rtw_memcpy(ploopback->txbuf, pxmitframe->buf_addr, ploopback->txsize);
12156                 ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
12157                 cnt++;
12158                 RTW_INFO("%s: wirte port cnt=%d size=%d\n", __func__, cnt, ploopback->txsize);
12159                 pxmitframe->pxmitbuf->pdata = ploopback->txbuf;
12160                 rtw_write_port(padapter, ff_hwaddr, ploopback->txsize, (u8 *)pxmitframe->pxmitbuf);
12161
12162                 /* wait for rx pkt */
12163                 _rtw_down_sema(&ploopback->sema);
12164
12165                 err = pktcmp(padapter, ploopback->txbuf, ploopback->txsize, ploopback->rxbuf, ploopback->rxsize);
12166                 if (err == _TRUE)
12167                         ok++;
12168                 else
12169                         fail++;
12170
12171                 ploopback->txsize = 0;
12172                 _rtw_memset(ploopback->txbuf, 0, 0x8000);
12173                 ploopback->rxsize = 0;
12174                 _rtw_memset(ploopback->rxbuf, 0, 0x8000);
12175
12176                 freeloopbackpkt(padapter, pxmitframe);
12177                 pxmitframe = NULL;
12178
12179                 if (signal_pending(current))
12180                         flush_signals(current);
12181
12182                 if ((ploopback->bstop == _TRUE) ||
12183                     ((ploopback->cnt != 0) && (ploopback->cnt == cnt))) {
12184                         u32 ok_rate, fail_rate, all;
12185                         all = cnt;
12186                         ok_rate = (ok * 100) / all;
12187                         fail_rate = (fail * 100) / all;
12188                         sprintf(ploopback->msg, \
12189                                 "loopback result: ok=%d%%(%d/%d),error=%d%%(%d/%d)", \
12190                                 ok_rate, ok, all, fail_rate, fail, all);
12191                         break;
12192                 }
12193         } while (1);
12194
12195         ploopback->bstop = _TRUE;
12196
12197         thread_exit();
12198 }
12199
12200 static void loopbackTest(PADAPTER padapter, u32 cnt, u32 size, u8 *pmsg)
12201 {
12202         PLOOPBACKDATA ploopback;
12203         u32 len;
12204         s32 err;
12205
12206
12207         ploopback = padapter->ploopback;
12208
12209         if (ploopback) {
12210                 if (ploopback->bstop == _FALSE) {
12211                         ploopback->bstop = _TRUE;
12212                         _rtw_up_sema(&ploopback->sema);
12213                 }
12214                 len = 0;
12215                 do {
12216                         len = strlen(ploopback->msg);
12217                         if (len)
12218                                 break;
12219                         rtw_msleep_os(1);
12220                 } while (1);
12221                 _rtw_memcpy(pmsg, ploopback->msg, len + 1);
12222                 freeLoopback(padapter);
12223
12224                 return;
12225         }
12226
12227         /* disable dynamic algorithm     */
12228         rtw_phydm_ability_backup(padapter);
12229         rtw_phydm_func_disable_all(padapter);
12230
12231         /* create pseudo ad-hoc connection */
12232         err = initpseudoadhoc(padapter);
12233         if (err == _FAIL) {
12234                 sprintf(pmsg, "loopback FAIL! 1.1 init ad-hoc FAIL!");
12235                 return;
12236         }
12237
12238         err = createpseudoadhoc(padapter);
12239         if (err == _FAIL) {
12240                 sprintf(pmsg, "loopback FAIL! 1.2 create ad-hoc master FAIL!");
12241                 return;
12242         }
12243
12244         err = initLoopback(padapter);
12245         if (err) {
12246                 sprintf(pmsg, "loopback FAIL! 2. init FAIL! error code=%d", err);
12247                 return;
12248         }
12249
12250         ploopback = padapter->ploopback;
12251
12252         ploopback->bstop = _FALSE;
12253         ploopback->cnt = cnt;
12254         ploopback->size = size;
12255         ploopback->lbkthread = kthread_run(lbk_thread, padapter, "RTW_LBK_THREAD");
12256         if (IS_ERR(padapter->lbkthread)) {
12257                 freeLoopback(padapter);
12258                 sprintf(pmsg, "loopback start FAIL! cnt=%d", cnt);
12259                 return;
12260         }
12261
12262         sprintf(pmsg, "loopback start! cnt=%d", cnt);
12263 }
12264 #endif /* CONFIG_MAC_LOOPBACK_DRIVER */
12265
12266 static int rtw_test(
12267         struct net_device *dev,
12268         struct iw_request_info *info,
12269         union iwreq_data *wrqu, char *extra)
12270 {
12271         u32 len;
12272         u8 *pbuf, *pch;
12273         char *ptmp;
12274         u8 *delim = ",";
12275         PADAPTER padapter = rtw_netdev_priv(dev);
12276
12277
12278         RTW_INFO("+%s\n", __func__);
12279         len = wrqu->data.length;
12280
12281         pbuf = (u8 *)rtw_zmalloc(len);
12282         if (pbuf == NULL) {
12283                 RTW_INFO("%s: no memory!\n", __func__);
12284                 return -ENOMEM;
12285         }
12286
12287         if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
12288                 rtw_mfree(pbuf, len);
12289                 RTW_INFO("%s: copy from user fail!\n", __func__);
12290                 return -EFAULT;
12291         }
12292         RTW_INFO("%s: string=\"%s\"\n", __func__, pbuf);
12293
12294         ptmp = (char *)pbuf;
12295         pch = strsep(&ptmp, delim);
12296         if ((pch == NULL) || (strlen(pch) == 0)) {
12297                 rtw_mfree(pbuf, len);
12298                 RTW_INFO("%s: parameter error(level 1)!\n", __func__);
12299                 return -EFAULT;
12300         }
12301
12302 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
12303         if (strcmp(pch, "loopback") == 0) {
12304                 s32 cnt = 0;
12305                 u32 size = 64;
12306
12307                 pch = strsep(&ptmp, delim);
12308                 if ((pch == NULL) || (strlen(pch) == 0)) {
12309                         rtw_mfree(pbuf, len);
12310                         RTW_INFO("%s: parameter error(level 2)!\n", __func__);
12311                         return -EFAULT;
12312                 }
12313
12314                 sscanf(pch, "%d", &cnt);
12315                 RTW_INFO("%s: loopback cnt=%d\n", __func__, cnt);
12316
12317                 pch = strsep(&ptmp, delim);
12318                 if ((pch == NULL) || (strlen(pch) == 0)) {
12319                         rtw_mfree(pbuf, len);
12320                         RTW_INFO("%s: parameter error(level 2)!\n", __func__);
12321                         return -EFAULT;
12322                 }
12323
12324                 sscanf(pch, "%d", &size);
12325                 RTW_INFO("%s: loopback size=%d\n", __func__, size);
12326
12327                 loopbackTest(padapter, cnt, size, extra);
12328                 wrqu->data.length = strlen(extra) + 1;
12329
12330                 goto free_buf;
12331         }
12332 #endif
12333
12334
12335 #ifdef CONFIG_BT_COEXIST
12336         if (strcmp(pch, "bton") == 0) {
12337                 rtw_btcoex_SetManualControl(padapter, _FALSE);
12338                 goto free_buf;
12339         } else if (strcmp(pch, "btoff") == 0) {
12340                 rtw_btcoex_SetManualControl(padapter, _TRUE);
12341                 goto free_buf;
12342         }
12343 #endif
12344
12345         if (strcmp(pch, "h2c") == 0) {
12346                 u8 param[8];
12347                 u8 count = 0;
12348                 u32 tmp;
12349                 u8 i;
12350                 u32 pos;
12351                 u8 ret;
12352
12353                 do {
12354                         pch = strsep(&ptmp, delim);
12355                         if ((pch == NULL) || (strlen(pch) == 0))
12356                                 break;
12357
12358                         sscanf(pch, "%x", &tmp);
12359                         param[count++] = (u8)tmp;
12360                 } while (count < 8);
12361
12362                 if (count == 0) {
12363                         rtw_mfree(pbuf, len);
12364                         RTW_INFO("%s: parameter error(level 2)!\n", __func__);
12365                         return -EFAULT;
12366                 }
12367
12368                 ret = rtw_test_h2c_cmd(padapter, param, count);
12369
12370                 pos = sprintf(extra, "H2C ID=0x%02x content=", param[0]);
12371                 for (i = 1; i < count; i++)
12372                         pos += sprintf(extra + pos, "%02x,", param[i]);
12373                 extra[pos] = 0;
12374                 pos--;
12375                 pos += sprintf(extra + pos, " %s", ret == _FAIL ? "FAIL" : "OK");
12376
12377                 wrqu->data.length = strlen(extra) + 1;
12378
12379                 goto free_buf;
12380         }
12381
12382 free_buf:
12383         rtw_mfree(pbuf, len);
12384         return 0;
12385 }
12386
12387 static iw_handler rtw_handlers[] = {
12388         NULL,                                   /* SIOCSIWCOMMIT */
12389         rtw_wx_get_name,                /* SIOCGIWNAME */
12390         dummy,                                  /* SIOCSIWNWID */
12391         dummy,                                  /* SIOCGIWNWID */
12392         rtw_wx_set_freq,                /* SIOCSIWFREQ */
12393         rtw_wx_get_freq,                /* SIOCGIWFREQ */
12394         rtw_wx_set_mode,                /* SIOCSIWMODE */
12395         rtw_wx_get_mode,                /* SIOCGIWMODE */
12396         dummy,                                  /* SIOCSIWSENS */
12397         rtw_wx_get_sens,                /* SIOCGIWSENS */
12398         NULL,                                   /* SIOCSIWRANGE */
12399         rtw_wx_get_range,               /* SIOCGIWRANGE */
12400         rtw_wx_set_priv,                /* SIOCSIWPRIV */
12401         NULL,                                   /* SIOCGIWPRIV */
12402         NULL,                                   /* SIOCSIWSTATS */
12403         NULL,                                   /* SIOCGIWSTATS */
12404         dummy,                                  /* SIOCSIWSPY */
12405         dummy,                                  /* SIOCGIWSPY */
12406         NULL,                                   /* SIOCGIWTHRSPY */
12407         NULL,                                   /* SIOCWIWTHRSPY */
12408         rtw_wx_set_wap,         /* SIOCSIWAP */
12409         rtw_wx_get_wap,         /* SIOCGIWAP */
12410         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
12411         dummy,                                  /* SIOCGIWAPLIST -- depricated */
12412         rtw_wx_set_scan,                /* SIOCSIWSCAN */
12413         rtw_wx_get_scan,                /* SIOCGIWSCAN */
12414         rtw_wx_set_essid,               /* SIOCSIWESSID */
12415         rtw_wx_get_essid,               /* SIOCGIWESSID */
12416         dummy,                                  /* SIOCSIWNICKN */
12417         rtw_wx_get_nick,                /* SIOCGIWNICKN */
12418         NULL,                                   /* -- hole -- */
12419         NULL,                                   /* -- hole -- */
12420         rtw_wx_set_rate,                /* SIOCSIWRATE */
12421         rtw_wx_get_rate,                /* SIOCGIWRATE */
12422         rtw_wx_set_rts,                 /* SIOCSIWRTS */
12423         rtw_wx_get_rts,                 /* SIOCGIWRTS */
12424         rtw_wx_set_frag,                /* SIOCSIWFRAG */
12425         rtw_wx_get_frag,                /* SIOCGIWFRAG */
12426         dummy,                                  /* SIOCSIWTXPOW */
12427         dummy,                                  /* SIOCGIWTXPOW */
12428         dummy,                                  /* SIOCSIWRETRY */
12429         rtw_wx_get_retry,               /* SIOCGIWRETRY */
12430         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
12431         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
12432         dummy,                                  /* SIOCSIWPOWER */
12433         rtw_wx_get_power,               /* SIOCGIWPOWER */
12434         NULL,                                   /*---hole---*/
12435         NULL,                                   /*---hole---*/
12436         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
12437         NULL,                                   /* SIOCGWGENIE */
12438         rtw_wx_set_auth,                /* SIOCSIWAUTH */
12439         NULL,                                   /* SIOCGIWAUTH */
12440         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
12441         NULL,                                   /* SIOCGIWENCODEEXT */
12442         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
12443         NULL,                                   /*---hole---*/
12444 };
12445
12446
12447 static const struct iw_priv_args rtw_private_args[] = {
12448         {
12449                 SIOCIWFIRSTPRIV + 0x0,
12450                 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
12451         },
12452         {
12453                 SIOCIWFIRSTPRIV + 0x1,
12454                 IW_PRIV_TYPE_CHAR | 0x7FF,
12455                 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
12456         },
12457         {
12458                 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
12459         },
12460         {
12461                 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
12462         },
12463         {
12464                 SIOCIWFIRSTPRIV + 0x4,
12465                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
12466         },
12467         {
12468                 SIOCIWFIRSTPRIV + 0x5,
12469                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
12470         },
12471         {
12472                 SIOCIWFIRSTPRIV + 0x6,
12473                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
12474         },
12475         /* for PLATFORM_MT53XX   */
12476         {
12477                 SIOCIWFIRSTPRIV + 0x7,
12478                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
12479         },
12480         {
12481                 SIOCIWFIRSTPRIV + 0x8,
12482                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
12483         },
12484         {
12485                 SIOCIWFIRSTPRIV + 0x9,
12486                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
12487         },
12488
12489         /* for RTK_DMP_PLATFORM  */
12490         {
12491                 SIOCIWFIRSTPRIV + 0xA,
12492                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
12493         },
12494
12495         {
12496                 SIOCIWFIRSTPRIV + 0xB,
12497                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
12498         },
12499         {
12500                 SIOCIWFIRSTPRIV + 0xC,
12501                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
12502         },
12503         {
12504                 SIOCIWFIRSTPRIV + 0xD,
12505                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
12506         },
12507 #if 0
12508         {
12509                 SIOCIWFIRSTPRIV + 0xE, 0, 0, "wowlan_ctrl"
12510         },
12511 #endif
12512         {
12513                 SIOCIWFIRSTPRIV + 0x10,
12514                 IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
12515         },
12516         {
12517                 SIOCIWFIRSTPRIV + 0x11,
12518                 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "p2p_get"
12519         },
12520         {
12521                 SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
12522         },
12523         {
12524                 SIOCIWFIRSTPRIV + 0x13,
12525                 IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2"
12526         },
12527         {
12528                 SIOCIWFIRSTPRIV + 0x14,
12529                 IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
12530         },
12531         {
12532                 SIOCIWFIRSTPRIV + 0x15,
12533                 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "tdls_get"
12534         },
12535         {
12536                 SIOCIWFIRSTPRIV + 0x16,
12537                 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
12538         },
12539
12540         {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
12541 #ifdef CONFIG_MP_INCLUDED
12542         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0,  "NULL"},
12543         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "NULL"},
12544 #else
12545         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
12546         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
12547 #endif
12548         {
12549                 SIOCIWFIRSTPRIV + 0x1D,
12550                 IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
12551         },
12552
12553 #ifdef CONFIG_INTEL_WIDI
12554         {
12555                 SIOCIWFIRSTPRIV + 0x1E,
12556                 IW_PRIV_TYPE_CHAR | 1024, 0, "widi_set"
12557         },
12558         {
12559                 SIOCIWFIRSTPRIV + 0x1F,
12560                 IW_PRIV_TYPE_CHAR | 128, 0, "widi_prob_req"
12561         },
12562 #endif /* CONFIG_INTEL_WIDI */
12563
12564         { SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0 , ""},  /* set  */
12565         { SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , ""},/* get
12566  * --- sub-ioctls definitions --- */
12567
12568 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
12569         { VENDOR_IE_SET, IW_PRIV_TYPE_CHAR | 1024 , 0 , "vendor_ie_set" },
12570         { VENDOR_IE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "vendor_ie_get" },
12571 #endif
12572 #if defined(CONFIG_RTL8723B)
12573         { MP_SetBT, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_setbt" },
12574         { MP_DISABLE_BT_COEXIST, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_disa_btcoex"},
12575 #endif
12576 #ifdef CONFIG_WOWLAN
12577         { MP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" },
12578         { MP_WOW_SET_PATTERN , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_set_pattern" },
12579 #endif
12580 #ifdef CONFIG_AP_WOWLAN
12581         { MP_AP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, /* set  */
12582 #endif
12583 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
12584         { MP_SD_IREAD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sd_iread" },
12585         { MP_SD_IWRITE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sd_iwrite" },
12586 #endif
12587 };
12588
12589
12590 static const struct iw_priv_args rtw_mp_private_args[] = {
12591         /* --- sub-ioctls definitions --- */
12592 #ifdef CONFIG_MP_INCLUDED
12593         { MP_START , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start" },
12594         { MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara" },
12595         { MP_STOP , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop" },
12596         { MP_CHANNEL , IW_PRIV_TYPE_CHAR | 1024 , IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel" },
12597         { MP_BANDWIDTH , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"},
12598         { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
12599         { MP_RESET_STATS , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
12600         { MP_QUERY , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "mp_query"},
12601         { READ_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg" },
12602         { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
12603         { READ_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf" },
12604         { MP_PSD , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
12605         { MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump" },
12606         { MP_TXPOWER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
12607         { MP_ANT_TX , IW_PRIV_TYPE_CHAR | 1024,  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
12608         { MP_ANT_RX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
12609         { WRITE_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg" },
12610         { WRITE_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf" },
12611         { MP_CTX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
12612         { MP_ARX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
12613         { MP_THER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
12614         { EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set" },
12615         { EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get" },
12616         { MP_PWRTRK , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
12617         { MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery" },
12618         { MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"},
12619         { MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath" },
12620         { MP_PwrCtlDM, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrctldm" },
12621         { MP_GET_TXPOWER_INX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_get_txpower" },
12622         { MP_GETVER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_priv_ver" },
12623         { MP_MON, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_mon" },
12624         { EFUSE_MASK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_mask" },
12625         { EFUSE_FILE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_file" },
12626         { MP_TX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_tx" },
12627         { MP_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rx" },
12628         { MP_HW_TX_MODE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_hxtx" },
12629         { CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
12630 #endif /* CONFIG_MP_INCLUDED */
12631 };
12632
12633 static iw_handler rtw_private_handler[] = {
12634         rtw_wx_write32,                                 /* 0x00 */
12635         rtw_wx_read32,                                  /* 0x01 */
12636         rtw_drvext_hdl,                                 /* 0x02 */
12637 #ifdef MP_IOCTL_HDL
12638         rtw_mp_ioctl_hdl,                               /* 0x03 */
12639 #else
12640         rtw_wx_priv_null,
12641 #endif
12642         /* for MM DTV platform */
12643         rtw_get_ap_info,                                        /* 0x04 */
12644
12645         rtw_set_pid,                                            /* 0x05 */
12646         rtw_wps_start,                                  /* 0x06 */
12647
12648         /* for PLATFORM_MT53XX */
12649         rtw_wx_get_sensitivity,                 /* 0x07 */
12650         rtw_wx_set_mtk_wps_probe_ie,    /* 0x08 */
12651         rtw_wx_set_mtk_wps_ie,                  /* 0x09 */
12652
12653         /* for RTK_DMP_PLATFORM
12654          * Set Channel depend on the country code */
12655         rtw_wx_set_channel_plan,                /* 0x0A */
12656
12657         rtw_dbg_port,                                   /* 0x0B */
12658         rtw_wx_write_rf,                                        /* 0x0C */
12659         rtw_wx_read_rf,                                 /* 0x0D */
12660
12661         rtw_priv_set,                                   /*0x0E*/
12662         rtw_priv_get,                                   /*0x0F*/
12663
12664         rtw_p2p_set,                                    /* 0x10 */
12665         rtw_p2p_get,                                    /* 0x11 */
12666         NULL,                                                   /* 0x12 */
12667         rtw_p2p_get2,                                   /* 0x13 */
12668
12669         rtw_tdls,                                               /* 0x14 */
12670         rtw_tdls_get,                                   /* 0x15 */
12671
12672         rtw_pm_set,                                             /* 0x16 */
12673         rtw_wx_priv_null,                               /* 0x17 */
12674         rtw_rereg_nd_name,                              /* 0x18 */
12675         rtw_wx_priv_null,                               /* 0x19 */
12676 #ifdef CONFIG_MP_INCLUDED
12677         rtw_wx_priv_null,                               /* 0x1A */
12678         rtw_wx_priv_null,                               /* 0x1B */
12679 #else
12680         rtw_mp_efuse_set,                               /* 0x1A */
12681         rtw_mp_efuse_get,                               /* 0x1B */
12682 #endif
12683         NULL,                                                   /* 0x1C is reserved for hostapd */
12684         rtw_test,                                               /* 0x1D */
12685 #ifdef CONFIG_INTEL_WIDI
12686         rtw_widi_set,                                   /* 0x1E */
12687         rtw_widi_set_probe_request,             /* 0x1F */
12688 #endif /* CONFIG_INTEL_WIDI */
12689 };
12690
12691 #if WIRELESS_EXT >= 17
12692 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
12693 {
12694         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
12695         struct iw_statistics *piwstats = &padapter->iwstats;
12696         int tmp_level = 0;
12697         int tmp_qual = 0;
12698         int tmp_noise = 0;
12699
12700         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != _TRUE) {
12701                 piwstats->qual.qual = 0;
12702                 piwstats->qual.level = 0;
12703                 piwstats->qual.noise = 0;
12704                 /* RTW_INFO("No link  level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); */
12705         } else {
12706 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
12707                 tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
12708 #else
12709 #ifdef CONFIG_SIGNAL_SCALE_MAPPING
12710                 tmp_level = padapter->recvpriv.signal_strength;
12711 #else
12712                 {
12713                         /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
12714
12715                         HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
12716
12717                         tmp_level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, padapter->recvpriv.signal_strength);
12718                 }
12719 #endif
12720 #endif
12721
12722                 tmp_qual = padapter->recvpriv.signal_qual;
12723                 rtw_get_noise(padapter);
12724                 tmp_noise = padapter->recvpriv.noise;
12725                 /* RTW_INFO("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise,padapter->recvpriv.rssi); */
12726
12727                 piwstats->qual.level = tmp_level;
12728                 piwstats->qual.qual = tmp_qual;
12729                 piwstats->qual.noise = tmp_noise;
12730         }
12731 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14))
12732         piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* |IW_QUAL_DBM; */
12733 #else
12734 #ifdef RTK_DMP_PLATFORM
12735         /* IW_QUAL_DBM= 0x8, if driver use this flag, wireless extension will show value of dbm. */
12736         /* remove this flag for show percentage 0~100 */
12737         piwstats->qual.updated = 0x07;
12738 #else
12739         piwstats->qual.updated = 0x0f;
12740 #endif
12741 #endif
12742
12743 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
12744         piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
12745 #endif
12746
12747         return &padapter->iwstats;
12748 }
12749 #endif
12750
12751 #ifdef CONFIG_WIRELESS_EXT
12752 struct iw_handler_def rtw_handlers_def = {
12753         .standard = rtw_handlers,
12754         .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
12755 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) || defined(CONFIG_WEXT_PRIV)
12756         .private = rtw_private_handler,
12757         .private_args = (struct iw_priv_args *)rtw_private_args,
12758         .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
12759         .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
12760 #endif
12761 #if WIRELESS_EXT >= 17
12762         .get_wireless_stats = rtw_get_wireless_stats,
12763 #endif
12764 };
12765 #endif
12766
12767 /* copy from net/wireless/wext.c start
12768  * ----------------------------------------------------------------
12769  *
12770  * Calculate size of private arguments
12771  */
12772 static const char iw_priv_type_size[] = {
12773         0,                              /* IW_PRIV_TYPE_NONE */
12774         1,                              /* IW_PRIV_TYPE_BYTE */
12775         1,                              /* IW_PRIV_TYPE_CHAR */
12776         0,                              /* Not defined */
12777         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
12778         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
12779         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
12780         0,                              /* Not defined */
12781 };
12782
12783 static int get_priv_size(__u16 args)
12784 {
12785         int num = args & IW_PRIV_SIZE_MASK;
12786         int type = (args & IW_PRIV_TYPE_MASK) >> 12;
12787
12788         return num * iw_priv_type_size[type];
12789 }
12790 /* copy from net/wireless/wext.c end */
12791
12792
12793 static int _rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
12794 {
12795         int err = 0;
12796         u8 *input = NULL;
12797         u32 input_len = 0;
12798         const char delim[] = " ";
12799         u8 *output = NULL;
12800         u32 output_len = 0;
12801         u32 count = 0;
12802         u8 *buffer = NULL;
12803         u32 buffer_len = 0;
12804         char *ptr = NULL;
12805         u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */
12806         u32 cmdlen;
12807         s32 len;
12808         u8 *extra = NULL;
12809         u32 extra_size = 0;
12810
12811         s32 k;
12812         const iw_handler *priv;         /* Private ioctl */
12813         const struct iw_priv_args *priv_args;   /* Private ioctl description */
12814         const struct iw_priv_args *mp_priv_args;        /*MP Private ioctl description */
12815         const struct iw_priv_args *sel_priv_args;       /*Selected Private ioctl description */
12816         u32 num_priv;                           /* Number of ioctl */
12817         u32 num_priv_args;                      /* Number of descriptions */
12818         u32 num_mp_priv_args;                   /*Number of MP descriptions */
12819         u32 num_sel_priv_args;                  /*Number of Selected descriptions */
12820         iw_handler handler;
12821         int temp;
12822         int subcmd = 0;                         /* sub-ioctl index */
12823         int offset = 0;                         /* Space for sub-ioctl index */
12824
12825         union iwreq_data wdata;
12826
12827         _rtw_memcpy(&wdata, wrq_data, sizeof(wdata));
12828
12829         input_len = wdata.data.length;
12830         input = rtw_zmalloc(input_len);
12831         if (NULL == input || input_len == 0)
12832                 return -ENOMEM;
12833         if (copy_from_user(input, wdata.data.pointer, input_len)) {
12834                 err = -EFAULT;
12835                 goto exit;
12836         }
12837         input[input_len - 1] = '\0';
12838         ptr = input;
12839         len = input_len;
12840
12841         if (ptr == NULL) {
12842                 err = -EOPNOTSUPP;
12843                 goto exit;
12844         }
12845
12846         sscanf(ptr, "%16s", cmdname);
12847         cmdlen = strlen(cmdname);
12848         RTW_INFO("%s: cmd=%s\n", __func__, cmdname);
12849
12850         /* skip command string */
12851         if (cmdlen > 0)
12852                 cmdlen += 1; /* skip one space */
12853         ptr += cmdlen;
12854         len -= cmdlen;
12855         RTW_INFO("%s: parameters=%s\n", __func__, ptr);
12856
12857         priv = rtw_private_handler;
12858         priv_args = rtw_private_args;
12859         mp_priv_args = rtw_mp_private_args;
12860         num_priv = sizeof(rtw_private_handler) / sizeof(iw_handler);
12861         num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
12862         num_mp_priv_args = sizeof(rtw_mp_private_args) / sizeof(struct iw_priv_args);
12863
12864         if (num_priv_args == 0) {
12865                 err = -EOPNOTSUPP;
12866                 goto exit;
12867         }
12868
12869         /* Search the correct ioctl */
12870         k = -1;
12871         sel_priv_args = priv_args;
12872         num_sel_priv_args = num_priv_args;
12873         while
12874         ((++k < num_sel_priv_args) && strcmp(sel_priv_args[k].name, cmdname))
12875                 ;
12876
12877         /* If not found... */
12878         if (k == num_sel_priv_args) {
12879                 k = -1;
12880                 sel_priv_args = mp_priv_args;
12881                 num_sel_priv_args = num_mp_priv_args;
12882                 while
12883                 ((++k < num_sel_priv_args) && strcmp(sel_priv_args[k].name, cmdname))
12884                         ;
12885
12886                 if (k == num_sel_priv_args) {
12887                         err = -EOPNOTSUPP;
12888                         goto exit;
12889                 }
12890         }
12891
12892         /* Watch out for sub-ioctls ! */
12893         if (sel_priv_args[k].cmd < SIOCDEVPRIVATE) {
12894                 int j = -1;
12895
12896                 /* Find the matching *real* ioctl */
12897                 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
12898                          (priv_args[j].set_args != sel_priv_args[k].set_args) ||
12899                          (priv_args[j].get_args != sel_priv_args[k].get_args)))
12900                         ;
12901
12902                 /* If not found... */
12903                 if (j == num_priv_args) {
12904                         err = -EINVAL;
12905                         goto exit;
12906                 }
12907
12908                 /* Save sub-ioctl number */
12909                 subcmd = sel_priv_args[k].cmd;
12910                 /* Reserve one int (simplify alignment issues) */
12911                 offset = sizeof(__u32);
12912                 /* Use real ioctl definition from now on */
12913                 k = j;
12914         }
12915
12916         buffer = rtw_zmalloc(4096);
12917         if (NULL == buffer) {
12918                 err = -ENOMEM;
12919                 goto exit;
12920         }
12921
12922         /* If we have to set some data */
12923         if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
12924             (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
12925                 u8 *str;
12926
12927                 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
12928                 case IW_PRIV_TYPE_BYTE:
12929                         /* Fetch args */
12930                         count = 0;
12931                         do {
12932                                 str = strsep(&ptr, delim);
12933                                 if (NULL == str)
12934                                         break;
12935                                 sscanf(str, "%i", &temp);
12936                                 buffer[count++] = (u8)temp;
12937                         } while (1);
12938                         buffer_len = count;
12939
12940                         /* Number of args to fetch */
12941                         wdata.data.length = count;
12942                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
12943                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
12944
12945                         break;
12946
12947                 case IW_PRIV_TYPE_INT:
12948                         /* Fetch args */
12949                         count = 0;
12950                         do {
12951                                 str = strsep(&ptr, delim);
12952                                 if (NULL == str)
12953                                         break;
12954                                 sscanf(str, "%i", &temp);
12955                                 ((s32 *)buffer)[count++] = (s32)temp;
12956                         } while (1);
12957                         buffer_len = count * sizeof(s32);
12958
12959                         /* Number of args to fetch */
12960                         wdata.data.length = count;
12961                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
12962                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
12963
12964                         break;
12965
12966                 case IW_PRIV_TYPE_CHAR:
12967                         if (len > 0) {
12968                                 /* Size of the string to fetch */
12969                                 wdata.data.length = len;
12970                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
12971                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
12972
12973                                 /* Fetch string */
12974                                 _rtw_memcpy(buffer, ptr, wdata.data.length);
12975                         } else {
12976                                 wdata.data.length = 1;
12977                                 buffer[0] = '\0';
12978                         }
12979                         buffer_len = wdata.data.length;
12980                         break;
12981
12982                 default:
12983                         RTW_INFO("%s: Not yet implemented...\n", __func__);
12984                         err = -1;
12985                         goto exit;
12986                 }
12987
12988                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
12989                     (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
12990                         RTW_INFO("%s: The command %s needs exactly %d argument(s)...\n",
12991                                 __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
12992                         err = -EINVAL;
12993                         goto exit;
12994                 }
12995         }   /* if args to set */
12996         else
12997                 wdata.data.length = 0L;
12998
12999         /* Those two tests are important. They define how the driver
13000         * will have to handle the data */
13001         if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
13002             ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
13003                 /* First case : all SET args fit within wrq */
13004                 if (offset)
13005                         wdata.mode = subcmd;
13006                 _rtw_memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
13007         } else {
13008                 if ((priv_args[k].set_args == 0) &&
13009                     (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
13010                     (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
13011                         /* Second case : no SET args, GET args fit within wrq */
13012                         if (offset)
13013                                 wdata.mode = subcmd;
13014                 } else {
13015                         /* Third case : args won't fit in wrq, or variable number of args */
13016                         if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
13017                                 err = -EFAULT;
13018                                 goto exit;
13019                         }
13020                         wdata.data.flags = subcmd;
13021                 }
13022         }
13023
13024         rtw_mfree(input, input_len);
13025         input = NULL;
13026
13027         extra_size = 0;
13028         if (IW_IS_SET(priv_args[k].cmd)) {
13029                 /* Size of set arguments */
13030                 extra_size = get_priv_size(priv_args[k].set_args);
13031
13032                 /* Does it fits in iwr ? */
13033                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
13034                     ((extra_size + offset) <= IFNAMSIZ))
13035                         extra_size = 0;
13036         } else {
13037                 /* Size of get arguments */
13038                 extra_size = get_priv_size(priv_args[k].get_args);
13039
13040                 /* Does it fits in iwr ? */
13041                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
13042                     (extra_size <= IFNAMSIZ))
13043                         extra_size = 0;
13044         }
13045
13046         if (extra_size == 0) {
13047                 extra = (u8 *)&wdata;
13048                 rtw_mfree(buffer, 4096);
13049                 buffer = NULL;
13050         } else
13051                 extra = buffer;
13052
13053         handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
13054         err = handler(dev, NULL, &wdata, extra);
13055
13056         /* If we have to get some data */
13057         if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
13058             (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
13059                 int j;
13060                 int n = 0;      /* number of args */
13061                 u8 str[20] = {0};
13062
13063                 /* Check where is the returned data */
13064                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
13065                     (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
13066                         n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
13067                 else
13068                         n = wdata.data.length;
13069
13070                 output = rtw_zmalloc(4096);
13071                 if (NULL == output) {
13072                         err =  -ENOMEM;
13073                         goto exit;
13074                 }
13075
13076                 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
13077                 case IW_PRIV_TYPE_BYTE:
13078                         /* Display args */
13079                         for (j = 0; j < n; j++) {
13080                                 sprintf(str, "%d  ", extra[j]);
13081                                 len = strlen(str);
13082                                 output_len = strlen(output);
13083                                 if ((output_len + len + 1) > 4096) {
13084                                         err = -E2BIG;
13085                                         goto exit;
13086                                 }
13087                                 _rtw_memcpy(output + output_len, str, len);
13088                         }
13089                         break;
13090
13091                 case IW_PRIV_TYPE_INT:
13092                         /* Display args */
13093                         for (j = 0; j < n; j++) {
13094                                 sprintf(str, "%d  ", ((__s32 *)extra)[j]);
13095                                 len = strlen(str);
13096                                 output_len = strlen(output);
13097                                 if ((output_len + len + 1) > 4096) {
13098                                         err = -E2BIG;
13099                                         goto exit;
13100                                 }
13101                                 _rtw_memcpy(output + output_len, str, len);
13102                         }
13103                         break;
13104
13105                 case IW_PRIV_TYPE_CHAR:
13106                         /* Display args */
13107                         _rtw_memcpy(output, extra, n);
13108                         break;
13109
13110                 default:
13111                         RTW_INFO("%s: Not yet implemented...\n", __func__);
13112                         err = -1;
13113                         goto exit;
13114                 }
13115
13116                 output_len = strlen(output) + 1;
13117                 wrq_data->data.length = output_len;
13118                 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
13119                         err = -EFAULT;
13120                         goto exit;
13121                 }
13122         }   /* if args to set */
13123         else
13124                 wrq_data->data.length = 0;
13125
13126 exit:
13127         if (input)
13128                 rtw_mfree(input, input_len);
13129         if (buffer)
13130                 rtw_mfree(buffer, 4096);
13131         if (output)
13132                 rtw_mfree(output, 4096);
13133
13134         return err;
13135 }
13136
13137 #ifdef CONFIG_COMPAT
13138 static int rtw_ioctl_compat_wext_private(struct net_device *dev, struct ifreq *rq)
13139 {
13140         struct compat_iw_point iwp_compat;
13141         union iwreq_data wrq_data;
13142         int err = 0;
13143         RTW_INFO("%s:...\n", __func__);
13144         if (copy_from_user(&iwp_compat, rq->ifr_ifru.ifru_data, sizeof(struct compat_iw_point)))
13145                 return -EFAULT;
13146
13147         wrq_data.data.pointer = compat_ptr(iwp_compat.pointer);
13148         wrq_data.data.length = iwp_compat.length;
13149         wrq_data.data.flags = iwp_compat.flags;
13150
13151         err = _rtw_ioctl_wext_private(dev, &wrq_data);
13152
13153         iwp_compat.pointer = ptr_to_compat(wrq_data.data.pointer);
13154         iwp_compat.length = wrq_data.data.length;
13155         iwp_compat.flags = wrq_data.data.flags;
13156         if (copy_to_user(rq->ifr_ifru.ifru_data, &iwp_compat, sizeof(struct compat_iw_point)))
13157                 return -EFAULT;
13158
13159         return err;
13160 }
13161 #endif /* CONFIG_COMPAT */
13162
13163 static int rtw_ioctl_standard_wext_private(struct net_device *dev, struct ifreq *rq)
13164 {
13165         struct iw_point *iwp;
13166         struct ifreq ifrq;
13167         union iwreq_data wrq_data;
13168         int err = 0;
13169         iwp = &wrq_data.data;
13170         RTW_INFO("%s:...\n", __func__);
13171         if (copy_from_user(iwp, rq->ifr_ifru.ifru_data, sizeof(struct iw_point)))
13172                 return -EFAULT;
13173
13174         err = _rtw_ioctl_wext_private(dev, &wrq_data);
13175
13176         if (copy_to_user(rq->ifr_ifru.ifru_data, iwp, sizeof(struct iw_point)))
13177                 return -EFAULT;
13178
13179         return err;
13180 }
13181
13182 static int rtw_ioctl_wext_private(struct net_device *dev, struct ifreq *rq)
13183 {
13184 #ifdef CONFIG_COMPAT
13185         if (is_compat_task())
13186                 return rtw_ioctl_compat_wext_private(dev, rq);
13187         else
13188 #endif /* CONFIG_COMPAT */
13189                 return rtw_ioctl_standard_wext_private(dev, rq);
13190 }
13191
13192 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
13193 {
13194         struct iwreq *wrq = (struct iwreq *)rq;
13195         int ret = 0;
13196
13197         switch (cmd) {
13198         case RTL_IOCTL_WPA_SUPPLICANT:
13199                 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
13200                 break;
13201 #ifdef CONFIG_AP_MODE
13202         case RTL_IOCTL_HOSTAPD:
13203                 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
13204                 break;
13205 #ifdef CONFIG_WIRELESS_EXT
13206         case SIOCSIWMODE:
13207                 ret = rtw_wx_set_mode(dev, NULL, &wrq->u, NULL);
13208                 break;
13209 #endif
13210 #endif /* CONFIG_AP_MODE */
13211         case SIOCDEVPRIVATE:
13212                 ret = rtw_ioctl_wext_private(dev, rq);
13213                 break;
13214         case (SIOCDEVPRIVATE+1):
13215                 ret = rtw_android_priv_cmd(dev, rq, cmd);
13216                 break;
13217         default:
13218                 ret = -EOPNOTSUPP;
13219                 break;
13220         }
13221
13222         return ret;
13223 }