8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / 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
24 //#ifdef CONFIG_MP_INCLUDED
25 #include <rtw_mp.h>
26 #include <rtw_mp_ioctl.h>
27 #include "../../hal/OUTSRC/phydm_precomp.h"
28 //#endif
29
30 #if defined(CONFIG_RTL8723B)
31 #include <rtw_bt_mp.h>
32 #endif
33
34 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
35 #define  iwe_stream_add_event(a, b, c, d, e)  iwe_stream_add_event(b, c, d, e)
36 #define  iwe_stream_add_point(a, b, c, d, e)  iwe_stream_add_point(b, c, d, e)
37 #endif
38
39 #ifdef CONFIG_80211N_HT
40 extern int rtw_ht_enable;
41 #endif
42
43
44 #define RTL_IOCTL_WPA_SUPPLICANT        SIOCIWFIRSTPRIV+30
45
46 #define SCAN_ITEM_SIZE 768
47 #define MAX_CUSTOM_LEN 64
48 #define RATE_COUNT 4
49
50 #ifdef CONFIG_GLOBAL_UI_PID
51 extern int ui_pid[3];
52 #endif
53
54 // combo scan
55 #define WEXT_CSCAN_AMOUNT 9
56 #define WEXT_CSCAN_BUF_LEN              360
57 #define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
58 #define WEXT_CSCAN_HEADER_SIZE          12
59 #define WEXT_CSCAN_SSID_SECTION         'S'
60 #define WEXT_CSCAN_CHANNEL_SECTION      'C'
61 #define WEXT_CSCAN_NPROBE_SECTION       'N'
62 #define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
63 #define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
64 #define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
65 #define WEXT_CSCAN_TYPE_SECTION         'T'
66
67
68 extern u8 key_2char2num(u8 hch, u8 lch);
69 extern u8 str_2char2num(u8 hch, u8 lch);
70 extern void macstr2num(u8 *dst, u8 *src);
71 extern u8 convert_ip_addr(u8 hch, u8 mch, u8 lch);
72
73 u32 rtw_rates[] = {1000000,2000000,5500000,11000000,
74         6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
75
76 static const char * const iw_operation_mode[] = 
77
78         "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater", "Secondary", "Monitor" 
79 };
80
81 static int hex2num_i(char c)
82 {
83         if (c >= '0' && c <= '9')
84                 return c - '0';
85         if (c >= 'a' && c <= 'f')
86                 return c - 'a' + 10;
87         if (c >= 'A' && c <= 'F')
88                 return c - 'A' + 10;
89         return -1;
90 }
91
92 static int hex2byte_i(const char *hex)
93 {
94         int a, b;
95         a = hex2num_i(*hex++);
96         if (a < 0)
97                 return -1;
98         b = hex2num_i(*hex++);
99         if (b < 0)
100                 return -1;
101         return (a << 4) | b;
102 }
103
104 /**
105  * hwaddr_aton - Convert ASCII string to MAC address
106  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
107  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
108  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
109  */
110 static int hwaddr_aton_i(const char *txt, u8 *addr)
111 {
112         int i;
113
114         for (i = 0; i < 6; i++) {
115                 int a, b;
116
117                 a = hex2num_i(*txt++);
118                 if (a < 0)
119                         return -1;
120                 b = hex2num_i(*txt++);
121                 if (b < 0)
122                         return -1;
123                 *addr++ = (a << 4) | b;
124                 if (i < 5 && *txt++ != ':')
125                         return -1;
126         }
127
128         return 0;
129 }
130
131 static void indicate_wx_custom_event(_adapter *padapter, char *msg)
132 {
133         u8 *buff, *p;
134         union iwreq_data wrqu;
135
136         if (strlen(msg) > IW_CUSTOM_MAX) {
137                 DBG_871X("%s strlen(msg):%zu > IW_CUSTOM_MAX:%u\n", __FUNCTION__ , strlen(msg), IW_CUSTOM_MAX);
138                 return;
139         }
140
141         buff = rtw_zmalloc(IW_CUSTOM_MAX+1);
142         if(!buff)
143                 return;
144
145         _rtw_memcpy(buff, msg, strlen(msg));
146                 
147         _rtw_memset(&wrqu,0,sizeof(wrqu));
148         wrqu.data.length = strlen(msg);
149
150         DBG_871X("%s %s\n", __FUNCTION__, buff);        
151 #ifndef CONFIG_IOCTL_CFG80211
152         wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
153 #endif
154
155         rtw_mfree(buff, IW_CUSTOM_MAX+1);
156
157 }
158
159
160 static void request_wps_pbc_event(_adapter *padapter)
161 {
162         u8 *buff, *p;
163         union iwreq_data wrqu;
164
165
166         buff = rtw_malloc(IW_CUSTOM_MAX);
167         if(!buff)
168                 return;
169                 
170         _rtw_memset(buff, 0, IW_CUSTOM_MAX);
171                 
172         p=buff;
173                 
174         p+=sprintf(p, "WPS_PBC_START.request=TRUE");
175                 
176         _rtw_memset(&wrqu,0,sizeof(wrqu));
177                 
178         wrqu.data.length = p-buff;
179                 
180         wrqu.data.length = (wrqu.data.length<IW_CUSTOM_MAX) ? wrqu.data.length:IW_CUSTOM_MAX;
181
182         DBG_871X("%s\n", __FUNCTION__);
183                 
184 #ifndef CONFIG_IOCTL_CFG80211
185         wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
186 #endif
187
188         if(buff)
189         {
190                 rtw_mfree(buff, IW_CUSTOM_MAX);
191         }
192
193 }
194
195 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
196 void rtw_request_wps_pbc_event(_adapter *padapter)
197 {
198 #ifdef RTK_DMP_PLATFORM
199 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
200         kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_NET_PBC);
201 #else
202         kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_NET_PBC);
203 #endif
204 #else
205
206         if ( padapter->pid[0] == 0 )
207         {       //      0 is the default value and it means the application monitors the HW PBC doesn't privde its pid to driver.
208                 return;
209         }
210
211         rtw_signal_process(padapter->pid[0], SIGUSR1);
212
213 #endif
214
215         rtw_led_control(padapter, LED_CTL_START_WPS_BOTTON);
216 }
217 #endif//#ifdef CONFIG_SUPPORT_HW_WPS_PBC
218
219 void indicate_wx_scan_complete_event(_adapter *padapter)
220 {       
221         union iwreq_data wrqu;
222         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;     
223
224         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
225
226         //DBG_871X("+rtw_indicate_wx_scan_complete_event\n");
227 #ifndef CONFIG_IOCTL_CFG80211
228         wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
229 #endif
230 }
231
232
233 void rtw_indicate_wx_assoc_event(_adapter *padapter)
234 {       
235         union iwreq_data wrqu;
236         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
237         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
238         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
239         WLAN_BSSID_EX           *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
240
241         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
242         
243         wrqu.ap_addr.sa_family = ARPHRD_ETHER;  
244         
245         if(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==_TRUE )
246                 _rtw_memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
247         else
248                 _rtw_memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
249
250         DBG_871X_LEVEL(_drv_always_, "assoc success\n");
251 #ifndef CONFIG_IOCTL_CFG80211
252         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
253 #endif
254 }
255
256 void rtw_indicate_wx_disassoc_event(_adapter *padapter)
257 {       
258         union iwreq_data wrqu;
259
260         _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
261
262         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
263         _rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
264
265 #ifndef CONFIG_IOCTL_CFG80211
266         DBG_871X_LEVEL(_drv_always_, "indicate disassoc\n");
267         wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
268 #endif
269 }
270
271 /*
272 uint    rtw_is_cckrates_included(u8 *rate)
273 {       
274                 u32     i = 0;                  
275
276                 while(rate[i]!=0)
277                 {               
278                         if  (  (((rate[i]) & 0x7f) == 2)        || (((rate[i]) & 0x7f) == 4) ||         
279                         (((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22) )             
280                         return _TRUE;   
281                         i++;
282                 }
283                 
284                 return _FALSE;
285 }
286
287 uint    rtw_is_cckratesonly_included(u8 *rate)
288 {
289         u32 i = 0;
290
291         while(rate[i]!=0)
292         {
293                         if  (  (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
294                                 (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22) )
295                         return _FALSE;          
296                         i++;
297         }
298         
299         return _TRUE;
300 }
301 */
302
303 static int search_p2p_wfd_ie(_adapter *padapter,
304                                 struct iw_request_info* info, struct wlan_network *pnetwork,
305                                 char *start, char *stop)
306 {
307 #ifdef CONFIG_P2P
308         struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
309 #ifdef CONFIG_WFD
310         if ( SCAN_RESULT_ALL == pwdinfo->wfd_info->scan_result_type )
311         {
312
313         }
314         else if ( ( SCAN_RESULT_P2P_ONLY == pwdinfo->wfd_info->scan_result_type ) || 
315                       ( SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type ) )
316 #endif // CONFIG_WFD
317         {
318                 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
319                 {
320                         u32     blnGotP2PIE = _FALSE;
321                         
322                         //      User is doing the P2P device discovery
323                         //      The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE.
324                         //      If not, the driver should ignore this AP and go to the next AP.
325
326                         //      Verifying the SSID
327                         if ( _rtw_memcmp( pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN ) )
328                         {
329                                 u32     p2pielen = 0;
330
331                                 //      Verifying the P2P IE
332                                 if (rtw_get_p2p_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &p2pielen, pnetwork->network.Reserved[0])) 
333                                 {
334                                         blnGotP2PIE = _TRUE;
335                                 }
336                         }
337
338                         if ( blnGotP2PIE == _FALSE )
339                         {
340                                 return _FALSE;
341                         }
342                         
343                 }
344         }
345
346 #ifdef CONFIG_WFD
347         if ( SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type )
348         {
349                 u32     blnGotWFD = _FALSE;
350                 u8      wfd_ie[ 128 ] = { 0x00 };
351                 uint    wfd_ielen = 0;
352                 
353                 if ( rtw_get_wfd_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength,  wfd_ie, &wfd_ielen, pnetwork->network.Reserved[0]) )
354                 {
355                         u8      wfd_devinfo[ 6 ] = { 0x00 };
356                         uint    wfd_devlen = 6;
357                         
358                         if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen) )
359                         {
360                                 if ( pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_PSINK )
361                                 {
362                                         //      the first two bits will indicate the WFD device type
363                                         if ( ( wfd_devinfo[ 1 ] & 0x03 ) == WFD_DEVINFO_SOURCE )
364                                         {
365                                                 //      If this device is Miracast PSink device, the scan reuslt should just provide the Miracast source.
366                                                 blnGotWFD = _TRUE;
367                                         }
368                                 }
369                                 else if ( pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_SOURCE )
370                                 {
371                                         //      the first two bits will indicate the WFD device type
372                                         if ( ( wfd_devinfo[ 1 ] & 0x03 ) == WFD_DEVINFO_PSINK )
373                                         {
374                                                 //      If this device is Miracast source device, the scan reuslt should just provide the Miracast PSink.
375                                                 //      Todo: How about the SSink?!
376                                                 blnGotWFD = _TRUE;
377                                         }
378                                 }
379                         }
380                 }
381                 
382                 if ( blnGotWFD == _FALSE )
383                 {
384                         return _FALSE;
385                 }
386         }
387 #endif // CONFIG_WFD
388
389 #endif //CONFIG_P2P
390         return _TRUE;
391 }
392  static inline char *iwe_stream_mac_addr_proess(_adapter *padapter,
393                                 struct iw_request_info* info, struct wlan_network *pnetwork,
394                                 char *start, char *stop,struct iw_event *iwe)
395 {       
396         /*  AP MAC address  */
397         iwe->cmd = SIOCGIWAP;
398         iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
399
400         _rtw_memcpy(iwe->u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
401         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_ADDR_LEN);   
402         return start;
403 }
404  static inline char * iwe_stream_essid_proess(_adapter *padapter,
405                                 struct iw_request_info* info, struct wlan_network *pnetwork,
406                                 char *start, char *stop,struct iw_event *iwe)
407 {
408         
409         /* Add the ESSID */
410         iwe->cmd = SIOCGIWESSID;
411         iwe->u.data.flags = 1;  
412         iwe->u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
413         start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);              
414         return start;
415 }
416
417  static inline char * iwe_stream_chan_process(_adapter *padapter,
418                                 struct iw_request_info* info, struct wlan_network *pnetwork,
419                                 char *start, char *stop,struct iw_event *iwe)
420 {
421         if(pnetwork->network.Configuration.DSConfig<1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
422                 pnetwork->network.Configuration.DSConfig = 1;
423
424          /* Add frequency/channel */
425         iwe->cmd = SIOCGIWFREQ;
426         iwe->u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
427         iwe->u.freq.e = 1;
428         iwe->u.freq.i = pnetwork->network.Configuration.DSConfig;
429         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_FREQ_LEN);
430         return start;
431 }
432  static inline char * iwe_stream_mode_process(_adapter *padapter,
433                                 struct iw_request_info* info, struct wlan_network *pnetwork,
434                                 char *start, char *stop,struct iw_event *iwe,u16 cap)
435 {
436         /* Add mode */
437         if(cap & (WLAN_CAPABILITY_IBSS |WLAN_CAPABILITY_BSS)){
438                 iwe->cmd = SIOCGIWMODE;
439                 if (cap & WLAN_CAPABILITY_BSS)
440                         iwe->u.mode = IW_MODE_MASTER;
441                 else
442                         iwe->u.mode = IW_MODE_ADHOC;
443
444                 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_UINT_LEN);
445         }
446         return start;
447  }
448  static inline char * iwe_stream_encryption_process(_adapter *padapter,
449                                 struct iw_request_info* info, struct wlan_network *pnetwork,
450                                 char *start, char *stop,struct iw_event *iwe,u16 cap)
451 {       
452
453         /* Add encryption capability */
454         iwe->cmd = SIOCGIWENCODE;
455         if (cap & WLAN_CAPABILITY_PRIVACY)
456                 iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
457         else
458                 iwe->u.data.flags = IW_ENCODE_DISABLED;
459         iwe->u.data.length = 0;
460         start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
461         return start;
462
463 }       
464
465  static inline char * iwe_stream_protocol_process(_adapter *padapter,
466                                 struct iw_request_info* info, struct wlan_network *pnetwork,
467                                 char *start, char *stop,struct iw_event *iwe)
468  {
469         u16 ht_cap=_FALSE,vht_cap = _FALSE;
470         u32 ht_ielen = 0, vht_ielen = 0;
471         char *p;
472         u8 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);// Probe Request      
473                 
474         //parsing HT_CAP_IE     
475         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-ie_offset); 
476         if(p && ht_ielen>0)             
477                 ht_cap = _TRUE;                 
478
479         #ifdef CONFIG_80211AC_VHT
480         //parsing VHT_CAP_IE
481         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength-ie_offset);
482         if(p && vht_ielen>0)
483                 vht_cap = _TRUE;        
484         #endif
485          /* Add the protocol name */
486         iwe->cmd = SIOCGIWNAME;
487         if ((rtw_is_cckratesonly_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE)            
488         {
489                 if(ht_cap == _TRUE)
490                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bn");
491                 else
492                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11b");
493         }       
494         else if ((rtw_is_cckrates_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE)   
495         {
496                 if(ht_cap == _TRUE)
497                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bgn");
498                 else
499                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bg");
500         }       
501         else
502         {
503                 if(pnetwork->network.Configuration.DSConfig > 14)
504                 {
505                         #ifdef CONFIG_80211AC_VHT
506                         if(vht_cap == _TRUE){
507                                 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11AC");
508                         }
509                         else 
510                         #endif  
511                         {
512                                 if(ht_cap == _TRUE)
513                                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11an");
514                                 else
515                                         snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11a");
516                         }
517                 }
518                 else
519                 {
520                         if(ht_cap == _TRUE)
521                                 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11gn");
522                         else
523                                 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11g");
524                 }
525         }
526         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_CHAR_LEN);
527         return start;
528  }
529                                 
530  static inline char * iwe_stream_rate_process(_adapter *padapter,
531                                 struct iw_request_info* info, struct wlan_network *pnetwork,
532                                 char *start, char *stop,struct iw_event *iwe)
533 {
534         u32 ht_ielen = 0, vht_ielen = 0;
535         char *p;
536         u16 max_rate=0, rate, ht_cap=_FALSE, vht_cap = _FALSE;
537         u32 i = 0;              
538         u8 bw_40MHz=0, short_GI=0, bw_160MHz=0, vht_highest_rate = 0;
539         u16 mcs_rate=0, vht_data_rate=0;
540         char custom[MAX_CUSTOM_LEN]={0};
541         u8 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);// Probe Request      
542         
543         //parsing HT_CAP_IE     
544         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-ie_offset); 
545         if(p && ht_ielen>0)
546         {
547                 struct rtw_ieee80211_ht_cap *pht_capie;
548                 ht_cap = _TRUE;                 
549                 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);               
550                 _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
551                 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1:0;
552                 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1:0;
553         }
554
555 #ifdef CONFIG_80211AC_VHT
556         //parsing VHT_CAP_IE
557         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength-ie_offset);
558         if(p && vht_ielen>0)
559         {
560                 u8      mcs_map[2];
561
562                 vht_cap = _TRUE;                
563                 bw_160MHz = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p+2);
564                 if(bw_160MHz)
565                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI160M(p+2);
566                 else
567                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI80M(p+2);
568
569                 _rtw_memcpy(mcs_map, GET_VHT_CAPABILITY_ELE_TX_MCS(p+2), 2);
570
571                 vht_highest_rate = rtw_get_vht_highest_rate(mcs_map);
572                 vht_data_rate = rtw_vht_mcs_to_data_rate(CHANNEL_WIDTH_80, short_GI, vht_highest_rate);
573         }
574 #endif  
575         
576         /*Add basic and extended rates */       
577         p = custom;
578         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
579         while(pnetwork->network.SupportedRates[i]!=0)
580         {
581                 rate = pnetwork->network.SupportedRates[i]&0x7F; 
582                 if (rate > max_rate)
583                         max_rate = rate;
584                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
585                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
586                 i++;
587         }
588 #ifdef CONFIG_80211AC_VHT
589         if(vht_cap == _TRUE) {
590                 max_rate = vht_data_rate;
591         }
592         else
593 #endif          
594         if(ht_cap == _TRUE)
595         {
596                 if(mcs_rate&0x8000)//MCS15
597                 {
598                         max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
599                         
600                 }
601                 else if(mcs_rate&0x0080)//MCS7
602                 {
603                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
604                 }
605                 else//default MCS7
606                 {
607                         //DBG_871X("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate);
608                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
609                 }
610
611                 max_rate = max_rate*2;//Mbps/2;         
612         }
613
614         iwe->cmd = SIOCGIWRATE;
615         iwe->u.bitrate.fixed = iwe->u.bitrate.disabled = 0;
616         iwe->u.bitrate.value = max_rate * 500000;
617         start =iwe_stream_add_event(info, start, stop, iwe, IW_EV_PARAM_LEN);
618         return start ;
619 }
620
621 static inline char * iwe_stream_wpa_wpa2_process(_adapter *padapter,
622                                 struct iw_request_info* info, struct wlan_network *pnetwork,
623                                 char *start, char *stop,struct iw_event *iwe)
624 {
625         int buf_size = MAX_WPA_IE_LEN*2;
626         //u8 pbuf[buf_size]={0};        
627         u8 *pbuf = rtw_zmalloc(buf_size);
628
629         u8 wpa_ie[255]={0},rsn_ie[255]={0};
630         u16 i, wpa_len=0,rsn_len=0;
631         u8 *p;
632         sint out_len=0;
633                 
634         
635         if(pbuf){
636                 p=pbuf; 
637         
638                 //parsing WPA/WPA2 IE
639                 if (pnetwork->network.Reserved[0] != 2) // Probe Request
640                 {       
641                         out_len=rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,rsn_ie,&rsn_len,wpa_ie,&wpa_len);
642                         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: ssid=%s\n",pnetwork->network.Ssid.Ssid));
643                         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
644
645                         if (wpa_len > 0){
646                                 
647                                 _rtw_memset(pbuf, 0, buf_size);
648                                 p += sprintf(p, "wpa_ie=");
649                                 for (i = 0; i < wpa_len; i++) {
650                                         p += sprintf(p, "%02x", wpa_ie[i]);
651                                 }
652
653                                 if (wpa_len > 100) {
654                                         printk("-----------------Len %d----------------\n", wpa_len);
655                                         for (i = 0; i < wpa_len; i++) {
656                                                 printk("%02x ", wpa_ie[i]);
657                                         }
658                                         printk("\n");
659                                         printk("-----------------Len %d----------------\n", wpa_len);
660                                 }
661                 
662                                 _rtw_memset(iwe, 0, sizeof(*iwe));
663                                 iwe->cmd = IWEVCUSTOM;
664                                 iwe->u.data.length = strlen(pbuf);
665                                 start = iwe_stream_add_point(info, start, stop, iwe,pbuf);
666                                 
667                                 _rtw_memset(iwe, 0, sizeof(*iwe));
668                                 iwe->cmd =IWEVGENIE;
669                                 iwe->u.data.length = wpa_len;
670                                 start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie);                   
671                         }
672                         if (rsn_len > 0){
673                                 
674                                 _rtw_memset(pbuf, 0, buf_size);
675                                 p += sprintf(p, "rsn_ie=");
676                                 for (i = 0; i < rsn_len; i++) {
677                                         p += sprintf(p, "%02x", rsn_ie[i]);
678                                 }
679                                 _rtw_memset(iwe, 0, sizeof(*iwe));
680                                 iwe->cmd = IWEVCUSTOM;
681                                 iwe->u.data.length = strlen(pbuf);
682                                 start = iwe_stream_add_point(info, start, stop, iwe,pbuf);
683                         
684                                 _rtw_memset(iwe, 0, sizeof(*iwe));
685                                 iwe->cmd =IWEVGENIE;
686                                 iwe->u.data.length = rsn_len;
687                                 start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie);           
688                         }
689                 }
690         
691                 rtw_mfree(pbuf, buf_size);      
692         }
693         return start;
694 }
695
696 static inline char * iwe_stream_wps_process(_adapter *padapter,
697                                 struct iw_request_info* info, struct wlan_network *pnetwork,
698                                 char *start, char *stop,struct iw_event *iwe)
699 {       
700         //parsing WPS IE
701         uint cnt = 0,total_ielen;       
702         u8 *wpsie_ptr=NULL;
703         uint wps_ielen = 0;             
704         u8 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);
705         
706         u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
707         total_ielen= pnetwork->network.IELength - ie_offset;
708
709         if (pnetwork->network.Reserved[0] == 2) // Probe Request
710         {
711                 ie_ptr = pnetwork->network.IEs;
712                 total_ielen = pnetwork->network.IELength;
713         }
714         else     // Beacon or Probe Respones
715         {
716                 ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
717                 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
718         }    
719         while(cnt < total_ielen)
720         {
721                 if(rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen>2))                    
722                 {
723                         wpsie_ptr = &ie_ptr[cnt];
724                         iwe->cmd =IWEVGENIE;
725                         iwe->u.data.length = (u16)wps_ielen;
726                         start = iwe_stream_add_point(info, start, stop,iwe, wpsie_ptr);                                         
727                 }                       
728                 cnt+=ie_ptr[cnt+1]+2; //goto next
729         }
730         return start;
731 }
732
733 static inline char * iwe_stream_wapi_process(_adapter *padapter,
734                                 struct iw_request_info* info, struct wlan_network *pnetwork,
735                                 char *start, char *stop,struct iw_event *iwe)
736 {
737 #ifdef CONFIG_WAPI_SUPPORT
738         char *p;
739                 
740         if (pnetwork->network.Reserved[0] != 2) // Probe Request
741         {               
742                 sint out_len_wapi=0;
743                 /* here use static for stack size */
744                 static u8 buf_wapi[MAX_WAPI_IE_LEN*2]={0};
745                 static u8 wapi_ie[MAX_WAPI_IE_LEN]={0};
746                 u16 wapi_len=0;
747                 u16  i;
748
749                 out_len_wapi=rtw_get_wapi_ie(pnetwork->network.IEs ,pnetwork->network.IELength,wapi_ie,&wapi_len);
750                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: ssid=%s\n",pnetwork->network.Ssid.Ssid));
751                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: wapi_len=%d \n",wapi_len));
752
753                 DBG_871X("rtw_wx_get_scan: %s ",pnetwork->network.Ssid.Ssid);
754                 DBG_871X("rtw_wx_get_scan: ssid = %d ",wapi_len);
755
756
757                 if (wapi_len > 0)
758                 {
759                         p=buf_wapi;
760                         //_rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN*2);
761                         p += sprintf(p, "wapi_ie=");
762                         for (i = 0; i < wapi_len; i++) {
763                                 p += sprintf(p, "%02x", wapi_ie[i]);
764                         }
765
766                         _rtw_memset(iwe, 0, sizeof(*iwe));
767                         iwe->cmd = IWEVCUSTOM;
768                         iwe->u.data.length = strlen(buf_wapi);
769                         start = iwe_stream_add_point(info, start, stop, iwe,buf_wapi);
770
771                         _rtw_memset(iwe, 0, sizeof(*iwe));
772                         iwe->cmd =IWEVGENIE;
773                         iwe->u.data.length = wapi_len;
774                         start = iwe_stream_add_point(info, start, stop, iwe, wapi_ie);
775                 }
776         }
777 #endif//#ifdef CONFIG_WAPI_SUPPORT
778         return start;
779 }
780
781 static inline char *  iwe_stream_rssi_process(_adapter *padapter,
782                                 struct iw_request_info* info, struct wlan_network *pnetwork,
783                                 char *start, char *stop,struct iw_event *iwe)
784 {
785         u8 ss, sq;
786         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
787         
788         /* Add quality statistics */
789         iwe->cmd = IWEVQUAL;
790         iwe->u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED 
791         #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
792                 | IW_QUAL_NOISE_UPDATED
793         #else
794                 | IW_QUAL_NOISE_INVALID
795         #endif
796         #ifdef CONFIG_SIGNAL_DISPLAY_DBM
797                 | IW_QUAL_DBM
798         #endif
799         ;
800
801         if ( check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE &&
802                 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)){
803                 ss = padapter->recvpriv.signal_strength;
804                 sq = padapter->recvpriv.signal_qual;
805         } else {
806                 ss = pnetwork->network.PhyInfo.SignalStrength;
807                 sq = pnetwork->network.PhyInfo.SignalQuality;
808         }
809         
810         
811         #ifdef CONFIG_SIGNAL_DISPLAY_DBM
812         iwe->u.qual.level = (u8) translate_percentage_to_dbm(ss);//dbm
813         #else
814         #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
815         {
816                 /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
817                 
818                 HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
819                 
820                 iwe->u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss);
821         }
822         #else
823         iwe->u.qual.level = (u8)ss;//%
824         #endif
825         #endif
826         
827         iwe->u.qual.qual = (u8)sq;   // signal quality
828
829         #ifdef CONFIG_PLATFORM_ROCKCHIPS
830         iwe->u.qual.noise = -100; // noise level suggest by zhf@rockchips
831         #else 
832         #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
833         {
834                 s16 tmp_noise=0;
835                 rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
836                 iwe->u.qual.noise = tmp_noise ;
837         }
838         #else
839         iwe->u.qual.noise = 0; // noise level
840         #endif  
841         #endif //CONFIG_PLATFORM_ROCKCHIPS
842         
843         //DBG_871X("iqual=%d, ilevel=%d, inoise=%d, iupdated=%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated);
844
845         start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_QUAL_LEN);
846         return start;
847 }
848
849 static inline char *  iwe_stream_net_rsv_process(_adapter *padapter,
850                                 struct iw_request_info* info, struct wlan_network *pnetwork,
851                                 char *start, char *stop,struct iw_event *iwe)
852 {       
853         u8 buf[32] = {0};
854         u8 * p,*pos;
855         int len;
856         p = buf;
857         pos = pnetwork->network.Reserved;
858         
859         p += sprintf(p, "fm=%02X%02X", pos[1], pos[0]);
860         _rtw_memset(iwe, 0, sizeof(*iwe));
861         iwe->cmd = IWEVCUSTOM;
862         iwe->u.data.length = strlen(buf);
863         start = iwe_stream_add_point(info, start, stop,iwe, buf);
864         return start;
865 }
866
867 #if 1
868 static char *translate_scan(_adapter *padapter, 
869                                 struct iw_request_info* info, struct wlan_network *pnetwork,
870                                 char *start, char *stop)
871 {       
872         struct iw_event iwe;
873         u16 cap = 0;
874         _rtw_memset(&iwe, 0, sizeof(iwe));
875         
876         if(_FALSE == search_p2p_wfd_ie(padapter,info,pnetwork,start,stop))
877                 return start;
878
879         start = iwe_stream_mac_addr_proess(padapter,info,pnetwork,start,stop,&iwe);     
880         start = iwe_stream_essid_proess(padapter,info,pnetwork,start,stop,&iwe);        
881         start = iwe_stream_protocol_process(padapter,info,pnetwork,start,stop,&iwe);
882         if (pnetwork->network.Reserved[0] == 2) // Probe Request
883         {
884                 cap = 0;
885         }
886         else
887         {
888                 _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
889                 cap = le16_to_cpu(cap);
890         }
891
892         start = iwe_stream_mode_process(padapter,info,pnetwork,start,stop,&iwe,cap);    
893         start = iwe_stream_chan_process(padapter,info,pnetwork,start,stop,&iwe);        
894         start = iwe_stream_encryption_process(padapter,info,pnetwork,start,stop,&iwe,cap);      
895         start = iwe_stream_rate_process(padapter,info,pnetwork,start,stop,&iwe);        
896         start = iwe_stream_wpa_wpa2_process(padapter,info,pnetwork,start,stop,&iwe);
897         start = iwe_stream_wps_process(padapter,info,pnetwork,start,stop,&iwe);
898         start = iwe_stream_wapi_process(padapter,info,pnetwork,start,stop,&iwe);
899         start = iwe_stream_rssi_process(padapter,info,pnetwork,start,stop,&iwe);
900         start = iwe_stream_net_rsv_process(padapter,info,pnetwork,start,stop,&iwe);     
901         
902         return start;   
903 }
904 #else
905 static char *translate_scan(_adapter *padapter, 
906                                 struct iw_request_info* info, struct wlan_network *pnetwork,
907                                 char *start, char *stop)
908 {
909         struct iw_event iwe;
910         u16 cap;
911         u32 ht_ielen = 0, vht_ielen = 0;
912         char custom[MAX_CUSTOM_LEN];
913         char *p;
914         u16 max_rate=0, rate, ht_cap=_FALSE, vht_cap = _FALSE;
915         u32 i = 0;      
916         char    *current_val;
917         long rssi;
918         u8 bw_40MHz=0, short_GI=0, bw_160MHz=0, vht_highest_rate = 0;
919         u16 mcs_rate=0, vht_data_rate=0;
920         u8 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);
921         struct registry_priv *pregpriv = &padapter->registrypriv;
922         
923         if(_FALSE == search_p2p_wfd_ie(padapter,info,pnetwork,start,stop))
924                 return start;
925
926         /*  AP MAC address  */
927         iwe.cmd = SIOCGIWAP;
928         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
929
930         _rtw_memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
931         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
932         
933         /* Add the ESSID */
934         iwe.cmd = SIOCGIWESSID;
935         iwe.u.data.flags = 1;   
936         iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
937         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
938
939         //parsing HT_CAP_IE
940         if (pnetwork->network.Reserved[0] == 2) // Probe Request
941         {
942                 p = rtw_get_ie(&pnetwork->network.IEs[0], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength);
943         }
944         else
945         {
946                 p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
947         }
948         if(p && ht_ielen>0)
949         {
950                 struct rtw_ieee80211_ht_cap *pht_capie;
951                 ht_cap = _TRUE;                 
952                 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);               
953                 _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
954                 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1:0;
955                 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1:0;
956         }
957
958 #ifdef CONFIG_80211AC_VHT
959         //parsing VHT_CAP_IE
960         p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength-ie_offset);
961         if(p && vht_ielen>0)
962         {
963                 u8      mcs_map[2];
964
965                 vht_cap = _TRUE;                
966                 bw_160MHz = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p+2);
967                 if(bw_160MHz)
968                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI160M(p+2);
969                 else
970                         short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI80M(p+2);
971
972                 _rtw_memcpy(mcs_map, GET_VHT_CAPABILITY_ELE_TX_MCS(p+2), 2);
973
974                 vht_highest_rate = rtw_get_vht_highest_rate(mcs_map);
975                 vht_data_rate = rtw_vht_mcs_to_data_rate(CHANNEL_WIDTH_80, short_GI, vht_highest_rate);
976         }
977 #endif
978
979         /* Add the protocol name */
980         iwe.cmd = SIOCGIWNAME;
981         if ((rtw_is_cckratesonly_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE)            
982         {
983                 if(ht_cap == _TRUE)
984                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
985                 else
986                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
987         }       
988         else if ((rtw_is_cckrates_included((u8*)&pnetwork->network.SupportedRates)) == _TRUE)   
989         {
990                 if(ht_cap == _TRUE)
991                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
992                 else
993                         snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
994         }       
995         else
996         {
997                 if(pnetwork->network.Configuration.DSConfig > 14)
998                 {
999                         if(vht_cap == _TRUE)
1000                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC");
1001                         else if(ht_cap == _TRUE)
1002                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
1003                         else
1004                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
1005                 }
1006                 else
1007                 {
1008                         if(ht_cap == _TRUE)
1009                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
1010                         else
1011                                 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
1012                 }
1013         }       
1014
1015         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
1016
1017           /* Add mode */
1018         if (pnetwork->network.Reserved[0] == 2) // Probe Request
1019         {
1020                 cap = 0;
1021         }
1022         else
1023         {
1024         iwe.cmd = SIOCGIWMODE;
1025                 _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
1026                 cap = le16_to_cpu(cap);
1027         }
1028
1029         if(cap & (WLAN_CAPABILITY_IBSS |WLAN_CAPABILITY_BSS)){
1030                 if (cap & WLAN_CAPABILITY_BSS)
1031                         iwe.u.mode = IW_MODE_MASTER;
1032                 else
1033                         iwe.u.mode = IW_MODE_ADHOC;
1034
1035                 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
1036         }
1037
1038         if(pnetwork->network.Configuration.DSConfig<1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
1039                 pnetwork->network.Configuration.DSConfig = 1;
1040
1041          /* Add frequency/channel */
1042         iwe.cmd = SIOCGIWFREQ;
1043         iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
1044         iwe.u.freq.e = 1;
1045         iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
1046         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
1047
1048         /* Add encryption capability */
1049         iwe.cmd = SIOCGIWENCODE;
1050         if (cap & WLAN_CAPABILITY_PRIVACY)
1051                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1052         else
1053                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1054         iwe.u.data.length = 0;
1055         start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
1056
1057         /*Add basic and extended rates */
1058         max_rate = 0;
1059         p = custom;
1060         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
1061         while(pnetwork->network.SupportedRates[i]!=0)
1062         {
1063                 rate = pnetwork->network.SupportedRates[i]&0x7F; 
1064                 if (rate > max_rate)
1065                         max_rate = rate;
1066                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
1067                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
1068                 i++;
1069         }
1070
1071         if(vht_cap == _TRUE) {
1072                 max_rate = vht_data_rate;
1073         }
1074         else if(ht_cap == _TRUE)
1075         {
1076                 if(mcs_rate&0x8000)//MCS15
1077                 {
1078                         max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
1079                         
1080                 }
1081                 else if(mcs_rate&0x0080)//MCS7
1082                 {
1083                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
1084                 }
1085                 else//default MCS7
1086                 {
1087                         //DBG_871X("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate);
1088                         max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
1089                 }
1090
1091                 max_rate = max_rate*2;//Mbps/2;         
1092         }
1093
1094         iwe.cmd = SIOCGIWRATE;
1095         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1096         iwe.u.bitrate.value = max_rate * 500000;
1097         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
1098
1099         //parsing WPA/WPA2 IE
1100         if (pnetwork->network.Reserved[0] != 2) // Probe Request
1101         {
1102                 u8 buf[MAX_WPA_IE_LEN*2];
1103                 u8 wpa_ie[255],rsn_ie[255];
1104                 u16 wpa_len=0,rsn_len=0;
1105                 u8 *p;
1106                 sint out_len=0;
1107                 out_len=rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,rsn_ie,&rsn_len,wpa_ie,&wpa_len);
1108                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: ssid=%s\n",pnetwork->network.Ssid.Ssid));
1109                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
1110
1111                 if (wpa_len > 0)
1112                 {
1113                         p=buf;
1114                         _rtw_memset(buf, 0, MAX_WPA_IE_LEN*2);
1115                         p += sprintf(p, "wpa_ie=");
1116                         for (i = 0; i < wpa_len; i++) {
1117                                 p += sprintf(p, "%02x", wpa_ie[i]);
1118                         }
1119
1120                         if (wpa_len > 100) {
1121                                 printk("-----------------Len %d----------------\n", wpa_len);
1122                                 for (i = 0; i < wpa_len; i++) {
1123                                         printk("%02x ", wpa_ie[i]);
1124                                 }
1125                                 printk("\n");
1126                                 printk("-----------------Len %d----------------\n", wpa_len);
1127                         }
1128         
1129                         _rtw_memset(&iwe, 0, sizeof(iwe));
1130                         iwe.cmd = IWEVCUSTOM;
1131                         iwe.u.data.length = strlen(buf);
1132                         start = iwe_stream_add_point(info, start, stop, &iwe,buf);
1133                         
1134                         _rtw_memset(&iwe, 0, sizeof(iwe));
1135                         iwe.cmd =IWEVGENIE;
1136                         iwe.u.data.length = wpa_len;
1137                         start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);                  
1138                 }
1139                 if (rsn_len > 0)
1140                 {
1141                         p = buf;
1142                         _rtw_memset(buf, 0, MAX_WPA_IE_LEN*2);
1143                         p += sprintf(p, "rsn_ie=");
1144                         for (i = 0; i < rsn_len; i++) {
1145                                 p += sprintf(p, "%02x", rsn_ie[i]);
1146                         }
1147                         _rtw_memset(&iwe, 0, sizeof(iwe));
1148                         iwe.cmd = IWEVCUSTOM;
1149                         iwe.u.data.length = strlen(buf);
1150                         start = iwe_stream_add_point(info, start, stop, &iwe,buf);
1151                 
1152                         _rtw_memset(&iwe, 0, sizeof(iwe));
1153                         iwe.cmd =IWEVGENIE;
1154                         iwe.u.data.length = rsn_len;
1155                         start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);          
1156                 }
1157         }
1158
1159         { //parsing WPS IE
1160                 uint cnt = 0,total_ielen;       
1161                 u8 *wpsie_ptr=NULL;
1162                 uint wps_ielen = 0;             
1163
1164                 u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
1165                 total_ielen= pnetwork->network.IELength - ie_offset;
1166
1167                 if (pnetwork->network.Reserved[0] == 2) // Probe Request
1168                 {
1169                         ie_ptr = pnetwork->network.IEs;
1170                         total_ielen = pnetwork->network.IELength;
1171                 }
1172                 else     // Beacon or Probe Respones
1173                 {
1174                         ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
1175                         total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
1176                 }
1177         
1178                 while(cnt < total_ielen)
1179                 {
1180                         if(rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen>2))                    
1181                         {
1182                                 wpsie_ptr = &ie_ptr[cnt];
1183                                 iwe.cmd =IWEVGENIE;
1184                                 iwe.u.data.length = (u16)wps_ielen;
1185                                 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);                                               
1186                         }                       
1187                         cnt+=ie_ptr[cnt+1]+2; //goto next
1188                 }
1189         }
1190
1191 #ifdef CONFIG_WAPI_SUPPORT
1192         if (pnetwork->network.Reserved[0] != 2) // Probe Request
1193         {
1194                 sint out_len_wapi=0;
1195                 /* here use static for stack size */
1196                 static u8 buf_wapi[MAX_WAPI_IE_LEN*2];
1197                 static u8 wapi_ie[MAX_WAPI_IE_LEN];
1198                 u16 wapi_len=0;
1199                 u16  i;
1200
1201                 _rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN);
1202                 _rtw_memset(wapi_ie, 0, MAX_WAPI_IE_LEN);
1203
1204                 out_len_wapi=rtw_get_wapi_ie(pnetwork->network.IEs ,pnetwork->network.IELength,wapi_ie,&wapi_len);
1205                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: ssid=%s\n",pnetwork->network.Ssid.Ssid));
1206                 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan: wapi_len=%d \n",wapi_len));
1207
1208                 DBG_871X("rtw_wx_get_scan: %s ",pnetwork->network.Ssid.Ssid);
1209                 DBG_871X("rtw_wx_get_scan: ssid = %d ",wapi_len);
1210
1211
1212                 if (wapi_len > 0)
1213                 {
1214                         p=buf_wapi;
1215                         _rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN*2);
1216                         p += sprintf(p, "wapi_ie=");
1217                         for (i = 0; i < wapi_len; i++) {
1218                                 p += sprintf(p, "%02x", wapi_ie[i]);
1219                         }
1220
1221                         _rtw_memset(&iwe, 0, sizeof(iwe));
1222                         iwe.cmd = IWEVCUSTOM;
1223                         iwe.u.data.length = strlen(buf_wapi);
1224                         start = iwe_stream_add_point(info, start, stop, &iwe,buf_wapi);
1225
1226                         _rtw_memset(&iwe, 0, sizeof(iwe));
1227                         iwe.cmd =IWEVGENIE;
1228                         iwe.u.data.length = wapi_len;
1229                         start = iwe_stream_add_point(info, start, stop, &iwe, wapi_ie);
1230                 }
1231         }
1232 #endif
1233
1234 {
1235         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1236         u8 ss, sq;
1237         
1238         /* Add quality statistics */
1239         iwe.cmd = IWEVQUAL;
1240         iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED 
1241         #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
1242                 | IW_QUAL_NOISE_UPDATED
1243         #else
1244                 | IW_QUAL_NOISE_INVALID
1245         #endif
1246         #ifdef CONFIG_SIGNAL_DISPLAY_DBM
1247                 | IW_QUAL_DBM
1248         #endif
1249         ;
1250
1251         if ( check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE &&
1252                 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)){
1253                 ss = padapter->recvpriv.signal_strength;
1254                 sq = padapter->recvpriv.signal_qual;
1255         } else {
1256                 ss = pnetwork->network.PhyInfo.SignalStrength;
1257                 sq = pnetwork->network.PhyInfo.SignalQuality;
1258         }
1259         
1260         
1261         #ifdef CONFIG_SIGNAL_DISPLAY_DBM
1262         iwe.u.qual.level = (u8) translate_percentage_to_dbm(ss);//dbm
1263         #else
1264         #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
1265         {
1266                 /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
1267                 
1268                 HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
1269                 
1270                 iwe.u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss);
1271         }
1272         #else
1273         iwe.u.qual.level = (u8)ss;//%
1274         #endif
1275         #endif
1276         
1277         iwe.u.qual.qual = (u8)sq;   // signal quality
1278
1279         #ifdef CONFIG_PLATFORM_ROCKCHIPS
1280         iwe.u.qual.noise = -100; // noise level suggest by zhf@rockchips
1281         #else 
1282         #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
1283         {
1284                 s16 tmp_noise=0;
1285                 rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
1286                 iwe.u.qual.noise = tmp_noise ;
1287         }
1288         #else
1289         iwe.u.qual.noise = 0; // noise level
1290         #endif  
1291         #endif //CONFIG_PLATFORM_ROCKCHIPS
1292         
1293         //DBG_871X("iqual=%d, ilevel=%d, inoise=%d, iupdated=%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated);
1294
1295         start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
1296 }
1297
1298         {
1299                 u8 buf[MAX_WPA_IE_LEN];
1300                 u8 * p,*pos;
1301                 int len;
1302                 p = buf;
1303                 pos = pnetwork->network.Reserved;
1304                 _rtw_memset(buf, 0, MAX_WPA_IE_LEN);
1305                 p += sprintf(p, "fm=%02X%02X", pos[1], pos[0]);
1306                 _rtw_memset(&iwe, 0, sizeof(iwe));
1307                 iwe.cmd = IWEVCUSTOM;
1308                 iwe.u.data.length = strlen(buf);
1309                 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1310         }
1311         
1312         return start;   
1313 }
1314 #endif
1315
1316 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
1317 {       
1318         _adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
1319         int ret = 0;
1320
1321         if ((value & AUTH_ALG_SHARED_KEY)&&(value & AUTH_ALG_OPEN_SYSTEM))
1322         {
1323                 DBG_871X("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n",value);
1324                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1325                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
1326                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1327         } 
1328         else if (value & AUTH_ALG_SHARED_KEY)
1329         {
1330                 DBG_871X("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n",value);
1331                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1332
1333 #ifdef CONFIG_PLATFORM_MT53XX
1334                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
1335                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1336 #else
1337                 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
1338                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1339 #endif
1340         } 
1341         else if(value & AUTH_ALG_OPEN_SYSTEM)
1342         {
1343                 DBG_871X("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
1344                 //padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1345                 if(padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK)
1346                 {
1347 #ifdef CONFIG_PLATFORM_MT53XX
1348                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
1349                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1350 #else
1351                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1352                         padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1353 #endif
1354                 }
1355                 
1356         }
1357         else if(value & AUTH_ALG_LEAP)
1358         {
1359                 DBG_871X("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
1360         }
1361         else
1362         {
1363                 DBG_871X("wpa_set_auth_algs, error!\n");
1364                 ret = -EINVAL;
1365         }
1366
1367         return ret;
1368         
1369 }
1370
1371 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
1372 {
1373         int ret = 0;
1374         u32 wep_key_idx, wep_key_len,wep_total_len;
1375         NDIS_802_11_WEP  *pwep = NULL;  
1376         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1377         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;               
1378         struct security_priv *psecuritypriv = &padapter->securitypriv;
1379 #ifdef CONFIG_P2P
1380         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
1381 #endif //CONFIG_P2P
1382
1383 _func_enter_;
1384
1385         param->u.crypt.err = 0;
1386         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
1387
1388         if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
1389         {
1390                 ret =  -EINVAL;
1391                 goto exit;
1392         }
1393
1394         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1395             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1396             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
1397         {
1398
1399                 if (param->u.crypt.idx >= WEP_KEYS
1400 #ifdef CONFIG_IEEE80211W
1401                         && param->u.crypt.idx > BIP_MAX_KEYID
1402 #endif //CONFIG_IEEE80211W
1403                         )
1404                 {
1405                         ret = -EINVAL;
1406                         goto exit;
1407                 }
1408         } 
1409         else 
1410         {
1411 #ifdef CONFIG_WAPI_SUPPORT
1412                 if (strcmp(param->u.crypt.alg, "SMS4"))
1413 #endif
1414                 {
1415                         ret = -EINVAL;
1416                         goto exit;
1417                 }
1418         }
1419
1420         if (strcmp(param->u.crypt.alg, "WEP") == 0)
1421         {
1422                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("wpa_set_encryption, crypt.alg = WEP\n"));
1423                 DBG_871X("wpa_set_encryption, crypt.alg = WEP\n");
1424
1425                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1426                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
1427                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
1428
1429                 wep_key_idx = param->u.crypt.idx;
1430                 wep_key_len = param->u.crypt.key_len;
1431
1432                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("(1)wep_key_idx=%d\n", wep_key_idx));
1433                 DBG_871X("(1)wep_key_idx=%d\n", wep_key_idx);
1434
1435                 if (wep_key_idx > WEP_KEYS)
1436                         return -EINVAL;
1437
1438                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("(2)wep_key_idx=%d\n", wep_key_idx));
1439
1440                 if (wep_key_len > 0) 
1441                 {
1442                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
1443                         wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
1444                         pwep =(NDIS_802_11_WEP   *) rtw_malloc(wep_total_len);
1445                         if(pwep == NULL){
1446                                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,(" wpa_set_encryption: pwep allocate fail !!!\n"));
1447                                 goto exit;
1448                         }
1449
1450                         _rtw_memset(pwep, 0, wep_total_len);
1451
1452                         pwep->KeyLength = wep_key_len;
1453                         pwep->Length = wep_total_len;
1454
1455                         if(wep_key_len==13)
1456                         {
1457                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
1458                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;
1459                         }
1460                 }
1461                 else {          
1462                         ret = -EINVAL;
1463                         goto exit;
1464                 }
1465
1466                 pwep->KeyIndex = wep_key_idx;
1467                 pwep->KeyIndex |= 0x80000000;
1468
1469                 _rtw_memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
1470
1471                 if(param->u.crypt.set_tx)
1472                 {
1473                         DBG_871X("wep, set_tx=1\n");
1474
1475                         if(rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
1476                         {
1477                                 ret = -EOPNOTSUPP ;
1478                         }
1479                 }
1480                 else
1481                 {
1482                         DBG_871X("wep, set_tx=0\n");
1483                         
1484                         //don't update "psecuritypriv->dot11PrivacyAlgrthm" and 
1485                         //"psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to fw/cam
1486                         
1487                         if (wep_key_idx >= WEP_KEYS) {
1488                                 ret = -EOPNOTSUPP ;
1489                                 goto exit;
1490                         }                               
1491                         
1492                       _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
1493                         psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;     
1494                         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, _TRUE);
1495                 }
1496
1497                 goto exit;              
1498         }
1499
1500         if(padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) // 802_1x
1501         {
1502                 struct sta_info * psta,*pbcmc_sta;
1503                 struct sta_priv * pstapriv = &padapter->stapriv;
1504
1505                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) //sta mode
1506                 {
1507                         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));                         
1508                         if (psta == NULL) {
1509                                 //DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n"));
1510                         }
1511                         else
1512                         {
1513                                 //Jeff: don't disable ieee8021x_blocked while clearing key
1514                                 if (strcmp(param->u.crypt.alg, "none") != 0) 
1515                                         psta->ieee8021x_blocked = _FALSE;
1516                                 
1517                                 if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
1518                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
1519                                 {
1520                                         psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1521                                 }               
1522
1523                                 if(param->u.crypt.set_tx ==1)//pairwise key
1524                                 { 
1525                                         _rtw_memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
1526                                         
1527                                         if(strcmp(param->u.crypt.alg, "TKIP") == 0)//set mic key
1528                                         {                                               
1529                                                 //DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len));
1530                                                 _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
1531                                                 _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
1532
1533                                                 padapter->securitypriv.busetkipkey=_FALSE;
1534                                                 //_set_timer(&padapter->securitypriv.tkip_timer, 50);                                           
1535                                         }
1536
1537                                         //DEBUG_ERR((" param->u.crypt.key_len=%d\n",param->u.crypt.key_len));
1538                                         DBG_871X(" ~~~~set sta key:unicastkey\n");
1539                                         
1540                                         rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _TRUE);
1541                                 }
1542                                 else//group key
1543                                 {                                       
1544                                         if(strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0)
1545                                         {
1546                                                 _rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key,(param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
1547                                                 //only TKIP group key need to install this
1548                                                 if(param->u.crypt.key_len > 16)
1549                                                 {
1550                                                         _rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[16]),8);
1551                                                         _rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[24]),8);
1552                                                 }
1553                                                 padapter->securitypriv.binstallGrpkey = _TRUE;  
1554                                                 //DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len));
1555                                                 DBG_871X(" ~~~~set sta key:groupkey\n");
1556         
1557                                                 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
1558         
1559                                                 rtw_set_key(padapter,&padapter->securitypriv,param->u.crypt.idx, 1, _TRUE);
1560                                         }
1561 #ifdef CONFIG_IEEE80211W
1562                                         else if(strcmp(param->u.crypt.alg, "BIP") == 0)
1563                                         {
1564                                                 int no;
1565                                                 //printk("BIP key_len=%d , index=%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx);
1566                                                 //save the IGTK key, length 16 bytes
1567                                                 _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));
1568                                                 /*printk("IGTK key below:\n");
1569                                                 for(no=0;no<16;no++)
1570                                                         printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
1571                                                 printk("\n");*/
1572                                                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
1573                                                 padapter->securitypriv.binstallBIPkey = _TRUE;
1574                                                 DBG_871X(" ~~~~set sta key:IGKT\n");
1575                                         }
1576 #endif //CONFIG_IEEE80211W
1577                                         
1578 #ifdef CONFIG_P2P
1579                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1580                                         {
1581                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
1582                                         }
1583 #endif //CONFIG_P2P
1584                                         
1585                                 }                                               
1586                         }
1587
1588                         pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
1589                         if(pbcmc_sta==NULL)
1590                         {
1591                                 //DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null \n"));
1592                         }
1593                         else
1594                         {
1595                                 //Jeff: don't disable ieee8021x_blocked while clearing key
1596                                 if (strcmp(param->u.crypt.alg, "none") != 0) 
1597                                         pbcmc_sta->ieee8021x_blocked = _FALSE;
1598                                 
1599                                 if((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
1600                                                 (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
1601                                 {                                                       
1602                                         pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1603                                 }                                       
1604                         }                               
1605                 }
1606                 else if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) //adhoc mode
1607                 {               
1608                 }                       
1609         }
1610
1611 #ifdef CONFIG_WAPI_SUPPORT
1612         if (strcmp(param->u.crypt.alg, "SMS4") == 0)
1613         {
1614                 PRT_WAPI_T                      pWapiInfo = &padapter->wapiInfo;
1615                 PRT_WAPI_STA_INFO       pWapiSta;
1616                 u8                                      WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
1617                 u8                                      WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
1618                 u8                                      WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
1619
1620                 if(param->u.crypt.set_tx == 1)
1621                 {
1622                         list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
1623                                 if(_rtw_memcmp(pWapiSta->PeerMacAddr,param->sta_addr,6))
1624                                 {
1625                                         _rtw_memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
1626
1627                                         pWapiSta->wapiUsk.bSet = true;
1628                                         _rtw_memcpy(pWapiSta->wapiUsk.dataKey,param->u.crypt.key,16);
1629                                         _rtw_memcpy(pWapiSta->wapiUsk.micKey,param->u.crypt.key+16,16);
1630                                         pWapiSta->wapiUsk.keyId = param->u.crypt.idx ;
1631                                         pWapiSta->wapiUsk.bTxEnable = true;
1632
1633                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);
1634                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);
1635                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);
1636                                         _rtw_memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);
1637                                         _rtw_memcpy(pWapiSta->lastRxUnicastPN,WapiAEPNInitialValueSrc,16);
1638                                         pWapiSta->wapiUskUpdate.bTxEnable = false;
1639                                         pWapiSta->wapiUskUpdate.bSet = false;
1640
1641                                         if (psecuritypriv->sw_encrypt== false || psecuritypriv->sw_decrypt == false)
1642                                         {
1643                                                 //set unicast key for ASUE
1644                                                 rtw_wapi_set_key(padapter, &pWapiSta->wapiUsk, pWapiSta, false, false);
1645                                         }
1646                                 }
1647                         }
1648                 }
1649                 else
1650                 {
1651                         list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
1652                                 if(_rtw_memcmp(pWapiSta->PeerMacAddr,get_bssid(pmlmepriv),6))
1653                                 {
1654                                         pWapiSta->wapiMsk.bSet = true;
1655                                         _rtw_memcpy(pWapiSta->wapiMsk.dataKey,param->u.crypt.key,16);
1656                                         _rtw_memcpy(pWapiSta->wapiMsk.micKey,param->u.crypt.key+16,16);
1657                                         pWapiSta->wapiMsk.keyId = param->u.crypt.idx ;
1658                                         pWapiSta->wapiMsk.bTxEnable = false;
1659                                         if(!pWapiSta->bSetkeyOk)
1660                                                 pWapiSta->bSetkeyOk = true;
1661                                         pWapiSta->bAuthenticateInProgress = false;
1662
1663                                         _rtw_memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
1664
1665                                         if (psecuritypriv->sw_decrypt == false)
1666                                         {
1667                                                 //set rx broadcast key for ASUE
1668                                                 rtw_wapi_set_key(padapter, &pWapiSta->wapiMsk, pWapiSta, true, false);
1669                                         }
1670                                 }
1671
1672                         }
1673                 }
1674         }
1675 #endif
1676
1677 exit:
1678         
1679         if (pwep) {
1680                 rtw_mfree((u8 *)pwep, wep_total_len);           
1681         }       
1682         
1683 _func_exit_;
1684
1685         return ret;     
1686 }
1687
1688 static int rtw_set_wpa_ie(_adapter *padapter, char *pie, unsigned short ielen)
1689 {
1690         u8 *buf=NULL, *pos=NULL;        
1691         u32 left;       
1692         int group_cipher = 0, pairwise_cipher = 0;
1693         int ret = 0;
1694         u8 null_addr[]= {0,0,0,0,0,0};
1695 #ifdef CONFIG_P2P
1696         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
1697 #endif //CONFIG_P2P
1698
1699         if((ielen > MAX_WPA_IE_LEN) || (pie == NULL)){
1700                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1701                 if(pie == NULL) 
1702                         return ret;
1703                 else
1704                         return -EINVAL;
1705         }
1706
1707         if(ielen)
1708         {               
1709                 buf = rtw_zmalloc(ielen);
1710                 if (buf == NULL){
1711                         ret =  -ENOMEM;
1712                         goto exit;
1713                 }
1714         
1715                 _rtw_memcpy(buf, pie , ielen);
1716
1717                 //dump
1718                 {
1719                         int i;
1720                         DBG_871X("\n wpa_ie(length:%d):\n", ielen);
1721                         for(i=0;i<ielen;i=i+8)
1722                                 DBG_871X("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",buf[i],buf[i+1],buf[i+2],buf[i+3],buf[i+4],buf[i+5],buf[i+6],buf[i+7]);
1723                 }
1724         
1725                 pos = buf;
1726                 if(ielen < RSN_HEADER_LEN){
1727                         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("Ie len too short %d\n", ielen));
1728                         ret  = -1;
1729                         goto exit;
1730                 }
1731
1732 #if 0
1733                 pos += RSN_HEADER_LEN;
1734                 left  = ielen - RSN_HEADER_LEN;
1735                 
1736                 if (left >= RSN_SELECTOR_LEN){
1737                         pos += RSN_SELECTOR_LEN;
1738                         left -= RSN_SELECTOR_LEN;
1739                 }               
1740                 else if (left > 0){
1741                         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("Ie length mismatch, %u too much \n", left));
1742                         ret =-1;
1743                         goto exit;
1744                 }
1745 #endif          
1746                 
1747                 if(rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
1748                 {
1749                         padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
1750                         padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPAPSK;
1751                         _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);      
1752                 }
1753         
1754                 if(rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
1755                 {
1756                         padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
1757                         padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeWPA2PSK;  
1758                         _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);      
1759                 }
1760                         
1761                 if (group_cipher == 0)
1762                 {
1763                         group_cipher = WPA_CIPHER_NONE;
1764                 }
1765                 if (pairwise_cipher == 0)
1766                 {
1767                         pairwise_cipher = WPA_CIPHER_NONE;
1768                 }
1769                         
1770                 switch(group_cipher)
1771                 {
1772                         case WPA_CIPHER_NONE:
1773                                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
1774                                 padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;
1775                                 break;
1776                         case WPA_CIPHER_WEP40:
1777                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;
1778                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1779                                 break;
1780                         case WPA_CIPHER_TKIP:
1781                                 padapter->securitypriv.dot118021XGrpPrivacy=_TKIP_;
1782                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1783                                 break;
1784                         case WPA_CIPHER_CCMP:
1785                                 padapter->securitypriv.dot118021XGrpPrivacy=_AES_;
1786                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1787                                 break;
1788                         case WPA_CIPHER_WEP104: 
1789                                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP104_;
1790                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1791                                 break;
1792                 }
1793
1794                 switch(pairwise_cipher)
1795                 {
1796                         case WPA_CIPHER_NONE:
1797                                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
1798                                 padapter->securitypriv.ndisencryptstatus=Ndis802_11EncryptionDisabled;
1799                                 break;
1800                         case WPA_CIPHER_WEP40:
1801                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
1802                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1803                                 break;
1804                         case WPA_CIPHER_TKIP:
1805                                 padapter->securitypriv.dot11PrivacyAlgrthm=_TKIP_;
1806                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1807                                 break;
1808                         case WPA_CIPHER_CCMP:
1809                                 padapter->securitypriv.dot11PrivacyAlgrthm=_AES_;
1810                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1811                                 break;
1812                         case WPA_CIPHER_WEP104: 
1813                                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
1814                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1815                                 break;
1816                 }
1817                 
1818                 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1819                 {//set wps_ie   
1820                         u16 cnt = 0;    
1821                         u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
1822                          
1823                         while( cnt < ielen )
1824                         {
1825                                 eid = buf[cnt];
1826                 
1827                                 if((eid==_VENDOR_SPECIFIC_IE_)&&(_rtw_memcmp(&buf[cnt+2], wps_oui, 4)==_TRUE))
1828                                 {
1829                                         DBG_871X("SET WPS_IE\n");
1830
1831                                         padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN;
1832
1833                                         _rtw_memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
1834                                         
1835                                         set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1836                                         
1837 #ifdef CONFIG_P2P
1838                                         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
1839                                         {
1840                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
1841                                         }
1842 #endif //CONFIG_P2P
1843                                         cnt += buf[cnt+1]+2;
1844                                         
1845                                         break;
1846                                 } else {
1847                                         cnt += buf[cnt+1]+2; //goto next        
1848                                 }                               
1849                         }                       
1850                 }               
1851         }
1852         
1853         //TKIP and AES disallow multicast packets until installing group key
1854         if(padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
1855                 || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
1856                 || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
1857                 //WPS open need to enable multicast
1858                 //|| check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE)
1859                 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
1860         
1861         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1862                  ("rtw_set_wpa_ie: pairwise_cipher=0x%08x padapter->securitypriv.ndisencryptstatus=%d padapter->securitypriv.ndisauthtype=%d\n",
1863                   pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
1864         
1865 exit:
1866
1867         if (buf) rtw_mfree(buf, ielen);
1868
1869         return ret;
1870 }
1871
1872 static int rtw_wx_get_name(struct net_device *dev, 
1873                              struct iw_request_info *info, 
1874                              union iwreq_data *wrqu, char *extra)
1875 {
1876         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1877         u16 cap;
1878         u32 ht_ielen = 0;
1879         char *p;
1880         u8 ht_cap=_FALSE, vht_cap=_FALSE;
1881         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1882         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
1883         NDIS_802_11_RATES_EX* prates = NULL;
1884
1885         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("cmd_code=%x\n", info->cmd));
1886
1887         _func_enter_;   
1888
1889         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE)
1890         {
1891                 //parsing HT_CAP_IE
1892                 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
1893                 if(p && ht_ielen>0)
1894                 {
1895                         ht_cap = _TRUE;
1896                 }
1897
1898 #ifdef CONFIG_80211AC_VHT
1899                 if(pmlmepriv->vhtpriv.vht_option == _TRUE)
1900                         vht_cap = _TRUE;
1901 #endif
1902
1903                 prates = &pcur_bss->SupportedRates;
1904
1905                 if (rtw_is_cckratesonly_included((u8*)prates) == _TRUE)
1906                 {
1907                         if(ht_cap == _TRUE)
1908                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
1909                         else
1910                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
1911                 }
1912                 else if ((rtw_is_cckrates_included((u8*)prates)) == _TRUE)
1913                 {
1914                         if(ht_cap == _TRUE)
1915                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
1916                         else
1917                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
1918                 }
1919                 else
1920                 {
1921                         if(pcur_bss->Configuration.DSConfig > 14)
1922                         {
1923                         #ifdef CONFIG_80211AC_VHT
1924                                 if(vht_cap == _TRUE){
1925                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC");
1926                                 }
1927                                 else
1928                         #endif
1929                                 {
1930                                         if(ht_cap == _TRUE)
1931                                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
1932                                         else
1933                                                 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
1934                                 }
1935                         }
1936                         else
1937                         {
1938                                 if(ht_cap == _TRUE)
1939                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
1940                                 else
1941                                         snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
1942                         }
1943                 }
1944         }
1945         else
1946         {
1947                 //prates = &padapter->registrypriv.dev_network.SupportedRates;
1948                 //snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
1949                 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
1950         }
1951
1952         _func_exit_;
1953
1954         return 0;
1955 }
1956
1957 static int rtw_wx_set_freq(struct net_device *dev, 
1958                              struct iw_request_info *info, 
1959                              union iwreq_data *wrqu, char *extra)
1960 {       
1961
1962         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1963         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1964         struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
1965         int exp = 1, freq = 0, div = 0;
1966
1967         _func_enter_;
1968
1969         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
1970
1971         if (wrqu->freq.m <= 1000) {
1972                 if (wrqu->freq.flags == IW_FREQ_AUTO) {
1973                         padapter->mlmeextpriv.cur_channel = 1;
1974                         DBG_871X("%s: channel is auto, set to channel 1\n", __func__);
1975                 } else {
1976                         padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
1977                         DBG_871X("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
1978                 }
1979         } else {
1980                 while (wrqu->freq.e) {
1981                         exp *= 10;
1982                         wrqu->freq.e--;
1983                 }
1984
1985                 freq = wrqu->freq.m;
1986                 while (!(freq%10)) {
1987                         freq /= 10;
1988                         exp *= 10;
1989                 }
1990
1991                 /* freq unit is MHz here */
1992                 div = 1000000/exp;
1993
1994                 if (div)
1995                         freq /= div;
1996                 else {
1997                         div = exp/1000000;
1998                         freq *= div;
1999                 }
2000
2001                 /* If freq is invalid, rtw_freq2ch() will return channel 1 */
2002                 padapter->mlmeextpriv.cur_channel = rtw_freq2ch(freq);
2003                 DBG_871X("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
2004         }
2005
2006         _func_exit_;
2007         
2008         return 0;
2009 }
2010
2011 static int rtw_wx_get_freq(struct net_device *dev, 
2012                              struct iw_request_info *info, 
2013                              union iwreq_data *wrqu, char *extra)
2014 {
2015         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2016         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2017         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
2018         
2019         if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
2020         {
2021                 //wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000;
2022                 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
2023                 wrqu->freq.e = 1;
2024                 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
2025
2026         }
2027         else{
2028                 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
2029                 wrqu->freq.e = 1;
2030                 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
2031         }
2032
2033         return 0;
2034 }
2035
2036 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
2037                              union iwreq_data *wrqu, char *b)
2038 {
2039         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2040         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
2041         int ret = 0;
2042         
2043         _func_enter_;
2044         
2045         if(_FAIL == rtw_pwr_wakeup(padapter)) {
2046                 ret= -EPERM;
2047                 goto exit;
2048         }
2049
2050         if (padapter->hw_init_completed==_FALSE){
2051                 ret = -EPERM;
2052                 goto exit;
2053         }
2054
2055         /* initial default type */
2056         dev->type = ARPHRD_ETHER;
2057
2058         switch(wrqu->mode)
2059         {
2060                 case IW_MODE_MONITOR:
2061                         networkType = Ndis802_11Monitor;
2062 #if 0
2063                         dev->type = ARPHRD_IEEE80211; /* IEEE 802.11 : 801 */
2064 #endif
2065                         dev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */
2066                         DBG_871X("set_mode = IW_MODE_MONITOR\n");
2067                         break;
2068
2069                 case IW_MODE_AUTO:
2070                         networkType = Ndis802_11AutoUnknown;
2071                         DBG_871X("set_mode = IW_MODE_AUTO\n");  
2072                         break;                          
2073                 case IW_MODE_ADHOC:             
2074                         networkType = Ndis802_11IBSS;
2075                         DBG_871X("set_mode = IW_MODE_ADHOC\n");                 
2076                         break;
2077                 case IW_MODE_MASTER:            
2078                         networkType = Ndis802_11APMode;
2079                         DBG_871X("set_mode = IW_MODE_MASTER\n");
2080                         //rtw_setopmode_cmd(padapter, networkType,_TRUE);       
2081                         break;                          
2082                 case IW_MODE_INFRA:
2083                         networkType = Ndis802_11Infrastructure;
2084                         DBG_871X("set_mode = IW_MODE_INFRA\n");                 
2085                         break;
2086         
2087                 default :
2088                         ret = -EINVAL;;
2089                         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("\n Mode: %s is not supported  \n", iw_operation_mode[wrqu->mode]));
2090                         goto exit;
2091         }
2092         
2093 /*      
2094         if(Ndis802_11APMode == networkType)
2095         {
2096                 rtw_setopmode_cmd(padapter, networkType,_TRUE);
2097         }       
2098         else
2099         {
2100                 rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown,_TRUE);       
2101         }
2102 */
2103         
2104         if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==_FALSE){
2105
2106                 ret = -EPERM;
2107                 goto exit;
2108
2109         }
2110
2111         rtw_setopmode_cmd(padapter, networkType,_TRUE);
2112
2113 exit:
2114         
2115         _func_exit_;
2116         
2117         return ret;
2118         
2119 }
2120
2121 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
2122                              union iwreq_data *wrqu, char *b)
2123 {
2124         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2125         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2126         
2127         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_get_mode \n"));
2128
2129         _func_enter_;
2130         
2131         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
2132         {
2133                 wrqu->mode = IW_MODE_INFRA;
2134         }
2135         else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) ||
2136                        (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
2137                 
2138         {
2139                 wrqu->mode = IW_MODE_ADHOC;
2140         }
2141         else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2142         {
2143                 wrqu->mode = IW_MODE_MASTER;
2144         }
2145         else
2146         {
2147                 wrqu->mode = IW_MODE_AUTO;
2148         }
2149
2150         _func_exit_;
2151         
2152         return 0;
2153         
2154 }
2155
2156
2157 static int rtw_wx_set_pmkid(struct net_device *dev,
2158                              struct iw_request_info *a,
2159                              union iwreq_data *wrqu, char *extra)
2160 {
2161         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2162         u8          j,blInserted = _FALSE;
2163         int         intReturn = _FALSE;
2164         struct mlme_priv  *pmlmepriv = &padapter->mlmepriv;
2165         struct security_priv *psecuritypriv = &padapter->securitypriv;
2166         struct iw_pmksa*  pPMK = ( struct iw_pmksa* ) extra;
2167         u8     strZeroMacAddress[ ETH_ALEN ] = { 0x00 };
2168         u8     strIssueBssid[ ETH_ALEN ] = { 0x00 };
2169         
2170 /*
2171         struct iw_pmksa
2172         {
2173             __u32   cmd;
2174             struct sockaddr bssid;
2175             __u8    pmkid[IW_PMKID_LEN];   //IW_PMKID_LEN=16
2176         }
2177         There are the BSSID information in the bssid.sa_data array.
2178         If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
2179         If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
2180         If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
2181         */
2182
2183         _rtw_memcpy( strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
2184         if ( pPMK->cmd == IW_PMKSA_ADD )
2185         {
2186                 DBG_871X( "[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n" );
2187                 if ( _rtw_memcmp( strIssueBssid, strZeroMacAddress, ETH_ALEN ) == _TRUE )
2188                 {
2189                     return( intReturn );
2190                 }
2191                 else
2192                 {
2193                     intReturn = _TRUE;
2194                 }
2195                 blInserted = _FALSE;
2196                 
2197                 //overwrite PMKID
2198                 for(j=0 ; j<NUM_PMKID_CACHE; j++)
2199                 {
2200                         if( _rtw_memcmp( psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ==_TRUE )
2201                         { // BSSID is matched, the same AP => rewrite with new PMKID.
2202                                 
2203                                 DBG_871X( "[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n" );
2204
2205                                 _rtw_memcpy( psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
2206                                 psecuritypriv->PMKIDList[ j ].bUsed = _TRUE;
2207                                 psecuritypriv->PMKIDIndex = j+1;
2208                                 blInserted = _TRUE;
2209                                 break;
2210                         }       
2211                 }
2212
2213                 if(!blInserted)
2214                 {
2215                     // Find a new entry
2216                     DBG_871X( "[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
2217                             psecuritypriv->PMKIDIndex );
2218
2219                     _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
2220                     _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
2221
2222                     psecuritypriv->PMKIDList[ psecuritypriv->PMKIDIndex ].bUsed = _TRUE;
2223                     psecuritypriv->PMKIDIndex++ ;
2224                     if(psecuritypriv->PMKIDIndex==16)
2225                     {
2226                         psecuritypriv->PMKIDIndex =0;
2227                     }
2228                 }
2229         }
2230         else if ( pPMK->cmd == IW_PMKSA_REMOVE )
2231         {
2232                 DBG_871X( "[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n" );
2233                 intReturn = _TRUE;
2234                 for(j=0 ; j<NUM_PMKID_CACHE; j++)
2235                 {
2236                         if( _rtw_memcmp( psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ==_TRUE )
2237                         { // BSSID is matched, the same AP => Remove this PMKID information and reset it. 
2238                                 _rtw_memset( psecuritypriv->PMKIDList[ j ].Bssid, 0x00, ETH_ALEN );
2239                                 psecuritypriv->PMKIDList[ j ].bUsed = _FALSE;
2240                                 break;
2241                         }       
2242                 }
2243         }
2244         else if ( pPMK->cmd == IW_PMKSA_FLUSH ) 
2245         {
2246             DBG_871X( "[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n" );
2247             _rtw_memset( &psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
2248             psecuritypriv->PMKIDIndex = 0;
2249             intReturn = _TRUE;
2250         }
2251     return( intReturn );
2252 }
2253
2254 static int rtw_wx_get_sens(struct net_device *dev, 
2255                              struct iw_request_info *info, 
2256                              union iwreq_data *wrqu, char *extra)
2257 {
2258         #ifdef CONFIG_PLATFORM_ROCKCHIPS
2259         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2260         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 
2261         
2262         /*
2263         *  20110311 Commented by Jeff
2264         *  For rockchip platform's wpa_driver_wext_get_rssi
2265         */
2266         if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
2267                 //wrqu->sens.value=-padapter->recvpriv.signal_strength;
2268                 wrqu->sens.value=-padapter->recvpriv.rssi;
2269                 //DBG_871X("%s: %d\n", __FUNCTION__, wrqu->sens.value);
2270                 wrqu->sens.fixed = 0; /* no auto select */ 
2271         } else 
2272         #endif
2273         {
2274                 wrqu->sens.value = 0;
2275                 wrqu->sens.fixed = 0;   /* no auto select */
2276                 wrqu->sens.disabled = 1;
2277         }
2278         return 0;
2279 }
2280
2281 static int rtw_wx_get_range(struct net_device *dev, 
2282                                 struct iw_request_info *info, 
2283                                 union iwreq_data *wrqu, char *extra)
2284 {
2285         struct iw_range *range = (struct iw_range *)extra;
2286         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2287         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2288
2289         u16 val;
2290         int i;
2291         
2292         _func_enter_;
2293         
2294         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_range. cmd_code=%x\n", info->cmd));
2295
2296         wrqu->data.length = sizeof(*range);
2297         _rtw_memset(range, 0, sizeof(*range));
2298
2299         /* Let's try to keep this struct in the same order as in
2300          * linux/include/wireless.h
2301          */
2302
2303         /* TODO: See what values we can set, and remove the ones we can't
2304          * set, or fill them with some default data.
2305          */
2306
2307         /* ~5 Mb/s real (802.11b) */
2308         range->throughput = 5 * 1000 * 1000;     
2309
2310         // TODO: Not used in 802.11b?
2311 //      range->min_nwid;        /* Minimal NWID we are able to set */
2312         // TODO: Not used in 802.11b?
2313 //      range->max_nwid;        /* Maximal NWID we are able to set */
2314
2315         /* Old Frequency (backward compat - moved lower ) */
2316 //      range->old_num_channels; 
2317 //      range->old_num_frequency;
2318 //      range->old_freq[6]; /* Filler to keep "version" at the same offset */
2319
2320         /* signal level threshold range */
2321
2322         //percent values between 0 and 100.
2323         range->max_qual.qual = 100;     
2324         range->max_qual.level = 100;
2325         range->max_qual.noise = 100;
2326         range->max_qual.updated = 7; /* Updated all three */
2327
2328
2329         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
2330         /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
2331         range->avg_qual.level = 20 + -98;
2332         range->avg_qual.noise = 0;
2333         range->avg_qual.updated = 7; /* Updated all three */
2334
2335         range->num_bitrates = RATE_COUNT;
2336
2337         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
2338                 range->bitrate[i] = rtw_rates[i];
2339         }
2340
2341         range->min_frag = MIN_FRAG_THRESHOLD;
2342         range->max_frag = MAX_FRAG_THRESHOLD;
2343
2344         range->pm_capa = 0;
2345
2346         range->we_version_compiled = WIRELESS_EXT;
2347         range->we_version_source = 16;
2348
2349 //      range->retry_capa;      /* What retry options are supported */
2350 //      range->retry_flags;     /* How to decode max/min retry limit */
2351 //      range->r_time_flags;    /* How to decode max/min retry life */
2352 //      range->min_retry;       /* Minimal number of retries */
2353 //      range->max_retry;       /* Maximal number of retries */
2354 //      range->min_r_time;      /* Minimal retry lifetime */
2355 //      range->max_r_time;      /* Maximal retry lifetime */
2356
2357         for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
2358
2359                 // Include only legal frequencies for some countries
2360                 if(pmlmeext->channel_set[i].ChannelNum != 0)
2361                 {
2362                         range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
2363                         range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
2364                         range->freq[val].e = 1;
2365                         val++;
2366                 }
2367
2368                 if (val == IW_MAX_FREQUENCIES)
2369                         break;
2370         }
2371
2372         range->num_channels = val;
2373         range->num_frequency = val;
2374
2375 // Commented by Albert 2009/10/13
2376 // The following code will proivde the security capability to network manager.
2377 // If the driver doesn't provide this capability to network manager,
2378 // the WPA/WPA2 routers can't be choosen in the network manager.
2379
2380 /*
2381 #define IW_SCAN_CAPA_NONE               0x00
2382 #define IW_SCAN_CAPA_ESSID              0x01
2383 #define IW_SCAN_CAPA_BSSID              0x02
2384 #define IW_SCAN_CAPA_CHANNEL    0x04
2385 #define IW_SCAN_CAPA_MODE               0x08
2386 #define IW_SCAN_CAPA_RATE               0x10
2387 #define IW_SCAN_CAPA_TYPE               0x20
2388 #define IW_SCAN_CAPA_TIME               0x40
2389 */
2390
2391 #if WIRELESS_EXT > 17
2392         range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
2393                           IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
2394 #endif
2395
2396 #ifdef IW_SCAN_CAPA_ESSID //WIRELESS_EXT > 21
2397         range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |IW_SCAN_CAPA_BSSID|
2398                                         IW_SCAN_CAPA_CHANNEL|IW_SCAN_CAPA_MODE|IW_SCAN_CAPA_RATE;
2399 #endif
2400
2401
2402         _func_exit_;
2403
2404         return 0;
2405
2406 }
2407
2408 //set bssid flow
2409 //s1. rtw_set_802_11_infrastructure_mode()
2410 //s2. rtw_set_802_11_authentication_mode()
2411 //s3. set_802_11_encryption_mode()
2412 //s4. rtw_set_802_11_bssid()
2413 static int rtw_wx_set_wap(struct net_device *dev,
2414                          struct iw_request_info *info,
2415                          union iwreq_data *awrq,
2416                          char *extra)
2417 {
2418         _irqL   irqL;
2419         uint ret = 0;
2420         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2421         struct sockaddr *temp = (struct sockaddr *)awrq;
2422         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2423         _list   *phead;
2424         u8 *dst_bssid, *src_bssid;
2425         _queue  *queue  = &(pmlmepriv->scanned_queue);
2426         struct  wlan_network    *pnetwork = NULL;
2427         NDIS_802_11_AUTHENTICATION_MODE authmode;
2428
2429         _func_enter_;
2430 /*
2431 #ifdef CONFIG_CONCURRENT_MODE
2432         if(padapter->iface_type > PRIMARY_IFACE)
2433         {
2434                 ret = -EINVAL;
2435                 goto exit;
2436         }
2437 #endif  
2438 */      
2439
2440 #ifdef CONFIG_CONCURRENT_MODE
2441         if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
2442         {
2443                 DBG_871X("set bssid, but buddy_intf is under scanning or linking\n");
2444
2445                 ret = -EINVAL;
2446
2447                 goto exit;
2448         }
2449 #endif
2450
2451         rtw_ps_deny(padapter, PS_DENY_JOIN);
2452         if(_FAIL == rtw_pwr_wakeup(padapter))
2453         {
2454                 ret= -1;
2455                 goto exit;
2456         }
2457         
2458         if(!padapter->bup){
2459                 ret = -1;
2460                 goto exit;
2461         }
2462
2463         
2464         if (temp->sa_family != ARPHRD_ETHER){
2465                 ret = -EINVAL;
2466                 goto exit;
2467         }
2468
2469         authmode = padapter->securitypriv.ndisauthtype;
2470         _enter_critical_bh(&queue->lock, &irqL);
2471        phead = get_list_head(queue);
2472        pmlmepriv->pscanned = get_next(phead);
2473
2474         while (1)
2475          {
2476                         
2477                 if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == _TRUE)
2478                 {
2479 #if 0           
2480                         ret = -EINVAL;
2481                         goto exit;
2482
2483                         if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
2484                         {
2485                                 rtw_set_802_11_bssid(padapter, temp->sa_data);
2486                                 goto exit;                    
2487                         }
2488                         else
2489                         {
2490                                 ret = -EINVAL;
2491                                 goto exit;
2492                         }
2493 #endif
2494
2495                         break;
2496                 }
2497         
2498                 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
2499
2500                 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
2501
2502                 dst_bssid = pnetwork->network.MacAddress;
2503
2504                 src_bssid = temp->sa_data;
2505
2506                 if ((_rtw_memcmp(dst_bssid, src_bssid, ETH_ALEN)) == _TRUE)
2507                 {                       
2508                         if(!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode))
2509                         {
2510                                 ret = -1;
2511                                 _exit_critical_bh(&queue->lock, &irqL);
2512                                 goto exit;
2513                         }
2514
2515                                 break;                  
2516                 }
2517
2518         }               
2519         _exit_critical_bh(&queue->lock, &irqL);
2520         
2521         rtw_set_802_11_authentication_mode(padapter, authmode);
2522         //set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
2523         if (rtw_set_802_11_bssid(padapter, temp->sa_data) == _FALSE) {
2524                 ret = -1;
2525                 goto exit;              
2526         }       
2527         
2528 exit:
2529         
2530         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
2531
2532         _func_exit_;
2533         
2534         return ret;     
2535 }
2536
2537 static int rtw_wx_get_wap(struct net_device *dev, 
2538                             struct iw_request_info *info, 
2539                             union iwreq_data *wrqu, char *extra)
2540 {
2541
2542         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
2543         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2544         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;     
2545         
2546         wrqu->ap_addr.sa_family = ARPHRD_ETHER;
2547         
2548         _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
2549         
2550         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_wap\n"));
2551
2552         _func_enter_;
2553
2554         if  ( ((check_fwstate(pmlmepriv, _FW_LINKED)) == _TRUE) || 
2555                         ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE) ||
2556                         ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == _TRUE) )
2557         {
2558
2559                 _rtw_memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
2560         }
2561         else
2562         {
2563                 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
2564         }               
2565
2566         _func_exit_;
2567         
2568         return 0;
2569         
2570 }
2571
2572 static int rtw_wx_set_mlme(struct net_device *dev, 
2573                              struct iw_request_info *info, 
2574                              union iwreq_data *wrqu, char *extra)
2575 {
2576 #if 0
2577 /* SIOCSIWMLME data */
2578 struct  iw_mlme
2579 {
2580         __u16           cmd; /* IW_MLME_* */
2581         __u16           reason_code;
2582         struct sockaddr addr;
2583 };
2584 #endif
2585
2586         int ret=0;
2587         u16 reason;
2588         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2589         struct iw_mlme *mlme = (struct iw_mlme *) extra;
2590
2591
2592         if(mlme==NULL)
2593                 return -1;
2594
2595         DBG_871X("%s\n", __FUNCTION__);
2596
2597         reason = cpu_to_le16(mlme->reason_code);
2598
2599
2600         DBG_871X("%s, cmd=%d, reason=%d\n", __FUNCTION__, mlme->cmd, reason);
2601         
2602
2603         switch (mlme->cmd) 
2604         {
2605                 case IW_MLME_DEAUTH:
2606                                 if(!rtw_set_802_11_disassociate(padapter))
2607                                         ret = -1;
2608                                 break;
2609
2610                 case IW_MLME_DISASSOC:
2611                                 if(!rtw_set_802_11_disassociate(padapter))
2612                                         ret = -1;
2613
2614                                 break;
2615
2616                 default:
2617                         return -EOPNOTSUPP;
2618         }
2619
2620         return ret;
2621 }
2622
2623 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
2624                              union iwreq_data *wrqu, char *extra)
2625 {
2626         u8 _status = _FALSE;
2627         int ret = 0;    
2628         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2629         struct mlme_priv *pmlmepriv= &padapter->mlmepriv;
2630         NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
2631         _irqL   irqL;
2632 #ifdef CONFIG_P2P
2633         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);   
2634 #endif //CONFIG_P2P
2635         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_set_scan\n"));
2636
2637 _func_enter_;
2638
2639         #ifdef DBG_IOCTL
2640         DBG_871X("DBG_IOCTL %s:%d\n",__FUNCTION__, __LINE__);
2641         #endif
2642 /*
2643 #ifdef CONFIG_CONCURRENT_MODE
2644         if(padapter->iface_type > PRIMARY_IFACE)
2645         {
2646                 ret = -1;
2647                 goto exit;
2648         }
2649 #endif
2650 */
2651 #ifdef CONFIG_MP_INCLUDED
2652                 if (padapter->registrypriv.mp_mode == 1)
2653                 {
2654                                 DBG_871X(FUNC_ADPT_FMT ": MP mode block Scan request\n", FUNC_ADPT_ARG(padapter));      
2655                                 ret = -1;
2656                                 goto exit;
2657                 }
2658 #ifdef CONFIG_CONCURRENT_MODE
2659                 if (padapter->pbuddy_adapter) {
2660                                 if (padapter->pbuddy_adapter->registrypriv.mp_mode == 1)
2661                                 {
2662                                         DBG_871X(FUNC_ADPT_FMT ": MP mode block Scan request\n", FUNC_ADPT_ARG(padapter->pbuddy_adapter));
2663                                         ret = -1;
2664                                         goto exit;
2665                                 }
2666                 }
2667 #endif //CONFIG_CONCURRENT_MODE
2668 #endif
2669
2670         rtw_ps_deny(padapter, PS_DENY_SCAN);
2671         if(_FAIL == rtw_pwr_wakeup(padapter))
2672         {
2673                 ret= -1;
2674                 goto exit;
2675         }
2676
2677         if(padapter->bDriverStopped){
2678            DBG_871X("bDriverStopped=%d\n", padapter->bDriverStopped);
2679                 ret= -1;
2680                 goto exit;
2681         }
2682         
2683         if(!padapter->bup){
2684                 ret = -1;
2685                 goto exit;
2686         }
2687         
2688         if (padapter->hw_init_completed==_FALSE){
2689                 ret = -1;
2690                 goto exit;
2691         }
2692
2693         // When Busy Traffic, driver do not site survey. So driver return success.
2694         // wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout.
2695         // modify by thomas 2011-02-22.
2696         if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE
2697 #ifdef CONFIG_CONCURRENT_MODE
2698         || rtw_get_buddy_bBusyTraffic(padapter) == _TRUE
2699 #endif //CONFIG_CONCURRENT_MODE
2700         )
2701         {
2702                 indicate_wx_scan_complete_event(padapter);
2703                 goto exit;
2704         }
2705
2706         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
2707         {
2708                 indicate_wx_scan_complete_event(padapter);
2709                 goto exit;
2710         } 
2711
2712 #ifdef CONFIG_CONCURRENT_MODE
2713         if (check_buddy_fwstate(padapter,
2714                 _FW_UNDER_SURVEY|_FW_UNDER_LINKING|WIFI_UNDER_WPS) == _TRUE)
2715         {
2716                 indicate_wx_scan_complete_event(padapter);
2717                 goto exit;
2718         }
2719 #endif
2720
2721 #ifdef CONFIG_P2P
2722         if ( pwdinfo->p2p_state != P2P_STATE_NONE )
2723         {
2724                 rtw_p2p_set_pre_state( pwdinfo, rtw_p2p_state( pwdinfo ) );
2725                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
2726                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
2727                 rtw_free_network_queue(padapter, _TRUE);
2728         }
2729 #endif //CONFIG_P2P
2730
2731         _rtw_memset(ssid, 0, sizeof(NDIS_802_11_SSID)*RTW_SSID_SCAN_AMOUNT);
2732
2733 #if WIRELESS_EXT >= 17
2734         if (wrqu->data.length == sizeof(struct iw_scan_req)) 
2735         {
2736                 struct iw_scan_req *req = (struct iw_scan_req *)extra;
2737         
2738                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
2739                 {
2740                         int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
2741
2742                         _rtw_memcpy(ssid[0].Ssid, req->essid, len);
2743                         ssid[0].SsidLength = len;       
2744
2745                         DBG_871X("IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
2746                 
2747                         _enter_critical_bh(&pmlmepriv->lock, &irqL);                            
2748                 
2749                         _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
2750                 
2751                         _exit_critical_bh(&pmlmepriv->lock, &irqL);
2752                         
2753                 }
2754                 else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
2755                 {
2756                         DBG_871X("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
2757                 }
2758                 
2759         }
2760         else
2761 #endif
2762
2763         if(     wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
2764                 && _rtw_memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
2765         )
2766         {
2767                 int len = wrqu->data.length -WEXT_CSCAN_HEADER_SIZE;
2768                 char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
2769                 char section;
2770                 char sec_len;
2771                 int ssid_index = 0;
2772
2773                 //DBG_871X("%s COMBO_SCAN header is recognized\n", __FUNCTION__);
2774                 
2775                 while(len >= 1) {
2776                         section = *(pos++); len-=1;
2777
2778                         switch(section) {
2779                                 case WEXT_CSCAN_SSID_SECTION:
2780                                         //DBG_871X("WEXT_CSCAN_SSID_SECTION\n");
2781                                         if(len < 1) {
2782                                                 len = 0;
2783                                                 break;
2784                                         }
2785                                         
2786                                         sec_len = *(pos++); len-=1;
2787
2788                                         if(sec_len>0 && sec_len<=len) {
2789                                                 ssid[ssid_index].SsidLength = sec_len;
2790                                                 _rtw_memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
2791                                                 //DBG_871X("%s COMBO_SCAN with specific ssid:%s, %d\n", __FUNCTION__
2792                                                 //      , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength);
2793                                                 ssid_index++;
2794                                         }
2795                                         
2796                                         pos+=sec_len; len-=sec_len;
2797                                         break;
2798                                         
2799                                 
2800                                 case WEXT_CSCAN_CHANNEL_SECTION:
2801                                         //DBG_871X("WEXT_CSCAN_CHANNEL_SECTION\n");
2802                                         pos+=1; len-=1;
2803                                         break;
2804                                 case WEXT_CSCAN_ACTV_DWELL_SECTION:
2805                                         //DBG_871X("WEXT_CSCAN_ACTV_DWELL_SECTION\n");
2806                                         pos+=2; len-=2;
2807                                         break;
2808                                 case WEXT_CSCAN_PASV_DWELL_SECTION:
2809                                         //DBG_871X("WEXT_CSCAN_PASV_DWELL_SECTION\n");
2810                                         pos+=2; len-=2;                                 
2811                                         break;
2812                                 case WEXT_CSCAN_HOME_DWELL_SECTION:
2813                                         //DBG_871X("WEXT_CSCAN_HOME_DWELL_SECTION\n");
2814                                         pos+=2; len-=2;
2815                                         break;
2816                                 case WEXT_CSCAN_TYPE_SECTION:
2817                                         //DBG_871X("WEXT_CSCAN_TYPE_SECTION\n");
2818                                         pos+=1; len-=1;
2819                                         break;
2820                                 #if 0
2821                                 case WEXT_CSCAN_NPROBE_SECTION:
2822                                         DBG_871X("WEXT_CSCAN_NPROBE_SECTION\n");
2823                                         break;
2824                                 #endif
2825                                 
2826                                 default:
2827                                         //DBG_871X("Unknown CSCAN section %c\n", section);
2828                                         len = 0; // stop parsing
2829                         }
2830                         //DBG_871X("len:%d\n", len);
2831                         
2832                 }
2833                 
2834                 //jeff: it has still some scan paramater to parse, we only do this now...
2835                 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
2836                 
2837         } else
2838         
2839         {
2840                 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
2841         }
2842
2843         if(_status == _FALSE)
2844                 ret = -1;
2845
2846 exit:
2847
2848         rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
2849
2850         #ifdef DBG_IOCTL
2851         DBG_871X("DBG_IOCTL %s:%d return %d\n",__FUNCTION__, __LINE__, ret);
2852         #endif
2853
2854 _func_exit_;
2855
2856         return ret;     
2857 }
2858
2859 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
2860                              union iwreq_data *wrqu, char *extra)
2861 {
2862         _irqL   irqL;
2863         _list                                   *plist, *phead;
2864         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2865         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
2866         _queue                          *queue  = &(pmlmepriv->scanned_queue);
2867         struct  wlan_network    *pnetwork = NULL;
2868         char *ev = extra;
2869         char *stop = ev + wrqu->data.length;
2870         u32 ret = 0;
2871         u32 cnt=0;
2872         u32 wait_for_surveydone;
2873         sint wait_status;
2874 #ifdef CONFIG_CONCURRENT_MODE
2875         //PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
2876         //struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);      
2877 #endif
2878 #ifdef CONFIG_P2P
2879         struct  wifidirect_info*        pwdinfo = &padapter->wdinfo;
2880 #endif //CONFIG_P2P
2881         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_scan\n"));
2882         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
2883
2884         _func_enter_;
2885
2886         #ifdef DBG_IOCTL
2887         DBG_871X("DBG_IOCTL %s:%d\n",__FUNCTION__, __LINE__);
2888         #endif
2889 /*
2890 #ifdef CONFIG_CONCURRENT_MODE
2891         if(padapter->iface_type > PRIMARY_IFACE)
2892         {
2893                 ret = -EINVAL;
2894                 goto exit;
2895         }
2896 #endif
2897 */      
2898         if(adapter_to_pwrctl(padapter)->brfoffbyhw && padapter->bDriverStopped)
2899         {
2900                 ret = -EINVAL;
2901                 goto exit;
2902         }
2903   
2904 #ifdef CONFIG_P2P
2905         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
2906         {
2907                 wait_for_surveydone = 200;
2908         }
2909         else
2910         {
2911                 //      P2P is disabled
2912                 wait_for_surveydone = 100;
2913         }
2914 #else
2915         {
2916                 wait_for_surveydone = 100;
2917         }
2918 #endif //CONFIG_P2P
2919
2920 #if 1 // Wireless Extension use EAGAIN to try
2921         wait_status = _FW_UNDER_SURVEY
2922 #ifndef CONFIG_ANDROID
2923                 | _FW_UNDER_LINKING
2924 #endif
2925         ;
2926
2927         while (check_fwstate(pmlmepriv, wait_status) == _TRUE)
2928         {
2929                 return -EAGAIN;
2930         }
2931 #else
2932         wait_status = _FW_UNDER_SURVEY
2933                 #ifndef CONFIG_ANDROID
2934                 |_FW_UNDER_LINKING
2935                 #endif
2936         ;
2937
2938         while(check_fwstate(pmlmepriv, wait_status) == _TRUE)
2939         {       
2940                 rtw_msleep_os(30);
2941                 cnt++;
2942                 if(cnt > wait_for_surveydone )
2943                         break;
2944         }
2945 #endif
2946         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2947
2948         phead = get_list_head(queue);
2949         plist = get_next(phead);
2950        
2951         while(1)
2952         {
2953                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
2954                         break;
2955
2956                 if((stop - ev) < SCAN_ITEM_SIZE) {
2957                         ret = -E2BIG;
2958                         break;
2959                 }
2960
2961                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2962
2963                 //report network only if the current channel set contains the channel to which this network belongs
2964                 if(rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
2965                         && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE
2966                         && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
2967                 )
2968                 {
2969                         ev=translate_scan(padapter, a, pnetwork, ev, stop);
2970                 }
2971
2972                 plist = get_next(plist);
2973         
2974         }        
2975
2976         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2977
2978        wrqu->data.length = ev-extra;
2979         wrqu->data.flags = 0;
2980         
2981 exit:           
2982         
2983         _func_exit_;    
2984         
2985         #ifdef DBG_IOCTL
2986         DBG_871X("DBG_IOCTL %s:%d return %d\n",__FUNCTION__, __LINE__, ret);
2987         #endif
2988         
2989         return ret ;
2990         
2991 }
2992
2993 //set ssid flow
2994 //s1. rtw_set_802_11_infrastructure_mode()
2995 //s2. set_802_11_authenticaion_mode()
2996 //s3. set_802_11_encryption_mode()
2997 //s4. rtw_set_802_11_ssid()
2998 static int rtw_wx_set_essid(struct net_device *dev, 
2999                               struct iw_request_info *a,
3000                               union iwreq_data *wrqu, char *extra)
3001 {
3002         _irqL irqL;
3003         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3004         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3005         _queue *queue = &pmlmepriv->scanned_queue;
3006         _list *phead;
3007         s8 status = _TRUE;
3008         struct wlan_network *pnetwork = NULL;
3009         NDIS_802_11_AUTHENTICATION_MODE authmode;       
3010         NDIS_802_11_SSID ndis_ssid;     
3011         u8 *dst_ssid, *src_ssid;
3012
3013         uint ret = 0, len;
3014
3015         _func_enter_;
3016         
3017         #ifdef DBG_IOCTL
3018         DBG_871X("DBG_IOCTL %s:%d\n",__FUNCTION__, __LINE__);
3019         #endif
3020         #ifdef CONFIG_WEXT_DONT_JOIN_BYSSID
3021         DBG_871X("%s: CONFIG_WEXT_DONT_JOIN_BYSSID be defined!! only allow bssid joining\n", __func__);
3022         return -EPERM;
3023         #endif
3024 /*
3025 #ifdef CONFIG_CONCURRENT_MODE
3026         if(padapter->iface_type > PRIMARY_IFACE)
3027         {
3028                 ret = -EINVAL;
3029                 goto exit;
3030         }
3031 #endif
3032 */
3033
3034 #ifdef CONFIG_CONCURRENT_MODE
3035         if (check_buddy_fwstate(padapter, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE)
3036         {               
3037                 DBG_871X("set ssid, but buddy_intf is under scanning or linking\n");
3038                 
3039                 ret = -EINVAL;
3040                 
3041                 goto exit;
3042         }
3043 #endif
3044
3045         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
3046                  ("+rtw_wx_set_essid: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
3047
3048         rtw_ps_deny(padapter, PS_DENY_JOIN);
3049         if(_FAIL == rtw_pwr_wakeup(padapter))
3050         {               
3051                 ret = -1;
3052                 goto exit;
3053         }
3054
3055         if(!padapter->bup){
3056                 ret = -1;
3057                 goto exit;
3058         }
3059
3060 #if WIRELESS_EXT <= 20
3061         if ((wrqu->essid.length-1) > IW_ESSID_MAX_SIZE){
3062 #else
3063         if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
3064 #endif
3065                 ret= -E2BIG;
3066                 goto exit;
3067         }
3068         
3069         if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3070                 ret = -1;
3071                 goto exit;
3072         }               
3073         
3074         authmode = padapter->securitypriv.ndisauthtype;
3075         DBG_871X("=>%s\n",__FUNCTION__);
3076         if (wrqu->essid.flags && wrqu->essid.length)
3077         {
3078                 // Commented by Albert 20100519
3079                 // We got the codes in "set_info" function of iwconfig source code.
3080                 //      =========================================
3081                 //      wrq.u.essid.length = strlen(essid) + 1;
3082                 //      if(we_kernel_version > 20)
3083                 //              wrq.u.essid.length--;
3084                 //      =========================================
3085                 //      That means, if the WIRELESS_EXT less than or equal to 20, the correct ssid len should subtract 1.
3086 #if WIRELESS_EXT <= 20
3087                 len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
3088 #else
3089                 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
3090 #endif
3091
3092                 if( wrqu->essid.length != 33 )
3093                         DBG_871X("ssid=%s, len=%d\n", extra, wrqu->essid.length);
3094
3095                 _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
3096                 ndis_ssid.SsidLength = len;
3097                 _rtw_memcpy(ndis_ssid.Ssid, extra, len);                
3098                 src_ssid = ndis_ssid.Ssid;
3099                 
3100                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid=[%s]\n", src_ssid));
3101                 _enter_critical_bh(&queue->lock, &irqL);
3102                phead = get_list_head(queue);
3103               pmlmepriv->pscanned = get_next(phead);
3104
3105                 while (1)
3106                 {                       
3107                         if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == _TRUE)
3108                         {
3109 #if 0                   
3110                                 if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
3111                                 {
3112                                         rtw_set_802_11_ssid(padapter, &ndis_ssid);
3113
3114                                         goto exit;                    
3115                                 }
3116                                 else
3117                                 {
3118                                         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("rtw_wx_set_ssid(): scanned_queue is empty\n"));
3119                                         ret = -EINVAL;
3120                                         goto exit;
3121                                 }
3122 #endif                  
3123                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
3124                                          ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
3125
3126                                 break;
3127                         }
3128         
3129                         pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
3130
3131                         pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
3132
3133                         dst_ssid = pnetwork->network.Ssid.Ssid;
3134
3135                         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
3136                                  ("rtw_wx_set_essid: dst_ssid=%s\n",
3137                                   pnetwork->network.Ssid.Ssid));
3138
3139                         if ((_rtw_memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength) == _TRUE) &&
3140                                 (pnetwork->network.Ssid.SsidLength==ndis_ssid.SsidLength))
3141                         {
3142                                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
3143                                          ("rtw_wx_set_essid: find match, set infra mode\n"));
3144                                 
3145                                 if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
3146                                 {
3147                                         if(pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
3148                                                 continue;
3149                                 }       
3150                                         
3151                                 if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == _FALSE)
3152                                 {
3153                                         ret = -1;
3154                                         _exit_critical_bh(&queue->lock, &irqL);
3155                                         goto exit;
3156                                 }
3157
3158                                 break;                  
3159                         }
3160                 }
3161                 _exit_critical_bh(&queue->lock, &irqL);
3162                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
3163                          ("set ssid: set_802_11_auth. mode=%d\n", authmode));
3164                 rtw_set_802_11_authentication_mode(padapter, authmode);
3165                 //set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus);
3166                 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
3167                         ret = -1;
3168                         goto exit;
3169                 }       
3170         }                       
3171         
3172 exit:
3173
3174         rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
3175
3176         DBG_871X("<=%s, ret %d\n",__FUNCTION__, ret);
3177         
3178         #ifdef DBG_IOCTL
3179         DBG_871X("DBG_IOCTL %s:%d return %d\n",__FUNCTION__, __LINE__, ret);
3180         #endif
3181         
3182         _func_exit_;
3183         
3184         return ret;     
3185 }
3186
3187 static int rtw_wx_get_essid(struct net_device *dev, 
3188                               struct iw_request_info *a,
3189                               union iwreq_data *wrqu, char *extra)
3190 {
3191         u32 len,ret = 0;
3192         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3193         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
3194         WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
3195
3196         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_wx_get_essid\n"));
3197
3198         _func_enter_;
3199
3200         if ( (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
3201               (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
3202         {
3203                 len = pcur_bss->Ssid.SsidLength;
3204
3205                 wrqu->essid.length = len;
3206                         
3207                 _rtw_memcpy(extra, pcur_bss->Ssid.Ssid, len);
3208
3209                 wrqu->essid.flags = 1;
3210         }
3211         else
3212         {
3213                 ret = -1;
3214                 goto exit;
3215         }
3216
3217 exit:
3218
3219         _func_exit_;
3220         
3221         return ret;
3222         
3223 }
3224
3225 static int rtw_wx_set_rate(struct net_device *dev, 
3226                               struct iw_request_info *a,
3227                               union iwreq_data *wrqu, char *extra)
3228 {
3229         int     i, ret = 0;
3230         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3231         u8      datarates[NumRates];
3232         u32     target_rate = wrqu->bitrate.value;
3233         u32     fixed = wrqu->bitrate.fixed;
3234         u32     ratevalue = 0;
3235          u8 mpdatarate[NumRates]={11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
3236
3237 _func_enter_;
3238
3239         RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,(" rtw_wx_set_rate \n"));
3240         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("target_rate = %d, fixed = %d\n",target_rate,fixed));
3241         
3242         if(target_rate == -1){
3243                 ratevalue = 11;
3244                 goto set_rate;
3245         }
3246         target_rate = target_rate/100000;
3247
3248         switch(target_rate){
3249                 case 10:
3250                         ratevalue = 0;
3251                         break;
3252                 case 20:
3253                         ratevalue = 1;
3254                         break;
3255                 case 55:
3256                         ratevalue = 2;
3257                         break;
3258                 case 60:
3259                         ratevalue = 3;
3260                         break;
3261                 case 90:
3262                         ratevalue = 4;
3263                         break;
3264                 case 110:
3265                         ratevalue = 5;
3266                         break;
3267                 case 120:
3268                         ratevalue = 6;
3269                         break;
3270                 case 180:
3271                         ratevalue = 7;
3272                         break;
3273                 case 240:
3274                         ratevalue = 8;
3275                         break;
3276                 case 360:
3277                         ratevalue = 9;
3278                         break;
3279                 case 480:
3280                         ratevalue = 10;
3281                         break;
3282                 case 540:
3283                         ratevalue = 11;
3284                         break;
3285                 default:
3286                         ratevalue = 11;
3287                         break;
3288         }
3289
3290 set_rate:
3291
3292         for(i=0; i<NumRates; i++)
3293         {
3294                 if(ratevalue==mpdatarate[i])
3295                 {
3296                         datarates[i] = mpdatarate[i];
3297                         if(fixed == 0)
3298                                 break;
3299                 }
3300                 else{
3301                         datarates[i] = 0xff;
3302                 }
3303
3304                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("datarate_inx=%d\n",datarates[i]));
3305         }
3306
3307         if( rtw_setdatarate_cmd(padapter, datarates) !=_SUCCESS){
3308                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("rtw_wx_set_rate Fail!!!\n"));
3309                 ret = -1;
3310         }
3311
3312 _func_exit_;
3313
3314         return ret;
3315 }
3316
3317 static int rtw_wx_get_rate(struct net_device *dev, 
3318                              struct iw_request_info *info, 
3319                              union iwreq_data *wrqu, char *extra)
3320 {       
3321         u16 max_rate = 0;
3322
3323         max_rate = rtw_get_cur_max_rate((_adapter *)rtw_netdev_priv(dev));
3324
3325         if(max_rate == 0)
3326                 return -EPERM;
3327         
3328         wrqu->bitrate.fixed = 0;        /* no auto select */
3329         wrqu->bitrate.value = max_rate * 100000;
3330
3331         return 0;
3332 }
3333
3334 static int rtw_wx_set_rts(struct net_device *dev, 
3335                              struct iw_request_info *info, 
3336                              union iwreq_data *wrqu, char *extra)
3337 {
3338         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3339
3340         _func_enter_;
3341         
3342         if (wrqu->rts.disabled)
3343                 padapter->registrypriv.rts_thresh = 2347;
3344         else {
3345                 if (wrqu->rts.value < 0 ||
3346                     wrqu->rts.value > 2347)
3347                         return -EINVAL;
3348                 
3349                 padapter->registrypriv.rts_thresh = wrqu->rts.value;
3350         }
3351
3352         DBG_871X("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
3353         
3354         _func_exit_;
3355         
3356         return 0;
3357
3358 }
3359
3360 static int rtw_wx_get_rts(struct net_device *dev, 
3361                              struct iw_request_info *info, 
3362                              union iwreq_data *wrqu, char *extra)
3363 {
3364         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3365         
3366         _func_enter_;
3367
3368         DBG_871X("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);   
3369         
3370         wrqu->rts.value = padapter->registrypriv.rts_thresh;
3371         wrqu->rts.fixed = 0;    /* no auto select */
3372         //wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
3373         
3374         _func_exit_;
3375         
3376         return 0;
3377 }
3378
3379 static int rtw_wx_set_frag(struct net_device *dev, 
3380                              struct iw_request_info *info, 
3381                              union iwreq_data *wrqu, char *extra)
3382 {
3383         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3384
3385         _func_enter_;
3386         
3387         if (wrqu->frag.disabled)
3388                 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
3389         else {
3390                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
3391                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
3392                         return -EINVAL;
3393                 
3394                 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
3395         }
3396
3397         DBG_871X("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
3398         
3399         _func_exit_;
3400         
3401         return 0;
3402         
3403 }
3404
3405 static int rtw_wx_get_frag(struct net_device *dev, 
3406                              struct iw_request_info *info, 
3407                              union iwreq_data *wrqu, char *extra)
3408 {
3409         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3410         
3411         _func_enter_;
3412
3413         DBG_871X("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
3414         
3415         wrqu->frag.value = padapter->xmitpriv.frag_len;
3416         wrqu->frag.fixed = 0;   /* no auto select */
3417         //wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
3418         
3419         _func_exit_;
3420         
3421         return 0;
3422 }
3423
3424 static int rtw_wx_get_retry(struct net_device *dev, 
3425                              struct iw_request_info *info, 
3426                              union iwreq_data *wrqu, char *extra)
3427 {
3428         //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3429
3430         
3431         wrqu->retry.value = 7;
3432         wrqu->retry.fixed = 0;  /* no auto select */
3433         wrqu->retry.disabled = 1;
3434         
3435         return 0;
3436
3437 }       
3438
3439 #if 0
3440 #define IW_ENCODE_INDEX         0x00FF  /* Token index (if needed) */
3441 #define IW_ENCODE_FLAGS         0xFF00  /* Flags defined below */
3442 #define IW_ENCODE_MODE          0xF000  /* Modes defined below */
3443 #define IW_ENCODE_DISABLED      0x8000  /* Encoding disabled */
3444 #define IW_ENCODE_ENABLED       0x0000  /* Encoding enabled */
3445 #define IW_ENCODE_RESTRICTED    0x4000  /* Refuse non-encoded packets */
3446 #define IW_ENCODE_OPEN          0x2000  /* Accept non-encoded packets */
3447 #define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
3448 #define IW_ENCODE_TEMP          0x0400  /* Temporary key */
3449 /*
3450 iwconfig wlan0 key on -> flags = 0x6001 -> maybe it means auto
3451 iwconfig wlan0 key off -> flags = 0x8800
3452 iwconfig wlan0 key open -> flags = 0x2800
3453 iwconfig wlan0 key open 1234567890 -> flags = 0x2000
3454 iwconfig wlan0 key restricted -> flags = 0x4800
3455 iwconfig wlan0 key open [3] 1234567890 -> flags = 0x2003
3456 iwconfig wlan0 key restricted [2] 1234567890 -> flags = 0x4002
3457 iwconfig wlan0 key open [3] -> flags = 0x2803
3458 iwconfig wlan0 key restricted [2] -> flags = 0x4802
3459 */
3460 #endif
3461
3462 static int rtw_wx_set_enc(struct net_device *dev, 
3463                             struct iw_request_info *info, 
3464                             union iwreq_data *wrqu, char *keybuf)
3465 {       
3466         u32 key, ret = 0;
3467         u32 keyindex_provided;
3468         NDIS_802_11_WEP  wep;   
3469         NDIS_802_11_AUTHENTICATION_MODE authmode;
3470
3471         struct iw_point *erq = &(wrqu->encoding);
3472         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3473         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3474         DBG_871X("+rtw_wx_set_enc, flags=0x%x\n", erq->flags);
3475
3476         _rtw_memset(&wep, 0, sizeof(NDIS_802_11_WEP));
3477         
3478         key = erq->flags & IW_ENCODE_INDEX;
3479         
3480         _func_enter_;   
3481
3482         if (erq->flags & IW_ENCODE_DISABLED)
3483         {
3484                 DBG_871X("EncryptionDisabled\n");
3485                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
3486                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
3487                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
3488                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
3489                 authmode = Ndis802_11AuthModeOpen;
3490                 padapter->securitypriv.ndisauthtype=authmode;
3491                 
3492                 goto exit;
3493         }
3494
3495         if (key) {
3496                 if (key > WEP_KEYS)
3497                         return -EINVAL;
3498                 key--;
3499                 keyindex_provided = 1;
3500         } 
3501         else
3502         {
3503                 keyindex_provided = 0;
3504                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
3505                 DBG_871X("rtw_wx_set_enc, key=%d\n", key);
3506         }
3507         
3508         //set authentication mode       
3509         if(erq->flags & IW_ENCODE_OPEN)
3510         {
3511                 DBG_871X("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
3512                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;//Ndis802_11EncryptionDisabled;
3513
3514 #ifdef CONFIG_PLATFORM_MT53XX
3515                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3516 #else
3517                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open;
3518 #endif
3519
3520                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
3521                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
3522                 authmode = Ndis802_11AuthModeOpen;
3523                 padapter->securitypriv.ndisauthtype=authmode;
3524         }       
3525         else if(erq->flags & IW_ENCODE_RESTRICTED)
3526         {               
3527                 DBG_871X("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
3528                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
3529
3530 #ifdef CONFIG_PLATFORM_MT53XX
3531                 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3532 #else
3533                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Shared;
3534 #endif
3535
3536                 padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
3537                 padapter->securitypriv.dot118021XGrpPrivacy=_WEP40_;                    
3538                 authmode = Ndis802_11AuthModeShared;
3539                 padapter->securitypriv.ndisauthtype=authmode;
3540         }
3541         else
3542         {
3543                 DBG_871X("rtw_wx_set_enc():erq->flags=0x%x\n", erq->flags);
3544
3545                 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;//Ndis802_11EncryptionDisabled;
3546                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
3547                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
3548                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
3549                 authmode = Ndis802_11AuthModeOpen;
3550                 padapter->securitypriv.ndisauthtype=authmode;
3551         }
3552         
3553         wep.KeyIndex = key;
3554         if (erq->length > 0)
3555         {
3556                 wep.KeyLength = erq->length <= 5 ? 5 : 13;
3557
3558                 wep.Length = wep.KeyLength + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
3559         }
3560         else
3561         {
3562                 wep.KeyLength = 0 ;
3563                 
3564                 if(keyindex_provided == 1)// set key_id only, no given KeyMaterial(erq->length==0).
3565                 {
3566                         padapter->securitypriv.dot11PrivacyKeyIndex = key;
3567
3568                         DBG_871X("(keyindex_provided == 1), keyid=%d, key_len=%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
3569
3570                         switch(padapter->securitypriv.dot11DefKeylen[key])
3571                         {
3572                                 case 5:
3573                                         padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;                                     
3574                                         break;
3575                                 case 13:
3576                                         padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;                                    
3577                                         break;
3578                                 default:
3579                                         padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;                                        
3580                                         break;
3581                         }
3582                                 
3583                         goto exit;
3584                         
3585                 }
3586                 
3587         }
3588
3589         wep.KeyIndex |= 0x80000000;
3590
3591         _rtw_memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
3592         
3593         if (rtw_set_802_11_add_wep(padapter, &wep) == _FALSE) {
3594                 if(rf_on == pwrpriv->rf_pwrstate )
3595                         ret = -EOPNOTSUPP;
3596                 goto exit;
3597         }       
3598
3599 exit:
3600         
3601         _func_exit_;
3602         
3603         return ret;
3604         
3605 }
3606
3607 static int rtw_wx_get_enc(struct net_device *dev, 
3608                             struct iw_request_info *info, 
3609                             union iwreq_data *wrqu, char *keybuf)
3610 {
3611         uint key, ret =0;
3612         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3613         struct iw_point *erq = &(wrqu->encoding);
3614         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
3615
3616         _func_enter_;
3617         
3618         if(check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)
3619         {
3620                  if(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE)
3621                  {
3622                 erq->length = 0;
3623                 erq->flags |= IW_ENCODE_DISABLED;
3624                 return 0;
3625         }       
3626         }       
3627
3628         
3629         key = erq->flags & IW_ENCODE_INDEX;
3630
3631         if (key) {
3632                 if (key > WEP_KEYS)
3633                         return -EINVAL;
3634                 key--;
3635         } else
3636         {
3637                 key = padapter->securitypriv.dot11PrivacyKeyIndex;
3638         }       
3639
3640         erq->flags = key + 1;
3641
3642         //if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
3643         //{
3644         //      erq->flags |= IW_ENCODE_OPEN;
3645         //}       
3646         
3647         switch(padapter->securitypriv.ndisencryptstatus)
3648         {
3649                 case Ndis802_11EncryptionNotSupported:
3650                 case Ndis802_11EncryptionDisabled:
3651
3652                 erq->length = 0;
3653                 erq->flags |= IW_ENCODE_DISABLED;
3654         
3655                 break;
3656                 
3657                 case Ndis802_11Encryption1Enabled:                                      
3658                 
3659                 erq->length = padapter->securitypriv.dot11DefKeylen[key];               
3660
3661                 if(erq->length)
3662                 {
3663                         _rtw_memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
3664                 
3665                 erq->flags |= IW_ENCODE_ENABLED;
3666
3667                         if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
3668                         {
3669                                 erq->flags |= IW_ENCODE_OPEN;
3670                         }
3671                         else if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
3672                         {
3673                 erq->flags |= IW_ENCODE_RESTRICTED;
3674                         }       
3675                 }       
3676                 else
3677                 {
3678                         erq->length = 0;
3679                         erq->flags |= IW_ENCODE_DISABLED;
3680                 }
3681
3682                 break;
3683
3684                 case Ndis802_11Encryption2Enabled:
3685                 case Ndis802_11Encryption3Enabled:
3686
3687                 erq->length = 16;
3688                 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
3689
3690                 break;
3691         
3692                 default:
3693                 erq->length = 0;
3694                 erq->flags |= IW_ENCODE_DISABLED;
3695
3696                 break;
3697                 
3698         }
3699         
3700         _func_exit_;
3701         
3702         return ret;
3703         
3704 }                                    
3705
3706 static int rtw_wx_get_power(struct net_device *dev, 
3707                              struct iw_request_info *info, 
3708                              union iwreq_data *wrqu, char *extra)
3709 {
3710         //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3711         
3712         wrqu->power.value = 0;
3713         wrqu->power.fixed = 0;  /* no auto select */
3714         wrqu->power.disabled = 1;
3715         
3716         return 0;
3717
3718 }
3719
3720 static int rtw_wx_set_gen_ie(struct net_device *dev, 
3721                              struct iw_request_info *info, 
3722                              union iwreq_data *wrqu, char *extra)
3723 {
3724         int ret;
3725         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3726         
3727        ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
3728            
3729         return ret;
3730 }       
3731
3732 static int rtw_wx_set_auth(struct net_device *dev, 
3733                              struct iw_request_info *info, 
3734                              union iwreq_data *wrqu, char *extra)
3735 {
3736         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3737         struct iw_param *param = (struct iw_param*)&(wrqu->param);
3738         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
3739         struct security_priv *psecuritypriv = &padapter->securitypriv;
3740         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
3741         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
3742         u32 value = param->value;
3743         int ret = 0;
3744         
3745         switch (param->flags & IW_AUTH_INDEX) {
3746
3747         case IW_AUTH_WPA_VERSION:
3748 #ifdef CONFIG_WAPI_SUPPORT
3749 #ifndef CONFIG_IOCTL_CFG80211
3750                  padapter->wapiInfo.bWapiEnable = false;
3751                  if(value == IW_AUTH_WAPI_VERSION_1)
3752                  {
3753                         padapter->wapiInfo.bWapiEnable = true;
3754                         psecuritypriv->dot11PrivacyAlgrthm = _SMS4_;
3755                         psecuritypriv->dot118021XGrpPrivacy = _SMS4_;
3756                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
3757                         pmlmeinfo->auth_algo = psecuritypriv->dot11AuthAlgrthm;
3758                         padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
3759                         padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
3760                 }
3761 #endif
3762 #endif
3763                 break;
3764         case IW_AUTH_CIPHER_PAIRWISE:
3765                 
3766                 break;
3767         case IW_AUTH_CIPHER_GROUP:
3768                 
3769                 break;
3770         case IW_AUTH_KEY_MGMT:
3771 #ifdef CONFIG_WAPI_SUPPORT
3772 #ifndef CONFIG_IOCTL_CFG80211
3773                 DBG_871X("rtw_wx_set_auth: IW_AUTH_KEY_MGMT case \n");
3774                 if(value == IW_AUTH_KEY_MGMT_WAPI_PSK)
3775                         padapter->wapiInfo.bWapiPSK = true;
3776                 else
3777                         padapter->wapiInfo.bWapiPSK = false;
3778                 DBG_871X("rtw_wx_set_auth: IW_AUTH_KEY_MGMT bwapipsk %d \n",padapter->wapiInfo.bWapiPSK);
3779 #endif
3780 #endif
3781                 /*
3782                  *  ??? does not use these parameters
3783                  */
3784                 break;
3785
3786         case IW_AUTH_TKIP_COUNTERMEASURES:
3787         {
3788             if ( param->value )
3789             {  // wpa_supplicant is enabling the tkip countermeasure.
3790                padapter->securitypriv.btkip_countermeasure = _TRUE; 
3791             }
3792             else
3793             {  // wpa_supplicant is disabling the tkip countermeasure.
3794                padapter->securitypriv.btkip_countermeasure = _FALSE; 
3795             }
3796                 break;
3797         }
3798         case IW_AUTH_DROP_UNENCRYPTED:
3799                 {
3800                         /* HACK:
3801                          *
3802                          * wpa_supplicant calls set_wpa_enabled when the driver
3803                          * is loaded and unloaded, regardless of if WPA is being
3804                          * used.  No other calls are made which can be used to
3805                          * determine if encryption will be used or not prior to
3806                          * association being expected.  If encryption is not being
3807                          * used, drop_unencrypted is set to false, else true -- we
3808                          * can use this to determine if the CAP_PRIVACY_ON bit should
3809                          * be set.
3810                          */
3811
3812                         if(padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
3813                         {
3814                                 break;//it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, 
3815                                                 // then it needn't reset it;
3816                         }
3817                         
3818                         if(param->value){
3819                                 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
3820                                 padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
3821                                 padapter->securitypriv.dot118021XGrpPrivacy=_NO_PRIVACY_;
3822                                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_Open; //open system
3823                                 padapter->securitypriv.ndisauthtype=Ndis802_11AuthModeOpen;
3824                         }
3825                         
3826                         break;
3827                 }
3828
3829         case IW_AUTH_80211_AUTH_ALG:
3830
3831                 #if defined(CONFIG_ANDROID) || 1
3832                 /*
3833                  *  It's the starting point of a link layer connection using wpa_supplicant
3834                 */
3835                 if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3836                         LeaveAllPowerSaveMode(padapter);
3837                         rtw_disassoc_cmd(padapter, 500, _FALSE);
3838                         DBG_871X("%s...call rtw_indicate_disconnect\n ",__FUNCTION__);
3839                         rtw_indicate_disconnect(padapter);
3840                         rtw_free_assoc_resources(padapter, 1);
3841                 }
3842                 #endif
3843
3844
3845                 ret = wpa_set_auth_algs(dev, (u32)param->value);                
3846         
3847                 break;
3848
3849         case IW_AUTH_WPA_ENABLED:
3850
3851                 //if(param->value)
3852                 //      padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; //802.1x
3853                 //else
3854                 //      padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;//open system
3855                 
3856                 //_disassociate(priv);
3857                 
3858                 break;
3859
3860         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3861                 //ieee->ieee802_1x = param->value;
3862                 break;
3863
3864         case IW_AUTH_PRIVACY_INVOKED:
3865                 //ieee->privacy_invoked = param->value;
3866                 break;
3867
3868 #ifdef CONFIG_WAPI_SUPPORT
3869 #ifndef CONFIG_IOCTL_CFG80211
3870         case IW_AUTH_WAPI_ENABLED:
3871                 break;
3872 #endif
3873 #endif
3874
3875         default:
3876                 return -EOPNOTSUPP;
3877                 
3878         }
3879         
3880         return ret;
3881         
3882 }
3883
3884 static int rtw_wx_set_enc_ext(struct net_device *dev, 
3885                              struct iw_request_info *info, 
3886                              union iwreq_data *wrqu, char *extra)
3887 {
3888         char *alg_name;
3889         u32 param_len;
3890         struct ieee_param *param = NULL;
3891         struct iw_point *pencoding = &wrqu->encoding;
3892         struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
3893         int ret=0;
3894
3895         param_len = sizeof(struct ieee_param) + pext->key_len;
3896         param = (struct ieee_param *)rtw_malloc(param_len);
3897         if (param == NULL)
3898                 return -1;
3899         
3900         _rtw_memset(param, 0, param_len);
3901
3902         param->cmd = IEEE_CMD_SET_ENCRYPTION;
3903         _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
3904
3905
3906         switch (pext->alg) {
3907         case IW_ENCODE_ALG_NONE:
3908                 //todo: remove key 
3909                 //remove = 1;   
3910                 alg_name = "none";
3911                 break;
3912         case IW_ENCODE_ALG_WEP:
3913                 alg_name = "WEP";
3914                 break;
3915         case IW_ENCODE_ALG_TKIP:
3916                 alg_name = "TKIP";
3917                 break;
3918         case IW_ENCODE_ALG_CCMP:
3919                 alg_name = "CCMP";
3920                 break;
3921 #ifdef CONFIG_IEEE80211W
3922         case IW_ENCODE_ALG_AES_CMAC:
3923                 alg_name = "BIP";
3924                 break;
3925 #endif //CONFIG_IEEE80211W
3926 #ifdef CONFIG_WAPI_SUPPORT
3927 #ifndef CONFIG_IOCTL_CFG80211
3928         case IW_ENCODE_ALG_SM4:
3929                 alg_name= "SMS4";
3930                 _rtw_memcpy(param->sta_addr, pext->addr.sa_data, ETH_ALEN);
3931                 DBG_871X("rtw_wx_set_enc_ext: SMS4 case \n");
3932                 break;
3933 #endif
3934 #endif
3935         default:
3936                 ret = -1;
3937                 goto exit;
3938         }
3939
3940         strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
3941
3942         if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3943         {
3944                 param->u.crypt.set_tx = 1;
3945         }
3946
3947         /* cliW: WEP does not have group key
3948          * just not checking GROUP key setting 
3949          */
3950         if ((pext->alg != IW_ENCODE_ALG_WEP) &&
3951                 ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
3952 #ifdef CONFIG_IEEE80211W
3953                 || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC)
3954 #endif //CONFIG_IEEE80211W
3955         ))
3956         {
3957                 param->u.crypt.set_tx = 0;
3958         }
3959
3960         param->u.crypt.idx = (pencoding->flags&0x00FF) -1 ;
3961
3962         if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
3963         {
3964 #ifdef CONFIG_WAPI_SUPPORT
3965 #ifndef CONFIG_IOCTL_CFG80211
3966                 if(pext->alg == IW_ENCODE_ALG_SM4)
3967                         _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 16);
3968                 else
3969 #endif //CONFIG_IOCTL_CFG80211
3970 #endif //CONFIG_WAPI_SUPPORT
3971                 _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 8);
3972         }
3973
3974         if(pext->key_len)
3975         {
3976                 param->u.crypt.key_len = pext->key_len;
3977                 //_rtw_memcpy(param + 1, pext + 1, pext->key_len);
3978                 _rtw_memcpy(param->u.crypt.key, pext + 1, pext->key_len);
3979         }
3980
3981         if (pencoding->flags & IW_ENCODE_DISABLED)
3982         {
3983                 //todo: remove key 
3984                 //remove = 1;
3985         }
3986
3987         ret =  wpa_set_encryption(dev, param, param_len);
3988
3989 exit:
3990         if(param)
3991         {
3992                 rtw_mfree((u8*)param, param_len);
3993         }
3994
3995         return ret;
3996 }
3997
3998
3999 static int rtw_wx_get_nick(struct net_device *dev, 
4000                              struct iw_request_info *info, 
4001                              union iwreq_data *wrqu, char *extra)
4002 {       
4003         //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4004          //struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4005          //struct security_priv *psecuritypriv = &padapter->securitypriv;
4006
4007         if(extra)
4008         {
4009                 wrqu->data.length = 14;
4010                 wrqu->data.flags = 1;
4011                 _rtw_memcpy(extra, "<WIFI@REALTEK>", 14);
4012         }
4013
4014         //rtw_signal_process(pid, SIGUSR1); //for test
4015
4016         //dump debug info here  
4017 /*
4018         u32 dot11AuthAlgrthm;           // 802.11 auth, could be open, shared, and 8021x
4019         u32 dot11PrivacyAlgrthm;        // This specify the privacy for shared auth. algorithm.
4020         u32 dot118021XGrpPrivacy;       // This specify the privacy algthm. used for Grp key 
4021         u32 ndisauthtype;
4022         u32 ndisencryptstatus;
4023 */
4024
4025         //DBG_871X("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", 
4026         //              psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
4027         //              psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
4028         
4029         //DBG_871X("enc_alg=0x%x\n", psecuritypriv->dot11PrivacyAlgrthm);
4030         //DBG_871X("auth_type=0x%x\n", psecuritypriv->ndisauthtype);
4031         //DBG_871X("enc_type=0x%x\n", psecuritypriv->ndisencryptstatus);
4032
4033 #if 0
4034         DBG_871X("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
4035         DBG_871X("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
4036         DBG_871X("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
4037         DBG_871X("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
4038         DBG_871X("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
4039         
4040         DBG_871X("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
4041
4042
4043         DBG_871X("\n");
4044
4045         DBG_871X("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
4046         DBG_871X("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
4047
4048         DBG_871X("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
4049         
4050         DBG_871X("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
4051         
4052         DBG_871X("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
4053         DBG_871X("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
4054         
4055         DBG_871X("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
4056         DBG_871X("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
4057         DBG_871X("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
4058         DBG_871X("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
4059 #endif
4060         
4061         return 0;
4062
4063 }
4064
4065 static int rtw_wx_read32(struct net_device *dev,
4066                             struct iw_request_info *info,
4067                             union iwreq_data *wrqu, char *extra)
4068 {
4069         PADAPTER padapter;
4070         struct iw_point *p;
4071         u16 len;
4072         u32 addr;
4073         u32 data32;
4074         u32 bytes;
4075         u8 *ptmp;
4076         int ret;
4077
4078
4079         ret = 0;
4080         padapter = (PADAPTER)rtw_netdev_priv(dev);
4081         p = &wrqu->data;
4082         len = p->length;
4083         if (0 == len)
4084                 return -EINVAL;
4085
4086         ptmp = (u8*)rtw_malloc(len);
4087         if (NULL == ptmp)
4088                 return -ENOMEM;
4089
4090         if (copy_from_user(ptmp, p->pointer, len)) {
4091                 ret = -EFAULT;
4092                 goto exit;
4093         }
4094
4095         bytes = 0;
4096         addr = 0;
4097         sscanf(ptmp, "%d,%x", &bytes, &addr);
4098
4099         switch (bytes) {
4100                 case 1:
4101                         data32 = rtw_read8(padapter, addr);
4102                         sprintf(extra, "0x%02X", data32);
4103                         break;
4104                 case 2:
4105                         data32 = rtw_read16(padapter, addr);
4106                         sprintf(extra, "0x%04X", data32);
4107                         break;
4108                 case 4:
4109                         data32 = rtw_read32(padapter, addr);
4110                         sprintf(extra, "0x%08X", data32);
4111                         break;
4112                 default:
4113                         DBG_871X(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
4114                         ret = -EINVAL;
4115                         goto exit;
4116         }
4117         DBG_871X(KERN_INFO "%s: addr=0x%08X data=%s\n", __func__, addr, extra);
4118
4119 exit:
4120         rtw_mfree(ptmp, len);
4121
4122         return 0;
4123 }
4124
4125 static int rtw_wx_write32(struct net_device *dev,
4126                             struct iw_request_info *info,
4127                             union iwreq_data *wrqu, char *extra)
4128 {
4129         PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
4130
4131         u32 addr;
4132         u32 data32;
4133         u32 bytes;
4134
4135
4136         bytes = 0;
4137         addr = 0;
4138         data32 = 0;
4139         sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
4140
4141         switch (bytes) {
4142                 case 1:
4143                         rtw_write8(padapter, addr, (u8)data32);
4144                         DBG_871X(KERN_INFO "%s: addr=0x%08X data=0x%02X\n", __func__, addr, (u8)data32);
4145                         break;
4146                 case 2:
4147                         rtw_write16(padapter, addr, (u16)data32);
4148                         DBG_871X(KERN_INFO "%s: addr=0x%08X data=0x%04X\n", __func__, addr, (u16)data32);
4149                         break;
4150                 case 4:
4151                         rtw_write32(padapter, addr, data32);
4152                         DBG_871X(KERN_INFO "%s: addr=0x%08X data=0x%08X\n", __func__, addr, data32);
4153                         break;
4154                 default:
4155                         DBG_871X(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
4156                         return -EINVAL;
4157         }
4158
4159         return 0;
4160 }
4161
4162 static int rtw_wx_read_rf(struct net_device *dev,
4163                             struct iw_request_info *info,
4164                             union iwreq_data *wrqu, char *extra)
4165 {
4166         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4167         u32 path, addr, data32;
4168
4169
4170         path = *(u32*)extra;
4171         addr = *((u32*)extra + 1);
4172         data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
4173 //      DBG_871X("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32);
4174         /*
4175          * IMPORTANT!!
4176          * Only when wireless private ioctl is at odd order,
4177          * "extra" would be copied to user space.
4178          */
4179         sprintf(extra, "0x%05x", data32);
4180
4181         return 0;
4182 }
4183
4184 static int rtw_wx_write_rf(struct net_device *dev,
4185                             struct iw_request_info *info,
4186                             union iwreq_data *wrqu, char *extra)
4187 {
4188         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4189         u32 path, addr, data32;
4190
4191
4192         path = *(u32*)extra;
4193         addr = *((u32*)extra + 1);
4194         data32 = *((u32*)extra + 2);
4195 //      DBG_871X("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32);
4196         rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
4197
4198         return 0;
4199 }
4200
4201 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
4202                  union iwreq_data *wrqu, char *b)
4203 {
4204         return -1;
4205 }
4206
4207 static int dummy(struct net_device *dev, struct iw_request_info *a,
4208                  union iwreq_data *wrqu, char *b)
4209 {
4210         //_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);        
4211         //struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4212
4213         //DBG_871X("cmd_code=%x, fwstate=0x%x\n", a->cmd, get_fwstate(pmlmepriv));
4214         
4215         return -1;
4216         
4217 }
4218
4219 static int rtw_wx_set_channel_plan(struct net_device *dev,
4220                                struct iw_request_info *info,
4221                                union iwreq_data *wrqu, char *extra)
4222 {
4223         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4224         struct registry_priv *pregistrypriv = &padapter->registrypriv;
4225         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4226         extern int rtw_channel_plan;
4227         u8 channel_plan_req = (u8) (*((int *)wrqu));
4228
4229         #if 0
4230         rtw_channel_plan = (int)wrqu->data.pointer;
4231         pregistrypriv->channel_plan = rtw_channel_plan;
4232         pmlmepriv->ChannelPlan = pregistrypriv->channel_plan;
4233         #endif
4234
4235         if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1, 1)) {
4236                 DBG_871X("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
4237         } else 
4238                 return -EPERM;
4239
4240         return 0;
4241 }
4242
4243 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
4244                 struct iw_request_info *a,
4245                 union iwreq_data *wrqu, char *b)
4246 {
4247 #ifdef CONFIG_PLATFORM_MT53XX
4248         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4249         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4250
4251         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_,
4252                  ("WLAN IOCTL: cmd_code=%x, fwstate=0x%x\n",
4253                   a->cmd, get_fwstate(pmlmepriv)));
4254 #endif
4255         return 0;
4256 }
4257
4258 static int rtw_wx_get_sensitivity(struct net_device *dev,
4259                                 struct iw_request_info *info,
4260                                 union iwreq_data *wrqu, char *buf)
4261 {
4262 #ifdef CONFIG_PLATFORM_MT53XX
4263         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4264
4265         //      Modified by Albert 20110914
4266         //      This is in dbm format for MTK platform.
4267         wrqu->qual.level = padapter->recvpriv.rssi;
4268         DBG_871X(" level = %u\n",  wrqu->qual.level );
4269 #endif
4270         return 0;
4271 }
4272
4273 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
4274                                 struct iw_request_info *info,
4275                                 union iwreq_data *wrqu, char *extra)
4276 {
4277 #ifdef CONFIG_PLATFORM_MT53XX
4278         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4279
4280         return rtw_set_wpa_ie(padapter, wrqu->data.pointer, wrqu->data.length);
4281 #else
4282         return 0;
4283 #endif
4284 }
4285
4286 /*
4287 typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
4288                           union iwreq_data *wrqu, char *extra);
4289 */
4290 /*
4291  *      For all data larger than 16 octets, we need to use a
4292  *      pointer to memory allocated in user space.
4293  */
4294 static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
4295                                                 union iwreq_data *wrqu, char *extra)
4296 {
4297
4298  #if 0
4299 struct  iw_point
4300 {
4301   void __user   *pointer;       /* Pointer to the data  (in user space) */
4302   __u16         length;         /* number of fields or size in bytes */
4303   __u16         flags;          /* Optional params */
4304 };
4305  #endif
4306
4307 #ifdef CONFIG_DRVEXT_MODULE
4308         u8 res;
4309         struct drvext_handler *phandler;        
4310         struct drvext_oidparam *poidparam;              
4311         int ret;
4312         u16 len;
4313         u8 *pparmbuf, bset;
4314         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4315         struct iw_point *p = &wrqu->data;
4316
4317         if( (!p->length) || (!p->pointer)){
4318                 ret = -EINVAL;
4319                 goto _rtw_drvext_hdl_exit;
4320         }
4321         
4322         
4323         bset = (u8)(p->flags&0xFFFF);
4324         len = p->length;
4325         pparmbuf = (u8*)rtw_malloc(len);
4326         if (pparmbuf == NULL){
4327                 ret = -ENOMEM;
4328                 goto _rtw_drvext_hdl_exit;
4329         }
4330         
4331         if(bset)//set info
4332         {
4333                 if (copy_from_user(pparmbuf, p->pointer,len)) {
4334                         rtw_mfree(pparmbuf, len);
4335                         ret = -EFAULT;
4336                         goto _rtw_drvext_hdl_exit;
4337                 }               
4338         }
4339         else//query info
4340         {
4341         
4342         }
4343
4344         
4345         //
4346         poidparam = (struct drvext_oidparam *)pparmbuf; 
4347         
4348         RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("drvext set oid subcode [%d], len[%d], InformationBufferLength[%d]\r\n",
4349                                                  poidparam->subcode, poidparam->len, len));
4350
4351
4352         //check subcode 
4353         if ( poidparam->subcode >= MAX_DRVEXT_HANDLERS)
4354         {
4355                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext handlers\r\n"));             
4356                 ret = -EINVAL;
4357                 goto _rtw_drvext_hdl_exit;
4358         }
4359
4360
4361         if ( poidparam->subcode >= MAX_DRVEXT_OID_SUBCODES)
4362         {
4363                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext subcodes\r\n"));             
4364                 ret = -EINVAL;
4365                 goto _rtw_drvext_hdl_exit;
4366         }
4367
4368
4369         phandler = drvextoidhandlers + poidparam->subcode;
4370
4371         if (poidparam->len != phandler->parmsize)
4372         {
4373                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_err_,("no matching drvext param size %d vs %d\r\n",                    
4374                                                 poidparam->len , phandler->parmsize));          
4375                 ret = -EINVAL;          
4376                 goto _rtw_drvext_hdl_exit;
4377         }
4378
4379
4380         res = phandler->handler(&padapter->drvextpriv, bset, poidparam->data);
4381
4382         if(res==0)
4383         {
4384                 ret = 0;
4385                         
4386                 if (bset == 0x00) {//query info
4387                         //_rtw_memcpy(p->pointer, pparmbuf, len);
4388                         if (copy_to_user(p->pointer, pparmbuf, len))
4389                                 ret = -EFAULT;
4390                 }               
4391         }               
4392         else
4393                 ret = -EFAULT;
4394
4395         
4396 _rtw_drvext_hdl_exit:   
4397         
4398         return ret;     
4399         
4400 #endif
4401
4402         return 0;
4403
4404 }
4405
4406 static void rtw_dbg_mode_hdl(_adapter *padapter, u32 id, u8 *pdata, u32 len)
4407 {
4408         pRW_Reg         RegRWStruct;
4409         struct rf_reg_param *prfreg;
4410         u8 path;
4411         u8 offset;
4412         u32 value;
4413
4414         DBG_871X("%s\n", __FUNCTION__);
4415
4416         switch(id)
4417         {
4418                 case GEN_MP_IOCTL_SUBCODE(MP_START):
4419                         DBG_871X("871x_driver is only for normal mode, can't enter mp mode\n");
4420                         break;
4421                 case GEN_MP_IOCTL_SUBCODE(READ_REG):
4422                         RegRWStruct = (pRW_Reg)pdata;
4423                         switch (RegRWStruct->width)
4424                         {
4425                                 case 1:
4426                                         RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
4427                                         break;
4428                                 case 2:
4429                                         RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
4430                                         break;
4431                                 case 4:
4432                                         RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
4433                                         break;
4434                                 default:
4435                                         break;
4436                         }
4437                 
4438                         break;
4439                 case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
4440                         RegRWStruct = (pRW_Reg)pdata;
4441                         switch (RegRWStruct->width)
4442                         {
4443                                 case 1:
4444                                         rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
4445                                         break;
4446                                 case 2:
4447                                         rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
4448                                         break;
4449                                 case 4:
4450                                         rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
4451                                         break;
4452                                 default:                                        
4453                                 break;
4454                         }
4455                                 
4456                         break;
4457                 case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
4458
4459                         prfreg = (struct rf_reg_param *)pdata;
4460
4461                         path = (u8)prfreg->path;                
4462                         offset = (u8)prfreg->offset;    
4463
4464                         value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
4465
4466                         prfreg->value = value;
4467
4468                         break;                  
4469                 case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
4470
4471                         prfreg = (struct rf_reg_param *)pdata;
4472
4473                         path = (u8)prfreg->path;
4474                         offset = (u8)prfreg->offset;    
4475                         value = prfreg->value;
4476
4477                         rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
4478                         
4479                         break;                  
4480                 case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
4481                         DBG_871X("==> trigger gpio 0\n");
4482                         rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, 0);
4483                         break;  
4484 #ifdef CONFIG_BT_COEXIST
4485                 case GEN_MP_IOCTL_SUBCODE(SET_DM_BT):                   
4486                         DBG_871X("==> set dm_bt_coexist:%x\n",*(u8 *)pdata);
4487                         rtw_hal_set_hwreg(padapter, HW_VAR_BT_SET_COEXIST, pdata);
4488                         break;
4489                 case GEN_MP_IOCTL_SUBCODE(DEL_BA):
4490                         DBG_871X("==> delete ba:%x\n",*(u8 *)pdata);
4491                         rtw_hal_set_hwreg(padapter, HW_VAR_BT_ISSUE_DELBA, pdata);
4492                         break;
4493 #endif
4494 #ifdef DBG_CONFIG_ERROR_DETECT
4495                 case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):                                                     
4496                         *pdata = rtw_hal_sreset_get_wifi_status(padapter);                   
4497                         break;
4498 #endif
4499         
4500                 default:
4501                         break;
4502         }
4503         
4504 }
4505
4506 static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
4507                                                 union iwreq_data *wrqu, char *extra)
4508 {
4509         int ret = 0;
4510         u32 BytesRead, BytesWritten, BytesNeeded;
4511         struct oid_par_priv     oid_par;
4512         struct mp_ioctl_handler *phandler;
4513         struct mp_ioctl_param   *poidparam;
4514         uint status=0;
4515         u16 len;
4516         u8 *pparmbuf = NULL, bset;
4517         PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
4518         struct iw_point *p = &wrqu->data;
4519
4520         //DBG_871X("+rtw_mp_ioctl_hdl\n");
4521
4522         //mutex_lock(&ioctl_mutex);
4523
4524         if ((!p->length) || (!p->pointer)) {
4525                 ret = -EINVAL;
4526                 goto _rtw_mp_ioctl_hdl_exit;
4527         }
4528
4529         pparmbuf = NULL;
4530         bset = (u8)(p->flags & 0xFFFF);
4531         len = p->length;
4532         pparmbuf = (u8*)rtw_malloc(len);
4533         if (pparmbuf == NULL){
4534                 ret = -ENOMEM;
4535                 goto _rtw_mp_ioctl_hdl_exit;
4536         }
4537
4538         if (copy_from_user(pparmbuf, p->pointer, len)) {
4539                 ret = -EFAULT;
4540                 goto _rtw_mp_ioctl_hdl_exit;
4541         }
4542
4543         poidparam = (struct mp_ioctl_param *)pparmbuf;
4544         RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
4545                  ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
4546                   poidparam->subcode, poidparam->len, len));
4547
4548         if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
4549                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
4550                 ret = -EINVAL;
4551                 goto _rtw_mp_ioctl_hdl_exit;
4552         }
4553
4554         //DBG_871X("%s: %d\n", __func__, poidparam->subcode);
4555 #ifdef CONFIG_MP_INCLUDED 
4556 if (padapter->registrypriv.mp_mode == 1)
4557 {       
4558         phandler = mp_ioctl_hdl + poidparam->subcode;
4559
4560         if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize))
4561         {
4562                 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
4563                          ("no matching drvext param size %d vs %d\r\n",
4564                           poidparam->len, phandler->paramsize));
4565                 ret = -EINVAL;
4566                 goto _rtw_mp_ioctl_hdl_exit;
4567         }
4568
4569         if (phandler->handler)
4570         {
4571                 oid_par.adapter_context = padapter;
4572                 oid_par.oid = phandler->oid;
4573                 oid_par.information_buf = poidparam->data;
4574                 oid_par.information_buf_len = poidparam->len;
4575                 oid_par.dbg = 0;
4576
4577                 BytesWritten = 0;
4578                 BytesNeeded = 0;
4579
4580                 if (bset) {
4581                         oid_par.bytes_rw = &BytesRead;
4582                         oid_par.bytes_needed = &BytesNeeded;
4583                         oid_par.type_of_oid = SET_OID;
4584                 } else {
4585                         oid_par.bytes_rw = &BytesWritten;
4586                         oid_par.bytes_needed = &BytesNeeded;
4587                         oid_par.type_of_oid = QUERY_OID;
4588                 }
4589
4590                 status = phandler->handler(&oid_par);
4591
4592                 //todo:check status, BytesNeeded, etc.
4593         }
4594         else {
4595                 DBG_871X("rtw_mp_ioctl_hdl(): err!, subcode=%d, oid=%d, handler=%p\n", 
4596                         poidparam->subcode, phandler->oid, phandler->handler);
4597                 ret = -EFAULT;
4598                 goto _rtw_mp_ioctl_hdl_exit;
4599         }
4600 }
4601 else
4602 #endif
4603 {
4604         rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
4605 }
4606
4607         if (bset == 0x00) {//query info
4608                 if (copy_to_user(p->pointer, pparmbuf, len))
4609                         ret = -EFAULT;
4610         }
4611
4612         if (status) {
4613                 ret = -EFAULT;
4614                 goto _rtw_mp_ioctl_hdl_exit;
4615         }
4616
4617 _rtw_mp_ioctl_hdl_exit:
4618
4619         if (pparmbuf)
4620                 rtw_mfree(pparmbuf, len);
4621
4622         //mutex_unlock(&ioctl_mutex);
4623
4624         return ret;
4625 }
4626
4627 static int rtw_get_ap_info(struct net_device *dev,
4628                                struct iw_request_info *info,
4629                                union iwreq_data *wrqu, char *extra)
4630 {
4631         int bssid_match, ret = 0;
4632         u32 cnt=0, wpa_ielen;
4633         _irqL   irqL;
4634         _list   *plist, *phead;
4635         unsigned char *pbuf;
4636         u8 bssid[ETH_ALEN];
4637         char data[32];
4638         struct wlan_network *pnetwork = NULL;
4639         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
4640         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    
4641         _queue *queue = &(pmlmepriv->scanned_queue);
4642         struct iw_point *pdata = &wrqu->data;   
4643
4644         DBG_871X("+rtw_get_aplist_info\n");
4645
4646         if((padapter->bDriverStopped) || (pdata==NULL))
4647         {                
4648                 ret= -EINVAL;
4649                 goto exit;
4650         }               
4651   
4652         while((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == _TRUE)
4653         {       
4654                 rtw_msleep_os(30);
4655                 cnt++;
4656                 if(cnt > 100)
4657                         break;
4658         }
4659         
4660
4661         //pdata->length = 0;//? 
4662         pdata->flags = 0;
4663         if(pdata->length>=32)
4664         {
4665                 if(copy_from_user(data, pdata->pointer, 32))
4666                 {
4667                         ret= -EINVAL;
4668                         goto exit;
4669                 }
4670         }       
4671         else
4672         {
4673                 ret= -EINVAL;
4674                 goto exit;
4675         }       
4676
4677         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4678         
4679         phead = get_list_head(queue);
4680         plist = get_next(phead);
4681        
4682         while(1)
4683         {
4684                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
4685                         break;
4686
4687
4688                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4689
4690                 //if(hwaddr_aton_i(pdata->pointer, bssid)) 
4691                 if(hwaddr_aton_i(data, bssid)) 
4692                 {                       
4693                         DBG_871X("Invalid BSSID '%s'.\n", (u8*)data);
4694                         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4695                         return -EINVAL;
4696                 }               
4697                 
4698         
4699                 if(_rtw_memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) == _TRUE)//BSSID match, then check if supporting wpa/wpa2
4700                 {
4701                         DBG_871X("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
4702                         
4703                         pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);                           
4704                         if(pbuf && (wpa_ielen>0))
4705                         {
4706                                 pdata->flags = 1;
4707                                 break;
4708                         }
4709
4710                         pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
4711                         if(pbuf && (wpa_ielen>0))
4712                         {
4713                                 pdata->flags = 2;
4714                                 break;
4715                         }
4716                         
4717                 }
4718
4719                 plist = get_next(plist);                
4720         
4721         }        
4722
4723         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4724
4725         if(pdata->length>=34)
4726         {
4727                 if(copy_to_user((u8*)pdata->pointer+32, (u8*)&pdata->flags, 1))
4728                 {
4729                         ret= -EINVAL;
4730                         goto exit;
4731                 }
4732         }       
4733         
4734 exit:
4735         
4736         return ret;
4737                 
4738 }
4739
4740 static int rtw_set_pid(struct net_device *dev,
4741                                struct iw_request_info *info,
4742                                union iwreq_data *wrqu, char *extra)
4743 {
4744         
4745         int ret = 0;    
4746         _adapter *padapter = rtw_netdev_priv(dev);      
4747         int *pdata = (int *)wrqu;
4748         int selector;
4749
4750         if((padapter->bDriverStopped) || (pdata==NULL))
4751         {                
4752                 ret= -EINVAL;
4753                 goto exit;
4754         }               
4755   
4756         selector = *pdata;
4757         if(selector < 3 && selector >=0) {
4758                 padapter->pid[selector] = *(pdata+1);
4759                 #ifdef CONFIG_GLOBAL_UI_PID
4760                 ui_pid[selector] = *(pdata+1);
4761                 #endif
4762                 DBG_871X("%s set pid[%d]=%d\n", __FUNCTION__, selector ,padapter->pid[selector]);
4763         }
4764         else
4765                 DBG_871X("%s selector %d error\n", __FUNCTION__, selector);
4766
4767 exit:
4768         
4769         return ret;
4770                 
4771 }
4772
4773 static int rtw_wps_start(struct net_device *dev,
4774                                struct iw_request_info *info,
4775                                union iwreq_data *wrqu, char *extra)
4776 {
4777         
4778         int ret = 0;    
4779         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
4780         struct iw_point *pdata = &wrqu->data;
4781         u32   u32wps_start = 0;
4782         unsigned int uintRet = 0;
4783
4784         if((_TRUE == padapter->bDriverStopped) ||(_TRUE==padapter->bSurpriseRemoved) || (NULL== pdata))
4785         {                
4786                 ret= -EINVAL;
4787                 goto exit;
4788         }               
4789
4790         uintRet = copy_from_user( ( void* ) &u32wps_start, pdata->pointer, 4 );
4791         if ( u32wps_start == 0 )
4792         {
4793                 u32wps_start = *extra;
4794         }
4795
4796         DBG_871X( "[%s] wps_start = %d\n", __FUNCTION__, u32wps_start );
4797
4798         if ( u32wps_start == 1 ) // WPS Start
4799         {
4800                 rtw_led_control(padapter, LED_CTL_START_WPS);
4801         }
4802         else if ( u32wps_start == 2 ) // WPS Stop because of wps success
4803         {
4804                 rtw_led_control(padapter, LED_CTL_STOP_WPS);
4805         }
4806         else if ( u32wps_start == 3 ) // WPS Stop because of wps fail
4807         {
4808                 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
4809         }
4810
4811 #ifdef CONFIG_INTEL_WIDI
4812         process_intel_widi_wps_status(padapter, u32wps_start);
4813 #endif //CONFIG_INTEL_WIDI
4814         
4815 exit:
4816         
4817         return ret;
4818                 
4819 }
4820
4821 #ifdef CONFIG_P2P
4822 static int rtw_wext_p2p_enable(struct net_device *dev,
4823                                struct iw_request_info *info,
4824                                union iwreq_data *wrqu, char *extra)
4825 {
4826         
4827         int ret = 0;    
4828         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4829         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    
4830         struct iw_point *pdata = &wrqu->data;
4831         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
4832         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4833         enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
4834
4835         if(*extra == '0' )
4836                 init_role = P2P_ROLE_DISABLE;
4837         else if(*extra == '1')
4838                 init_role = P2P_ROLE_DEVICE;
4839         else if(*extra == '2')
4840                 init_role = P2P_ROLE_CLIENT;
4841         else if(*extra == '3')
4842                 init_role = P2P_ROLE_GO;
4843
4844         if(_FAIL == rtw_p2p_enable(padapter, init_role))
4845         {
4846                 ret = -EFAULT;
4847                 goto exit;
4848         }
4849
4850         //set channel/bandwidth
4851         if(init_role != P2P_ROLE_DISABLE) 
4852         {       
4853                 u8 channel, ch_offset;
4854                 u16 bwmode;
4855
4856                 if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
4857                 {
4858                         //      Stay at the listen state and wait for discovery.
4859                         channel = pwdinfo->listen_channel;
4860                         pwdinfo->operating_channel = pwdinfo->listen_channel;
4861                         ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4862                         bwmode = CHANNEL_WIDTH_20;
4863                 }
4864 #ifdef CONFIG_CONCURRENT_MODE
4865                 else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
4866                 {
4867                         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
4868                         //struct wifidirect_info        *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
4869                         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
4870                         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
4871                         
4872                         _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval );
4873                         if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
4874                         {
4875                                 pwdinfo->operating_channel = pbuddy_mlmeext->cur_channel;
4876                                 //      How about the ch_offset and bwmode ??
4877                         }
4878                         else
4879                         {
4880                                 pwdinfo->operating_channel = pwdinfo->listen_channel;
4881                         }
4882
4883                         channel = pbuddy_mlmeext->cur_channel;
4884                         ch_offset = pbuddy_mlmeext->cur_ch_offset;
4885                         bwmode = pbuddy_mlmeext->cur_bwmode;
4886                 }
4887 #endif
4888                 else
4889                 {
4890                         pwdinfo->operating_channel = pmlmeext->cur_channel;
4891                 
4892                         channel = pwdinfo->operating_channel;
4893                         ch_offset = pmlmeext->cur_ch_offset;
4894                         bwmode = pmlmeext->cur_bwmode;                                          
4895                 }
4896
4897                 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
4898         }
4899
4900 exit:
4901         return ret;
4902                 
4903 }
4904
4905 static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
4906                                struct iw_request_info *info,
4907                                union iwreq_data *wrqu, char *extra)
4908 {
4909         
4910         int ret = 0;    
4911         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4912         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    
4913         struct iw_point *pdata = &wrqu->data;
4914         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
4915
4916         DBG_871X( "[%s] ssid = %s, len = %zu\n", __FUNCTION__, extra, strlen( extra ) );
4917         _rtw_memcpy( pwdinfo->nego_ssid, extra, strlen( extra ) );
4918         pwdinfo->nego_ssidlen = strlen( extra );
4919         
4920         return ret;
4921                 
4922 }
4923
4924
4925 static int rtw_p2p_set_intent(struct net_device *dev,
4926                                struct iw_request_info *info,
4927                                union iwreq_data *wrqu, char *extra)
4928 {
4929         int                                                     ret = 0;
4930         _adapter                                                *padapter = (_adapter *)rtw_netdev_priv(dev);
4931         struct wifidirect_info                  *pwdinfo= &(padapter->wdinfo);
4932         u8                                                      intent = pwdinfo->intent;
4933
4934         extra[ wrqu->data.length ] = 0x00;
4935
4936         intent = rtw_atoi( extra );
4937
4938         if ( intent <= 15 )
4939         {
4940                 pwdinfo->intent= intent;
4941         }
4942         else
4943         {
4944                 ret = -1;
4945         }
4946         
4947         DBG_871X( "[%s] intent = %d\n", __FUNCTION__, intent);
4948
4949         return ret;
4950                 
4951 }
4952
4953 static int rtw_p2p_set_listen_ch(struct net_device *dev,
4954                                struct iw_request_info *info,
4955                                union iwreq_data *wrqu, char *extra)
4956 {
4957         
4958         int ret = 0;    
4959         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4960         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
4961         u8      listen_ch = pwdinfo->listen_channel;    //      Listen channel number
4962
4963         extra[ wrqu->data.length ] = 0x00;
4964         listen_ch = rtw_atoi( extra );
4965
4966         if ( ( listen_ch == 1 ) || ( listen_ch == 6 ) || ( listen_ch == 11 ) )
4967         {
4968                 pwdinfo->listen_channel = listen_ch;
4969                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4970         }
4971         else
4972         {
4973                 ret = -1;
4974         }
4975         
4976         DBG_871X( "[%s] listen_ch = %d\n", __FUNCTION__, pwdinfo->listen_channel );
4977         
4978         return ret;
4979                 
4980 }
4981
4982 static int rtw_p2p_set_op_ch(struct net_device *dev,
4983                                struct iw_request_info *info,
4984                                union iwreq_data *wrqu, char *extra)
4985 {
4986 //      Commented by Albert 20110524
4987 //      This function is used to set the operating channel if the driver will become the group owner
4988
4989         int ret = 0;    
4990         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4991         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
4992         u8      op_ch = pwdinfo->operating_channel;     //      Operating channel number
4993
4994         extra[ wrqu->data.length ] = 0x00;
4995
4996         op_ch = ( u8 ) rtw_atoi( extra );
4997         if ( op_ch > 0 )
4998         {
4999                 pwdinfo->operating_channel = op_ch;
5000         }
5001         else
5002         {
5003                 ret = -1;
5004         }
5005         
5006         DBG_871X( "[%s] op_ch = %d\n", __FUNCTION__, pwdinfo->operating_channel );
5007         
5008         return ret;
5009
5010 }
5011
5012
5013 static int rtw_p2p_profilefound(struct net_device *dev,
5014                                struct iw_request_info *info,
5015                                union iwreq_data *wrqu, char *extra)
5016 {
5017         
5018         int ret = 0;    
5019         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5020         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
5021
5022         //      Comment by Albert 2010/10/13
5023         //      Input data format:
5024         //      Ex:  0
5025         //      Ex:  1XX:XX:XX:XX:XX:XXYYSSID
5026         //      0 => Reflush the profile record list.
5027         //      1 => Add the profile list
5028         //      XX:XX:XX:XX:XX:XX => peer's MAC Address ( ex: 00:E0:4C:00:00:01 )
5029         //      YY => SSID Length
5030         //      SSID => SSID for persistence group
5031
5032         DBG_871X( "[%s] In value = %s, len = %d \n", __FUNCTION__, extra, wrqu->data.length -1);
5033
5034         
5035         //      The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function.
5036         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
5037         {
5038                 if ( extra[ 0 ] == '0' )
5039                 {
5040                         //      Remove all the profile information of wifidirect_info structure.
5041                         _rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
5042                         pwdinfo->profileindex = 0;
5043                 }
5044                 else
5045                 {
5046                         if ( pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM )
5047                 {
5048                                 ret = -1;
5049                 }
5050                 else
5051                 {
5052                                 int jj, kk;
5053                                 
5054                                 //      Add this profile information into pwdinfo->profileinfo
5055                                 //      Ex:  1XX:XX:XX:XX:XX:XXYYSSID
5056                                 for( jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3 )
5057                                 {
5058                                         pwdinfo->profileinfo[ pwdinfo->profileindex ].peermac[ jj ] = key_2char2num(extra[ kk ], extra[ kk+ 1 ]);
5059                                 }
5060
5061                                 //pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen = ( extra[18] - '0' ) * 10 + ( extra[ 19 ] - '0' );
5062                                 //_rtw_memcpy( pwdinfo->profileinfo[ pwdinfo->profileindex ].ssid, &extra[ 20 ], pwdinfo->profileinfo[ pwdinfo->profileindex ].ssidlen );
5063                                 pwdinfo->profileindex++;
5064                         }
5065                 }
5066         }       
5067         
5068         return ret;
5069                 
5070 }
5071
5072 static int rtw_p2p_setDN(struct net_device *dev,
5073                                struct iw_request_info *info,
5074                                union iwreq_data *wrqu, char *extra)
5075 {
5076         
5077         int ret = 0;    
5078         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5079         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
5080
5081
5082         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
5083         _rtw_memset( pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN );
5084         _rtw_memcpy( pwdinfo->device_name, extra, wrqu->data.length - 1 );
5085         pwdinfo->device_name_len = wrqu->data.length - 1;
5086
5087         return ret;
5088                 
5089 }
5090
5091
5092 static int rtw_p2p_get_status(struct net_device *dev,
5093                                struct iw_request_info *info,
5094                                union iwreq_data *wrqu, char *extra)
5095 {
5096         
5097         int ret = 0;    
5098         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5099         struct iw_point *pdata = &wrqu->data;
5100         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5101 #ifdef CONFIG_CONCURRENT_MODE
5102         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
5103         struct wifidirect_info  *pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
5104         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
5105         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; 
5106 #endif
5107         
5108         if ( padapter->bShowGetP2PState )
5109         {
5110                 DBG_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
5111                                 pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
5112                                 pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
5113         }
5114
5115         //      Commented by Albert 2010/10/12
5116         //      Because of the output size limitation, I had removed the "Role" information.
5117         //      About the "Role" information, we will use the new private IOCTL to get the "Role" information.
5118         sprintf( extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo) );
5119         wrqu->data.length = strlen( extra );
5120
5121         return ret;
5122                 
5123 }
5124
5125 //      Commented by Albert 20110520
5126 //      This function will return the config method description 
5127 //      This config method description will show us which config method the remote P2P device is intented to use
5128 //      by sending the provisioning discovery request frame.
5129
5130 static int rtw_p2p_get_req_cm(struct net_device *dev,
5131                                struct iw_request_info *info,
5132                                union iwreq_data *wrqu, char *extra)
5133 {
5134         
5135         int ret = 0;    
5136         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5137         struct iw_point *pdata = &wrqu->data;
5138         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5139
5140         sprintf( extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req );
5141         wrqu->data.length = strlen( extra );
5142         return ret;
5143                 
5144 }
5145
5146
5147 static int rtw_p2p_get_role(struct net_device *dev,
5148                                struct iw_request_info *info,
5149                                union iwreq_data *wrqu, char *extra)
5150 {
5151         
5152         int ret = 0;    
5153         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5154         struct iw_point *pdata = &wrqu->data;
5155         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5156
5157         
5158         DBG_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
5159                         pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
5160                         pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
5161
5162         sprintf( extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo) );
5163         wrqu->data.length = strlen( extra );
5164         return ret;
5165                 
5166 }
5167
5168
5169 static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
5170                                struct iw_request_info *info,
5171                                union iwreq_data *wrqu, char *extra)
5172 {
5173         
5174         int ret = 0;    
5175         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5176         struct iw_point *pdata = &wrqu->data;
5177         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5178
5179
5180         DBG_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
5181                         pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
5182                         pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
5183
5184         sprintf( extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
5185                         pwdinfo->p2p_peer_interface_addr[ 0 ], pwdinfo->p2p_peer_interface_addr[ 1 ], pwdinfo->p2p_peer_interface_addr[ 2 ],
5186                         pwdinfo->p2p_peer_interface_addr[ 3 ], pwdinfo->p2p_peer_interface_addr[ 4 ], pwdinfo->p2p_peer_interface_addr[ 5 ]);
5187         wrqu->data.length = strlen( extra );
5188         return ret;
5189                 
5190 }
5191
5192 static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
5193                                struct iw_request_info *info,
5194                                union iwreq_data *wrqu, char *extra)
5195
5196 {
5197         
5198         int ret = 0;    
5199         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5200         struct iw_point *pdata = &wrqu->data;
5201         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5202
5203         DBG_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
5204                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 0 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 1 ], 
5205                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 2 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 3 ],
5206                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 4 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 5 ]);
5207         sprintf( extra, "\n%.2X%.2X%.2X%.2X%.2X%.2X",
5208                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 0 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 1 ], 
5209                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 2 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 3 ],
5210                         pwdinfo->rx_prov_disc_info.peerDevAddr[ 4 ], pwdinfo->rx_prov_disc_info.peerDevAddr[ 5 ]);
5211         wrqu->data.length = strlen( extra );    
5212         return ret;
5213                 
5214 }
5215
5216 static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
5217                                struct iw_request_info *info,
5218                                union iwreq_data *wrqu, char *extra)
5219
5220 {
5221         
5222         int ret = 0;    
5223         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5224         struct iw_point *pdata = &wrqu->data;
5225         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5226
5227         DBG_871X( "[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
5228                         pwdinfo->p2p_peer_device_addr[ 0 ], pwdinfo->p2p_peer_device_addr[ 1 ], 
5229                         pwdinfo->p2p_peer_device_addr[ 2 ], pwdinfo->p2p_peer_device_addr[ 3 ],
5230                         pwdinfo->p2p_peer_device_addr[ 4 ], pwdinfo->p2p_peer_device_addr[ 5 ]);
5231         sprintf( extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
5232                         pwdinfo->p2p_peer_device_addr[ 0 ], pwdinfo->p2p_peer_device_addr[ 1 ], 
5233                         pwdinfo->p2p_peer_device_addr[ 2 ], pwdinfo->p2p_peer_device_addr[ 3 ],
5234                         pwdinfo->p2p_peer_device_addr[ 4 ], pwdinfo->p2p_peer_device_addr[ 5 ]);
5235         wrqu->data.length = strlen( extra );    
5236         return ret;
5237                 
5238 }
5239
5240 static int rtw_p2p_get_groupid(struct net_device *dev,
5241                                struct iw_request_info *info,
5242                                union iwreq_data *wrqu, char *extra)
5243
5244 {
5245         
5246         int ret = 0;    
5247         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5248         struct iw_point *pdata = &wrqu->data;
5249         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5250
5251         sprintf( extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
5252                         pwdinfo->groupid_info.go_device_addr[ 0 ], pwdinfo->groupid_info.go_device_addr[ 1 ], 
5253                         pwdinfo->groupid_info.go_device_addr[ 2 ], pwdinfo->groupid_info.go_device_addr[ 3 ],
5254                         pwdinfo->groupid_info.go_device_addr[ 4 ], pwdinfo->groupid_info.go_device_addr[ 5 ],
5255                         pwdinfo->groupid_info.ssid);
5256         wrqu->data.length = strlen( extra );    
5257         return ret;
5258                 
5259 }
5260
5261 static int rtw_p2p_get_op_ch(struct net_device *dev,
5262                                struct iw_request_info *info,
5263                                union iwreq_data *wrqu, char *extra)
5264
5265 {
5266         
5267         int ret = 0;    
5268         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5269         struct iw_point *pdata = &wrqu->data;
5270         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5271
5272         
5273         DBG_871X( "[%s] Op_ch = %02x\n", __FUNCTION__, pwdinfo->operating_channel);
5274         
5275         sprintf( extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel );
5276         wrqu->data.length = strlen( extra );
5277         return ret;
5278                 
5279 }
5280
5281 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
5282                                                                                 struct iw_request_info *info,
5283                                                                                 union iwreq_data *wrqu, char *extra, char *subcmd)
5284
5285         
5286         int ret = 0;
5287         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5288         u8 peerMAC[ETH_ALEN] = { 0x00 };
5289         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5290         _irqL irqL;
5291         _list * plist,*phead;
5292         _queue *queue = &(pmlmepriv->scanned_queue);
5293         struct wlan_network *pnetwork = NULL;
5294         u8 blnMatch = 0;
5295         u16     attr_content = 0;
5296         uint attr_contentlen = 0;
5297         u8      attr_content_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5298
5299         //      Commented by Albert 20110727
5300         //      The input data is the MAC address which the application wants to know its WPS config method.
5301         //      After knowing its WPS config method, the application can decide the config method for provisioning discovery.
5302         //      Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05
5303
5304         DBG_871X("[%s] data = %s\n", __FUNCTION__, subcmd);
5305
5306         macstr2num(peerMAC, subcmd);
5307
5308         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5309
5310         phead = get_list_head(queue);
5311         plist = get_next(phead);
5312
5313         while (1)
5314         {
5315                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
5316
5317                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5318                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
5319                 {
5320                         u8 *wpsie;
5321                         uint    wpsie_len = 0;
5322
5323                         //      The mac address is matched.
5324
5325                         if ( (wpsie=rtw_get_wps_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0])) )
5326                         {
5327                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&attr_content, &attr_contentlen);
5328                                 if (attr_contentlen)
5329                                 {
5330                                         attr_content = be16_to_cpu(attr_content);
5331                                         sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
5332                                         blnMatch = 1;
5333                                 }
5334                         }
5335
5336                         break;
5337                 }
5338
5339                 plist = get_next(plist);
5340
5341         }
5342
5343         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5344
5345         if (!blnMatch)
5346         {
5347                 sprintf(attr_content_str, "\n\nM=0000");
5348         }
5349
5350         wrqu->data.length = strlen(attr_content_str);
5351         _rtw_memcpy(extra, attr_content_str, wrqu->data.length);
5352
5353         return ret; 
5354                 
5355 }
5356
5357 #ifdef CONFIG_WFD
5358 static int rtw_p2p_get_peer_wfd_port(struct net_device *dev,
5359                                struct iw_request_info *info,
5360                                union iwreq_data *wrqu, char *extra)
5361 {
5362         
5363         int ret = 0;    
5364         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5365         struct iw_point *pdata = &wrqu->data;
5366         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5367
5368         DBG_871X( "[%s] p2p_state = %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );
5369
5370         sprintf( extra, "\n\nPort=%d\n", pwdinfo->wfd_info->peer_rtsp_ctrlport );
5371         DBG_871X( "[%s] remote port = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport );
5372         
5373         wrqu->data.length = strlen( extra );
5374         return ret;
5375                 
5376 }
5377
5378 static int rtw_p2p_get_peer_wfd_preferred_connection(struct net_device *dev,
5379                                struct iw_request_info *info,
5380                                union iwreq_data *wrqu, char *extra)
5381 {
5382         
5383         int ret = 0;    
5384         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5385         struct iw_point *pdata = &wrqu->data;
5386         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5387
5388         sprintf( extra, "\n\nwfd_pc=%d\n", pwdinfo->wfd_info->wfd_pc );
5389         DBG_871X( "[%s] wfd_pc = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_pc );
5390
5391         wrqu->data.length = strlen( extra );
5392         pwdinfo->wfd_info->wfd_pc = _FALSE;     //      Reset the WFD preferred connection to P2P
5393         return ret;
5394                 
5395 }
5396
5397 static int rtw_p2p_get_peer_wfd_session_available(struct net_device *dev,
5398                                struct iw_request_info *info,
5399                                union iwreq_data *wrqu, char *extra)
5400 {
5401         
5402         int ret = 0;    
5403         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
5404         struct iw_point *pdata = &wrqu->data;
5405         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5406
5407         sprintf( extra, "\n\nwfd_sa=%d\n", pwdinfo->wfd_info->peer_session_avail );
5408         DBG_871X( "[%s] wfd_sa = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_session_avail );
5409
5410         wrqu->data.length = strlen( extra );
5411         pwdinfo->wfd_info->peer_session_avail = _TRUE;  //      Reset the WFD session available
5412         return ret;
5413                 
5414 }
5415
5416 #endif // CONFIG_WFD
5417
5418 static int rtw_p2p_get_go_device_address(struct net_device *dev,
5419                                                                                  struct iw_request_info *info,
5420                                                                                  union iwreq_data *wrqu, char *extra, char *subcmd)
5421 {
5422
5423         int ret = 0;    
5424         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5425         u8 peerMAC[ETH_ALEN] = { 0x00 };
5426         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5427         _irqL irqL;
5428         _list *plist, *phead;
5429         _queue *queue   = &(pmlmepriv->scanned_queue);
5430         struct wlan_network *pnetwork = NULL;
5431         u8 blnMatch = 0;
5432         u8 *p2pie;
5433         uint p2pielen = 0, attr_contentlen = 0;
5434         u8 attr_content[100] = { 0x00 };
5435         u8 go_devadd_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5436
5437         //      Commented by Albert 20121209
5438         //      The input data is the GO's interface address which the application wants to know its device address.
5439         //      Format: iwpriv wlanx p2p_get2 go_devadd=00:E0:4C:00:00:05
5440
5441         DBG_871X("[%s] data = %s\n", __FUNCTION__, subcmd);
5442
5443         macstr2num(peerMAC, subcmd);
5444
5445         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5446
5447         phead = get_list_head(queue);
5448         plist = get_next(phead);
5449
5450         while (1)
5451         {
5452                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
5453
5454                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5455                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
5456                 {
5457                         //      Commented by Albert 2011/05/18
5458                         //      Match the device address located in the P2P IE
5459                         //      This is for the case that the P2P device address is not the same as the P2P interface address.
5460
5461                         if ((p2pie = rtw_get_p2p_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &p2pielen, pnetwork->network.Reserved[0])))
5462                         {
5463                                 while (p2pie)
5464                                 {
5465                                         //      The P2P Device ID attribute is included in the Beacon frame.
5466                                         //      The P2P Device Info attribute is included in the probe response frame.
5467
5468                                         _rtw_memset(attr_content, 0x00, 100);
5469                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen))
5470                                         {
5471                                                 //      Handle the P2P Device ID attribute of Beacon first
5472                                                 blnMatch = 1;
5473                                                 break;
5474
5475                                         } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen))
5476                                         {
5477                                                 //      Handle the P2P Device Info attribute of probe response
5478                                                 blnMatch = 1;
5479                                                 break;
5480                                         }
5481
5482                                         //Get the next P2P IE
5483                                         p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
5484                                 }
5485                         }
5486                 }
5487
5488                 plist = get_next(plist);
5489
5490         }
5491
5492         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5493
5494         if (!blnMatch)
5495         {
5496                 sprintf(go_devadd_str, "\n\ndev_add=NULL");
5497         } else
5498         {
5499                 sprintf(go_devadd_str, "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
5500                                 attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
5501         }
5502
5503         wrqu->data.length = strlen(go_devadd_str);
5504         _rtw_memcpy(extra, go_devadd_str, wrqu->data.length);
5505
5506         return ret; 
5507                 
5508 }
5509
5510 static int rtw_p2p_get_device_type(struct net_device *dev,
5511                                                                    struct iw_request_info *info,
5512                                                                    union iwreq_data *wrqu, char *extra, char *subcmd)
5513
5514         
5515         int ret = 0;
5516         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5517         u8 peerMAC[ETH_ALEN] = { 0x00 };
5518         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5519         _irqL irqL;
5520         _list *plist, *phead;
5521         _queue *queue = &(pmlmepriv->scanned_queue);
5522         struct wlan_network *pnetwork = NULL;
5523         u8 blnMatch = 0;
5524         u8 dev_type[8] = { 0x00 };
5525         uint dev_type_len = 0;
5526         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
5527
5528         //      Commented by Albert 20121209
5529         //      The input data is the MAC address which the application wants to know its device type.
5530         //      Such user interface could know the device type.
5531         //      Format: iwpriv wlanx p2p_get2 dev_type=00:E0:4C:00:00:05
5532
5533         DBG_871X("[%s] data = %s\n", __FUNCTION__, subcmd);
5534
5535         macstr2num(peerMAC, subcmd);
5536
5537         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5538
5539         phead = get_list_head(queue);
5540         plist = get_next(phead);
5541
5542         while (1)
5543         {
5544                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
5545
5546                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5547                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
5548                 {
5549                         u8 *wpsie;
5550                         uint    wpsie_len = 0;
5551
5552                         //      The mac address is matched.
5553
5554                         if ( (wpsie=rtw_get_wps_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0])) )
5555                         {
5556                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
5557                                 if (dev_type_len)
5558                                 {
5559                                         u16     type = 0;
5560
5561                                         _rtw_memcpy(&type, dev_type, 2);
5562                                         type = be16_to_cpu(type);
5563                                         sprintf(dev_type_str, "\n\nN=%.2d", type);
5564                                         blnMatch = 1;
5565                                 }
5566                         }
5567                         break;
5568                 }
5569
5570                 plist = get_next(plist);
5571
5572         }
5573
5574         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5575
5576         if (!blnMatch)
5577         {
5578                 sprintf(dev_type_str, "\n\nN=00");
5579         }
5580
5581         wrqu->data.length = strlen(dev_type_str);
5582         _rtw_memcpy(extra, dev_type_str, wrqu->data.length);
5583
5584         return ret; 
5585                 
5586 }
5587
5588 static int rtw_p2p_get_device_name(struct net_device *dev,
5589                                                                    struct iw_request_info *info,
5590                                                                    union iwreq_data *wrqu, char *extra, char *subcmd)
5591
5592         
5593         int ret = 0;
5594         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5595         u8 peerMAC[ETH_ALEN] = { 0x00 };
5596         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5597         _irqL irqL;
5598         _list *plist, *phead;
5599         _queue *queue = &(pmlmepriv->scanned_queue);
5600         struct wlan_network *pnetwork = NULL;
5601         u8 blnMatch = 0;
5602         u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = { 0x00 };
5603         uint dev_len = 0;
5604         u8 dev_name_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5605
5606         //      Commented by Albert 20121225
5607         //      The input data is the MAC address which the application wants to know its device name.
5608         //      Such user interface could show peer device's device name instead of ssid.
5609         //      Format: iwpriv wlanx p2p_get2 devN=00:E0:4C:00:00:05
5610
5611         DBG_871X("[%s] data = %s\n", __FUNCTION__, subcmd);
5612
5613         macstr2num(peerMAC, subcmd);
5614
5615         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5616
5617         phead = get_list_head(queue);
5618         plist = get_next(phead);
5619
5620         while (1)
5621         {
5622                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
5623
5624                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5625                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
5626                 {
5627                         u8 *wpsie;
5628                         uint    wpsie_len = 0;
5629
5630                         //      The mac address is matched.
5631
5632                         if ( (wpsie=rtw_get_wps_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0])) )
5633                         {
5634                                 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
5635                                 if (dev_len)
5636                                 {
5637                                         sprintf(dev_name_str, "\n\nN=%s", dev_name);
5638                                         blnMatch = 1;
5639                                 }
5640                         }
5641                         break;
5642                 }
5643
5644                 plist = get_next(plist);
5645
5646         }
5647
5648         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5649
5650         if (!blnMatch)
5651         {
5652                 sprintf(dev_name_str, "\n\nN=0000");
5653         }
5654
5655         wrqu->data.length = strlen(dev_name_str);
5656         _rtw_memcpy(extra, dev_name_str, wrqu->data.length);
5657
5658         return ret; 
5659                 
5660 }
5661
5662 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
5663                                                                                         struct iw_request_info *info,
5664                                                                                         union iwreq_data *wrqu, char *extra, char *subcmd)
5665 {
5666
5667         int ret = 0;    
5668         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5669         u8 peerMAC[ETH_ALEN] = { 0x00 };
5670         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5671         _irqL irqL;
5672         _list *plist, *phead;
5673         _queue *queue   = &(pmlmepriv->scanned_queue);
5674         struct wlan_network *pnetwork = NULL;
5675         u8 blnMatch = 0;
5676         u8 *p2pie;
5677         uint p2pielen = 0, attr_contentlen = 0;
5678         u8 attr_content[2] = { 0x00 };
5679         u8 inv_proc_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
5680
5681         //      Commented by Ouden 20121226
5682         //      The application wants to know P2P initation procedure is support or not.
5683         //      Format: iwpriv wlanx p2p_get2 InvProc=00:E0:4C:00:00:05
5684
5685         DBG_871X("[%s] data = %s\n", __FUNCTION__, subcmd);
5686
5687         macstr2num(peerMAC, subcmd);
5688
5689         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5690
5691         phead = get_list_head(queue);
5692         plist = get_next(phead);
5693
5694         while (1)
5695         {
5696                 if (rtw_end_of_queue_search(phead, plist) == _TRUE) break;
5697
5698                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5699                 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN))
5700                 {
5701                         //      Commented by Albert 20121226
5702                         //      Match the device address located in the P2P IE
5703                         //      This is for the case that the P2P device address is not the same as the P2P interface address.
5704
5705                         if ((p2pie = rtw_get_p2p_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &p2pielen, pnetwork->network.Reserved[0])))
5706                         {
5707                                 while (p2pie)
5708                                 {
5709                                         //_rtw_memset( attr_content, 0x00, 2);
5710                                         if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen))
5711                                         {
5712                                                 //      Handle the P2P capability attribute
5713                                                 blnMatch = 1;
5714                                                 break;
5715
5716                                         }
5717
5718                                         //Get the next P2P IE
5719                                         p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
5720                                 }
5721                         }
5722                 }
5723
5724                 plist = get_next(plist);
5725
5726         }
5727
5728         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5729
5730         if (!blnMatch)
5731         {
5732                 sprintf(inv_proc_str, "\nIP=-1");
5733         } else
5734         {
5735                 if ((attr_content[0] & 0x20) == 0x20)
5736                         sprintf(inv_proc_str, "\nIP=1");
5737                 else
5738                         sprintf(inv_proc_str, "\nIP=0");
5739         }
5740
5741         wrqu->data.length = strlen(inv_proc_str);
5742         _rtw_memcpy(extra, inv_proc_str, wrqu->data.length);
5743
5744         return ret; 
5745                 
5746 }
5747
5748 static int rtw_p2p_connect(struct net_device *dev,
5749                                struct iw_request_info *info,
5750                                union iwreq_data *wrqu, char *extra)
5751 {
5752         
5753         int ret = 0;    
5754         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);   
5755         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
5756         u8                                      peerMAC[ ETH_ALEN ] = { 0x00 };
5757         int                                     jj,kk;
5758         u8                                      peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
5759         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
5760         _irqL                           irqL;
5761         _list                                   *plist, *phead;
5762         _queue                          *queue  = &(pmlmepriv->scanned_queue);
5763         struct  wlan_network    *pnetwork = NULL;
5764         uint                                    uintPeerChannel = 0;
5765 #ifdef CONFIG_CONCURRENT_MODE
5766         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
5767         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
5768         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
5769 #endif // CONFIG_CONCURRENT_MODE        
5770
5771         //      Commented by Albert 20110304
5772         //      The input data contains two informations.
5773         //      1. First information is the MAC address which wants to formate with
5774         //      2. Second information is the WPS PINCode or "pbc" string for push button method
5775         //      Format: 00:E0:4C:00:00:05
5776         //      Format: 00:E0:4C:00:00:05
5777
5778         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
5779
5780         if ( pwdinfo->p2p_state == P2P_STATE_NONE )
5781         {
5782                 DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
5783                 return ret;
5784         }
5785
5786 #ifdef CONFIG_INTEL_WIDI
5787         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
5788                 DBG_871X( "[%s] WiFi is under survey!\n", __FUNCTION__ );
5789                 return ret;
5790         }
5791 #endif //CONFIG_INTEL_WIDI      
5792
5793         if ( pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO )
5794         {
5795                 return -1;
5796         }
5797         
5798         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
5799         {
5800                 peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
5801         }
5802
5803         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5804
5805         phead = get_list_head(queue);
5806         plist = get_next(phead);
5807        
5808         while(1)
5809         {
5810                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
5811                         break;
5812
5813                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5814                 if ( _rtw_memcmp( pnetwork->network.MacAddress, peerMAC, ETH_ALEN ) )
5815                 {
5816                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5817                         break;
5818                 }
5819
5820                 plist = get_next(plist);
5821         
5822         }
5823
5824         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5825
5826         if ( uintPeerChannel )
5827         {
5828 #ifdef CONFIG_CONCURRENT_MODE
5829                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
5830                 {
5831                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
5832                 }
5833 #endif // CONFIG_CONCURRENT_MODE
5834
5835                 _rtw_memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
5836                 _rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
5837                 
5838                 pwdinfo->nego_req_info.peer_channel_num[ 0 ] = uintPeerChannel;
5839                 _rtw_memcpy( pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN );
5840                 pwdinfo->nego_req_info.benable = _TRUE;
5841
5842                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5843                 if ( rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK )
5844                 {
5845                         //      Restore to the listen state if the current p2p state is not nego OK
5846                         rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN );
5847                 }
5848
5849                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5850                 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
5851
5852 #ifdef CONFIG_CONCURRENT_MODE
5853                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
5854                 {
5855                         //      Have to enter the power saving with the AP
5856                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
5857                         
5858                         issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
5859                 }
5860 #endif // CONFIG_CONCURRENT_MODE
5861
5862                 DBG_871X( "[%s] Start PreTx Procedure!\n", __FUNCTION__ );
5863                 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
5864 #ifdef CONFIG_CONCURRENT_MODE
5865                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
5866                 {
5867                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_GO_NEGO_TIMEOUT );
5868                 }
5869                 else
5870                 {
5871                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
5872                 }
5873 #else
5874                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT );
5875 #endif // CONFIG_CONCURRENT_MODE                
5876
5877         }
5878         else
5879         {
5880                 DBG_871X( "[%s] Not Found in Scanning Queue~\n", __FUNCTION__ );
5881 #ifdef CONFIG_INTEL_WIDI
5882                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
5883                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
5884                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
5885                 rtw_free_network_queue(padapter, _TRUE);
5886                 /** 
5887                  * For WiDi, if we can't find candidate device in scanning queue,
5888                  * driver will do scanning itself
5889                  */
5890                 _enter_critical_bh(&pmlmepriv->lock, &irqL);
5891                 rtw_sitesurvey_cmd(padapter, NULL, 0, NULL, 0);
5892                 _exit_critical_bh(&pmlmepriv->lock, &irqL);
5893 #endif //CONFIG_INTEL_WIDI 
5894                 ret = -1;
5895         }
5896 exit:   
5897         return ret;
5898 }
5899
5900 static int rtw_p2p_invite_req(struct net_device *dev,
5901                                struct iw_request_info *info,
5902                                union iwreq_data *wrqu, char *extra)
5903 {
5904         
5905         int ret = 0;    
5906         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);   
5907         struct iw_point                         *pdata = &wrqu->data;
5908         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
5909         int                                             jj,kk;
5910         u8                                              peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
5911         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
5912         _list                                           *plist, *phead;
5913         _queue                                  *queue  = &(pmlmepriv->scanned_queue);
5914         struct  wlan_network            *pnetwork = NULL;
5915         uint                                            uintPeerChannel = 0;
5916         u8                                              attr_content[50] = { 0x00 }, _status = 0;
5917         u8                                              *p2pie;
5918         uint                                            p2pielen = 0, attr_contentlen = 0;
5919         _irqL                                   irqL;
5920         struct tx_invite_req_info*      pinvite_req_info = &pwdinfo->invitereq_info;
5921         u8 ie_offset = 12;
5922 #ifdef CONFIG_CONCURRENT_MODE
5923         _adapter                                        *pbuddy_adapter = padapter->pbuddy_adapter;
5924         struct mlme_priv                        *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
5925         struct mlme_ext_priv            *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
5926 #endif // CONFIG_CONCURRENT_MODE
5927
5928 #ifdef CONFIG_WFD
5929         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
5930 #endif // CONFIG_WFD
5931         
5932         //      Commented by Albert 20120321
5933         //      The input data contains two informations.
5934         //      1. First information is the P2P device address which you want to send to.       
5935         //      2. Second information is the group id which combines with GO's mac address, space and GO's ssid.
5936         //      Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy"
5937         //      Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy
5938
5939         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
5940
5941         if ( wrqu->data.length <=  37 )
5942         {
5943                 DBG_871X( "[%s] Wrong format!\n", __FUNCTION__ );
5944                 return ret;
5945         }
5946
5947         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
5948         {
5949                 DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
5950                 return ret;
5951         }
5952         else
5953         {
5954                 //      Reset the content of struct tx_invite_req_info
5955                 pinvite_req_info->benable = _FALSE;
5956                 _rtw_memset( pinvite_req_info->go_bssid, 0x00, ETH_ALEN );
5957                 _rtw_memset( pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN );
5958                 pinvite_req_info->ssidlen = 0x00;
5959                 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
5960                 _rtw_memset( pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN );
5961                 pinvite_req_info->token = 3;
5962         }
5963         
5964         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
5965         {
5966                 pinvite_req_info->peer_macaddr[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
5967         }
5968
5969         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5970
5971         phead = get_list_head(queue);
5972         plist = get_next(phead);
5973        
5974         while(1)
5975         {
5976                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
5977                         break;
5978
5979                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5980
5981                 //      Commented by Albert 2011/05/18
5982                 //      Match the device address located in the P2P IE
5983                 //      This is for the case that the P2P device address is not the same as the P2P interface address.
5984
5985                 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);
5986                 if ( (p2pie=rtw_get_p2p_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &p2pielen, pnetwork->network.Reserved[0])))
5987                 {
5988                         //      The P2P Device ID attribute is included in the Beacon frame.
5989                         //      The P2P Device Info attribute is included in the probe response frame.
5990
5991                         if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
5992                         {
5993                                 //      Handle the P2P Device ID attribute of Beacon first
5994                                 if ( _rtw_memcmp( attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN ) )
5995                                 {
5996                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5997                                         break;
5998                                 }
5999                         }
6000                         else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
6001                         {
6002                                 //      Handle the P2P Device Info attribute of probe response
6003                                 if ( _rtw_memcmp( attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN ) )
6004                                 {
6005                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6006                                         break;
6007                                 }                                       
6008                         }
6009
6010                 }
6011
6012                 plist = get_next(plist);
6013         
6014         }
6015
6016         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6017
6018 #ifdef CONFIG_WFD
6019         if ( uintPeerChannel )
6020         {
6021                 u8      wfd_ie[ 128 ] = { 0x00 };
6022                 uint    wfd_ielen = 0;
6023                 
6024                 if ( rtw_get_wfd_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength,  wfd_ie, &wfd_ielen, pnetwork->network.Reserved[0]) )
6025                 {
6026                         u8      wfd_devinfo[ 6 ] = { 0x00 };
6027                         uint    wfd_devlen = 6;
6028
6029                         DBG_871X( "[%s] Found WFD IE!\n", __FUNCTION__ );
6030                         if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
6031                         {
6032                                 u16     wfd_devinfo_field = 0;
6033                                 
6034                                 //      Commented by Albert 20120319
6035                                 //      The first two bytes are the WFD device information field of WFD device information subelement.
6036                                 //      In big endian format.
6037                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
6038                                 if ( wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL )
6039                                 {
6040                                         pwfd_info->peer_session_avail = _TRUE;
6041                                 }
6042                                 else
6043                                 {
6044                                         pwfd_info->peer_session_avail = _FALSE;
6045                                 }
6046                         }
6047                 }
6048                 
6049                 if ( _FALSE == pwfd_info->peer_session_avail )
6050                 {
6051                         DBG_871X( "[%s] WFD Session not avaiable!\n", __FUNCTION__ );
6052                         goto exit;
6053                 }
6054         }
6055 #endif // CONFIG_WFD
6056
6057         if ( uintPeerChannel )
6058         {
6059 #ifdef CONFIG_CONCURRENT_MODE
6060                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
6061                 {
6062                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
6063                 }
6064 #endif // CONFIG_CONCURRENT_MODE
6065
6066                 //      Store the GO's bssid
6067                 for( jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3 )
6068                 {
6069                         pinvite_req_info->go_bssid[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
6070                 }
6071
6072                 //      Store the GO's ssid
6073                 pinvite_req_info->ssidlen = wrqu->data.length - 36;
6074                 _rtw_memcpy( pinvite_req_info->go_ssid, &extra[ 36 ], (u32) pinvite_req_info->ssidlen );
6075                 pinvite_req_info->benable = _TRUE;
6076                 pinvite_req_info->peer_ch = uintPeerChannel;
6077
6078                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
6079                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
6080
6081 #ifdef CONFIG_CONCURRENT_MODE
6082                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
6083                 {
6084                         //      Have to enter the power saving with the AP
6085                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
6086                         
6087                         issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
6088                 }
6089                 else
6090                 {
6091                         set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
6092                 }
6093 #else
6094                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
6095 #endif
6096
6097                 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
6098                 
6099 #ifdef CONFIG_CONCURRENT_MODE
6100                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
6101                 {
6102                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_INVITE_TIMEOUT );
6103                 }
6104                 else
6105                 {
6106                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT );
6107                 }
6108 #else
6109                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT );
6110 #endif // CONFIG_CONCURRENT_MODE                
6111
6112                 
6113         }
6114         else
6115         {
6116                 DBG_871X( "[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__ );
6117         }
6118 exit:
6119         
6120         return ret;
6121                 
6122 }
6123
6124 static int rtw_p2p_set_persistent(struct net_device *dev,
6125                                struct iw_request_info *info,
6126                                union iwreq_data *wrqu, char *extra)
6127 {
6128         
6129         int ret = 0;    
6130         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);   
6131         struct iw_point                         *pdata = &wrqu->data;
6132         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
6133         int                                             jj,kk;
6134         u8                                              peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
6135         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
6136         _list                                           *plist, *phead;
6137         _queue                                  *queue  = &(pmlmepriv->scanned_queue);
6138         struct  wlan_network            *pnetwork = NULL;
6139         uint                                            uintPeerChannel = 0;
6140         u8                                              attr_content[50] = { 0x00 }, _status = 0;
6141         u8                                              *p2pie;
6142         uint                                            p2pielen = 0, attr_contentlen = 0;
6143         _irqL                                   irqL;
6144         struct tx_invite_req_info*      pinvite_req_info = &pwdinfo->invitereq_info;
6145 #ifdef CONFIG_CONCURRENT_MODE
6146         _adapter                                        *pbuddy_adapter = padapter->pbuddy_adapter;
6147         struct mlme_priv                        *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
6148         struct mlme_ext_priv            *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
6149 #endif // CONFIG_CONCURRENT_MODE
6150
6151 #ifdef CONFIG_WFD
6152         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
6153 #endif // CONFIG_WFD
6154         
6155         //      Commented by Albert 20120328
6156         //      The input data is 0 or 1
6157         //      0: disable persistent group functionality
6158         //      1: enable persistent group founctionality
6159         
6160         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
6161
6162         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
6163         {
6164                 DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
6165                 return ret;
6166         }
6167         else
6168         {
6169                 if ( extra[ 0 ] == '0' )        //      Disable the persistent group function.
6170                 {
6171                         pwdinfo->persistent_supported = _FALSE;
6172                 }
6173                 else if ( extra[ 0 ] == '1' )   //      Enable the persistent group function.
6174                 {
6175                         pwdinfo->persistent_supported = _TRUE;
6176                 }
6177                 else
6178                 {
6179                         pwdinfo->persistent_supported = _FALSE;
6180                 }
6181         }
6182         printk( "[%s] persistent_supported = %d\n", __FUNCTION__, pwdinfo->persistent_supported );
6183         
6184 exit:
6185         
6186         return ret;
6187                 
6188 }
6189
6190 static int hexstr2bin(const char *hex, u8 *buf, size_t len)
6191 {
6192         size_t i;
6193         int a;
6194         const char *ipos = hex;
6195         u8 *opos = buf;
6196
6197         for (i = 0; i < len; i++) {
6198                 a = hex2byte_i(ipos);
6199                 if (a < 0)
6200                         return -1;
6201                 *opos++ = a;
6202                 ipos += 2;
6203         }
6204         return 0;
6205 }
6206
6207 static int uuid_str2bin(const char *str, u8 *bin)
6208 {
6209         const char *pos;
6210         u8 *opos;
6211
6212         pos = str;
6213         opos = bin;
6214
6215         if (hexstr2bin(pos, opos, 4))
6216                 return -1;
6217         pos += 8;
6218         opos += 4;
6219
6220         if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
6221                 return -1;
6222         pos += 4;
6223         opos += 2;
6224
6225         if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
6226                 return -1;
6227         pos += 4;
6228         opos += 2;
6229
6230         if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
6231                 return -1;
6232         pos += 4;
6233         opos += 2;
6234
6235         if (*pos++ != '-' || hexstr2bin(pos, opos, 6))
6236                 return -1;
6237
6238         return 0;
6239 }
6240
6241 static int rtw_p2p_set_wps_uuid(struct net_device *dev,
6242         struct iw_request_info *info,
6243         union iwreq_data *wrqu, char *extra)
6244 {
6245
6246         int ret = 0;
6247         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);
6248         struct wifidirect_info                  *pwdinfo = &(padapter->wdinfo);
6249
6250         DBG_871X("[%s] data = %s\n", __FUNCTION__, extra);
6251
6252         if ((36 == strlen(extra)) && (uuid_str2bin(extra, pwdinfo->uuid) == 0)) 
6253         {
6254                 pwdinfo->external_uuid = 1;
6255         } else {
6256                 pwdinfo->external_uuid = 0;
6257                 ret = -EINVAL;
6258         }
6259
6260         return ret;
6261
6262 }
6263 #ifdef CONFIG_WFD
6264 static int rtw_p2p_set_pc(struct net_device *dev,
6265                                struct iw_request_info *info,
6266                                union iwreq_data *wrqu, char *extra)
6267 {
6268         
6269         int ret = 0;    
6270         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);   
6271         struct iw_point                 *pdata = &wrqu->data;
6272         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
6273         u8                                      peerMAC[ ETH_ALEN ] = { 0x00 };
6274         int                                     jj,kk;
6275         u8                                      peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
6276         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
6277         _list                                   *plist, *phead;
6278         _queue                          *queue  = &(pmlmepriv->scanned_queue);
6279         struct  wlan_network    *pnetwork = NULL;
6280         u8                                      attr_content[50] = { 0x00 }, _status = 0;
6281         u8 *p2pie;
6282         uint                                    p2pielen = 0, attr_contentlen = 0;
6283         _irqL                           irqL;
6284         uint                                    uintPeerChannel = 0;
6285 #ifdef CONFIG_CONCURRENT_MODE
6286         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
6287         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
6288 #endif // CONFIG_CONCURRENT_MODE        
6289         
6290         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
6291         
6292         //      Commented by Albert 20120512
6293         //      1. Input information is the MAC address which wants to know the Preferred Connection bit (PC bit)
6294         //      Format: 00:E0:4C:00:00:05
6295
6296         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
6297
6298         if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
6299         {
6300                 DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
6301                 return ret;
6302         }
6303         
6304         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
6305         {
6306                 peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
6307         }
6308
6309         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6310
6311         phead = get_list_head(queue);
6312         plist = get_next(phead);
6313        
6314         while(1)
6315         {
6316                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
6317                         break;
6318
6319                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
6320
6321                 //      Commented by Albert 2011/05/18
6322                 //      Match the device address located in the P2P IE
6323                 //      This is for the case that the P2P device address is not the same as the P2P interface address.
6324
6325                 if ( (p2pie=rtw_get_p2p_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &p2pielen, pnetwork->network.Reserved[0])))
6326                 {
6327                         //      The P2P Device ID attribute is included in the Beacon frame.
6328                         //      The P2P Device Info attribute is included in the probe response frame.
6329                         printk( "[%s] Got P2P IE\n", __FUNCTION__ );
6330                         if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
6331                         {
6332                                 //      Handle the P2P Device ID attribute of Beacon first
6333                                 printk( "[%s] P2P_ATTR_DEVICE_ID \n", __FUNCTION__ );
6334                                 if ( _rtw_memcmp( attr_content, peerMAC, ETH_ALEN ) )
6335                                 {
6336                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6337                                         break;
6338                                 }
6339                         }
6340                         else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
6341                         {
6342                                 //      Handle the P2P Device Info attribute of probe response
6343                                 printk( "[%s] P2P_ATTR_DEVICE_INFO \n", __FUNCTION__ );
6344                                 if ( _rtw_memcmp( attr_content, peerMAC, ETH_ALEN ) )
6345                                 {
6346                                         uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6347                                         break;
6348                                 }                                       
6349                         }
6350
6351                 }
6352
6353                 plist = get_next(plist);
6354         
6355         }
6356
6357         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6358         printk( "[%s] channel = %d\n", __FUNCTION__, uintPeerChannel );
6359
6360         if ( uintPeerChannel )
6361         {
6362                 u8      wfd_ie[ 128 ] = { 0x00 };
6363                 uint    wfd_ielen = 0;
6364                 u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0:12);
6365
6366                 if ( rtw_get_wfd_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength,  wfd_ie, &wfd_ielen, pnetwork->network.Reserved[0]) )
6367                 {
6368                         u8      wfd_devinfo[ 6 ] = { 0x00 };
6369                         uint    wfd_devlen = 6;
6370
6371                         DBG_871X( "[%s] Found WFD IE!\n", __FUNCTION__ );
6372                         if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
6373                         {
6374                                 u16     wfd_devinfo_field = 0;
6375                                 
6376                                 //      Commented by Albert 20120319
6377                                 //      The first two bytes are the WFD device information field of WFD device information subelement.
6378                                 //      In big endian format.
6379                                 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
6380                                 if ( wfd_devinfo_field & WFD_DEVINFO_PC_TDLS )
6381                                 {
6382                                         pwfd_info->wfd_pc = _TRUE;
6383                                 }
6384                                 else
6385                                 {
6386                                         pwfd_info->wfd_pc = _FALSE;
6387                                 }
6388                         }
6389                 }
6390         }       
6391         else
6392         {
6393                 DBG_871X( "[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__ );
6394         }
6395
6396 exit:
6397         
6398         return ret;
6399                 
6400 }
6401
6402 static int rtw_p2p_set_wfd_device_type(struct net_device *dev,
6403                                struct iw_request_info *info,
6404                                union iwreq_data *wrqu, char *extra)
6405 {
6406         
6407         int ret = 0;    
6408         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);   
6409         struct iw_point                         *pdata = &wrqu->data;
6410         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
6411         struct wifi_display_info                *pwfd_info = pwdinfo->wfd_info;
6412         
6413         //      Commented by Albert 20120328
6414         //      The input data is 0 or 1
6415         //      0: specify to Miracast source device
6416         //      1 or others: specify to Miracast sink device (display device)
6417         
6418         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
6419
6420         if ( extra[ 0 ] == '0' )        //      Set to Miracast source device.
6421         {
6422                 pwfd_info->wfd_device_type = WFD_DEVINFO_SOURCE;
6423         }
6424         else                                    //      Set to Miracast sink device.
6425         {
6426                 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
6427         }
6428
6429 exit:
6430         
6431         return ret;
6432                 
6433 }
6434
6435 static int rtw_p2p_set_wfd_enable(struct net_device *dev,
6436                                struct iw_request_info *info,
6437                                union iwreq_data *wrqu, char *extra)
6438 {
6439 //      Commented by Kurt 20121206
6440 //      This function is used to set wfd enabled
6441
6442         int ret = 0;    
6443         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6444         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
6445
6446         if(*extra == '0' )
6447                 pwdinfo->wfd_info->wfd_enable = _FALSE;
6448         else if(*extra == '1')
6449                 pwdinfo->wfd_info->wfd_enable = _TRUE;
6450
6451         DBG_871X( "[%s] wfd_enable = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_enable );
6452         
6453         return ret;
6454                 
6455 }
6456
6457 static int rtw_p2p_set_driver_iface(struct net_device *dev,
6458                                struct iw_request_info *info,
6459                                union iwreq_data *wrqu, char *extra)
6460 {
6461 //      Commented by Kurt 20121206
6462 //      This function is used to set driver iface is WEXT or CFG80211
6463         int ret = 0;    
6464         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6465         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
6466
6467         if(*extra == '1' )
6468         {
6469                 pwdinfo->driver_interface = DRIVER_WEXT;
6470                 DBG_871X( "[%s] driver_interface = WEXT\n", __FUNCTION__);
6471         }
6472         else if(*extra == '2')
6473         {
6474                 pwdinfo->driver_interface = DRIVER_CFG80211;
6475                 DBG_871X( "[%s] driver_interface = CFG80211\n", __FUNCTION__);
6476         }
6477         
6478         return ret;
6479                 
6480 }
6481
6482 //      To set the WFD session available to enable or disable
6483 static int rtw_p2p_set_sa(struct net_device *dev,
6484                                struct iw_request_info *info,
6485                                union iwreq_data *wrqu, char *extra)
6486 {
6487         
6488         int ret = 0;    
6489         _adapter                                        *padapter = (_adapter *)rtw_netdev_priv(dev);   
6490         struct iw_point                         *pdata = &wrqu->data;
6491         struct wifidirect_info          *pwdinfo = &( padapter->wdinfo );
6492         struct wifi_display_info                *pwfd_info = pwdinfo->wfd_info;
6493         
6494         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
6495
6496         if( 0 )
6497         {
6498                 DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
6499                 return ret;
6500         }
6501         else
6502         {
6503                 if ( extra[ 0 ] == '0' )        //      Disable the session available.
6504                 {
6505                         pwdinfo->session_available = _FALSE;
6506                 }
6507                 else if ( extra[ 0 ] == '1' )   //      Enable the session available.
6508                 {
6509                         pwdinfo->session_available = _TRUE;
6510                 }
6511                 else
6512                 {
6513                         pwdinfo->session_available = _FALSE;
6514                 }
6515         }
6516         printk( "[%s] session available = %d\n", __FUNCTION__, pwdinfo->session_available );
6517         
6518 exit:
6519         
6520         return ret;
6521                 
6522 }
6523 #endif // CONFIG_WFD
6524
6525 static int rtw_p2p_prov_disc(struct net_device *dev,
6526                                struct iw_request_info *info,
6527                                union iwreq_data *wrqu, char *extra)
6528 {
6529         int ret = 0;    
6530         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);   
6531         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
6532         u8                                      peerMAC[ ETH_ALEN ] = { 0x00 };
6533         int                                     jj,kk;
6534         u8                                      peerMACStr[ ETH_ALEN * 2 ] = { 0x00 };
6535         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
6536         _list                                   *plist, *phead;
6537         _queue                          *queue  = &(pmlmepriv->scanned_queue);
6538         struct  wlan_network    *pnetwork = NULL;
6539         uint                                    uintPeerChannel = 0;
6540         u8                                      attr_content[100] = { 0x00 }, _status = 0;
6541         u8 *p2pie;
6542         uint                                    p2pielen = 0, attr_contentlen = 0;
6543         _irqL                           irqL;
6544         u8                                      ie_offset = 12;
6545 #ifdef CONFIG_CONCURRENT_MODE
6546         _adapter                                *pbuddy_adapter = padapter->pbuddy_adapter;
6547         struct mlme_priv                *pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
6548         struct mlme_ext_priv    *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
6549 #endif // CONFIG_CONCURRENT_MODE        
6550 #ifdef CONFIG_WFD
6551         struct wifi_display_info*       pwfd_info = pwdinfo->wfd_info;
6552 #endif // CONFIG_WFD
6553
6554         //      Commented by Albert 20110301
6555         //      The input data contains two informations.
6556         //      1. First information is the MAC address which wants to issue the provisioning discovery request frame.
6557         //      2. Second information is the WPS configuration method which wants to discovery
6558         //      Format: 00:E0:4C:00:00:05_display
6559         //      Format: 00:E0:4C:00:00:05_keypad
6560         //      Format: 00:E0:4C:00:00:05_pbc
6561         //      Format: 00:E0:4C:00:00:05_label
6562
6563         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
6564
6565         if ( pwdinfo->p2p_state == P2P_STATE_NONE )
6566         {
6567                 DBG_871X( "[%s] WiFi Direct is disable!\n", __FUNCTION__ );
6568                 return ret;
6569         }
6570         else
6571         {
6572 #ifdef CONFIG_INTEL_WIDI
6573                 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
6574                         DBG_871X( "[%s] WiFi is under survey!\n", __FUNCTION__ );
6575                         return ret;
6576                 }
6577 #endif //CONFIG_INTEL_WIDI
6578
6579                 //      Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request.
6580                 _rtw_memset( pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN );
6581                 _rtw_memset( pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN );
6582                 _rtw_memset( &pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof( NDIS_802_11_SSID ) );              
6583                 pwdinfo->tx_prov_disc_info.peer_channel_num[ 0 ] = 0;
6584                 pwdinfo->tx_prov_disc_info.peer_channel_num[ 1 ] = 0;
6585                 pwdinfo->tx_prov_disc_info.benable = _FALSE;
6586         }
6587         
6588         for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
6589         {
6590                 peerMAC[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
6591         }
6592
6593         if ( _rtw_memcmp( &extra[ 18 ], "display", 7 ) )
6594         {
6595                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
6596         }
6597         else if ( _rtw_memcmp( &extra[ 18 ], "keypad", 7 ) )
6598         {
6599                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
6600         }
6601         else if ( _rtw_memcmp( &extra[ 18 ], "pbc", 3 ) )
6602         {
6603                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
6604         }
6605         else if ( _rtw_memcmp( &extra[ 18 ], "label", 5 ) )
6606         {
6607                 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
6608         }
6609         else
6610         {
6611                 DBG_871X( "[%s] Unknown WPS config methodn", __FUNCTION__ );
6612                 return( ret );
6613         }
6614
6615         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6616
6617         phead = get_list_head(queue);
6618         plist = get_next(phead);
6619        
6620         while(1)
6621         {
6622                 if (rtw_end_of_queue_search(phead,plist)== _TRUE)
6623                         break;
6624
6625                 if( uintPeerChannel != 0 )
6626                         break;
6627
6628                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
6629
6630                 //      Commented by Albert 2011/05/18
6631                 //      Match the device address located in the P2P IE
6632                 //      This is for the case that the P2P device address is not the same as the P2P interface address.
6633
6634                 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);
6635                 if ( (p2pie=rtw_get_p2p_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &p2pielen, pnetwork->network.Reserved[0])))
6636                 {
6637                         while ( p2pie )
6638                         {
6639                                 //      The P2P Device ID attribute is included in the Beacon frame.
6640                                 //      The P2P Device Info attribute is included in the probe response frame.
6641
6642                                 if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen) )
6643                                 {
6644                                         //      Handle the P2P Device ID attribute of Beacon first
6645                                         if ( _rtw_memcmp( attr_content, peerMAC, ETH_ALEN ) )
6646                                         {
6647                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6648                                                 break;
6649                                         }
6650                                 }
6651                                 else if ( rtw_get_p2p_attr_content( p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen) )
6652                                 {
6653                                         //      Handle the P2P Device Info attribute of probe response
6654                                         if ( _rtw_memcmp( attr_content, peerMAC, ETH_ALEN ) )
6655                                         {
6656                                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6657                                                 break;
6658                                         }                                       
6659                                 }
6660
6661                                 //Get the next P2P IE
6662                                 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - ie_offset -(p2pie -&pnetwork->network.IEs[ie_offset] + p2pielen), NULL, &p2pielen);
6663                         }
6664
6665                 }
6666
6667 #ifdef CONFIG_INTEL_WIDI
6668                 // Some Intel WiDi source may not provide P2P IE, 
6669                 // so we could only compare mac addr by 802.11 Source Address
6670                 if( pmlmepriv->widi_state == INTEL_WIDI_STATE_WFD_CONNECTION 
6671                         && uintPeerChannel == 0 )
6672                 {
6673                         if ( _rtw_memcmp( pnetwork->network.MacAddress, peerMAC, ETH_ALEN ) )
6674                         {
6675                                 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
6676                                 break;
6677                         }
6678                 }
6679 #endif //CONFIG_INTEL_WIDI
6680
6681                 plist = get_next(plist);
6682         
6683         }
6684
6685         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6686
6687         if ( uintPeerChannel )
6688         {
6689 #ifdef CONFIG_WFD
6690                 {
6691                         u8      wfd_ie[ 128 ] = { 0x00 };
6692                         uint    wfd_ielen = 0;
6693                         
6694                         if ( rtw_get_wfd_ie_from_scan_queue( &pnetwork->network.IEs[0], pnetwork->network.IELength,  wfd_ie, &wfd_ielen, pnetwork->network.Reserved[0]) )
6695                         {
6696                                 u8      wfd_devinfo[ 6 ] = { 0x00 };
6697                                 uint    wfd_devlen = 6;
6698
6699                                 DBG_871X( "[%s] Found WFD IE!\n", __FUNCTION__ );
6700                                 if ( rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, wfd_devinfo, &wfd_devlen ) )
6701                                 {
6702                                         u16     wfd_devinfo_field = 0;
6703                                         
6704                                         //      Commented by Albert 20120319
6705                                         //      The first two bytes are the WFD device information field of WFD device information subelement.
6706                                         //      In big endian format.
6707                                         wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
6708                                         if ( wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL )
6709                                         {
6710                                                 pwfd_info->peer_session_avail = _TRUE;
6711                                         }
6712                                         else
6713                                         {
6714                                                 pwfd_info->peer_session_avail = _FALSE;
6715                                         }
6716                                 }
6717                         }
6718                         
6719                         if ( _FALSE == pwfd_info->peer_session_avail )
6720                         {
6721                                 DBG_871X( "[%s] WFD Session not avaiable!\n", __FUNCTION__ );
6722                                 goto exit;
6723                         }
6724                 }
6725 #endif // CONFIG_WFD
6726                 
6727                 DBG_871X( "[%s] peer channel: %d!\n", __FUNCTION__, uintPeerChannel );
6728 #ifdef CONFIG_CONCURRENT_MODE
6729                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
6730                 {
6731                         _cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
6732                 }
6733 #endif // CONFIG_CONCURRENT_MODE
6734                 _rtw_memcpy( pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN );
6735                 _rtw_memcpy( pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN );
6736                 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = ( u16 ) uintPeerChannel;
6737                 pwdinfo->tx_prov_disc_info.benable = _TRUE;
6738                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
6739                 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
6740
6741                 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
6742                 {
6743                         _rtw_memcpy( &pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof( NDIS_802_11_SSID ) );
6744                 }
6745                 else if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
6746                 {
6747                         _rtw_memcpy( pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN );
6748                         pwdinfo->tx_prov_disc_info.ssid.SsidLength= P2P_WILDCARD_SSID_LEN;
6749                 }
6750
6751 #ifdef CONFIG_CONCURRENT_MODE
6752                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
6753                 {
6754                         //      Have to enter the power saving with the AP
6755                         set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
6756                         
6757                         issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
6758                 }
6759                 else
6760                 {
6761                         set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
6762                 }
6763 #else
6764                 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
6765 #endif
6766
6767                 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
6768                 
6769 #ifdef CONFIG_CONCURRENT_MODE
6770                 if ( check_fwstate( pbuddy_mlmepriv, _FW_LINKED ) )
6771                 {
6772                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_PROVISION_TIMEOUT );
6773                 }
6774                 else
6775                 {
6776                         _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
6777                 }
6778 #else
6779                 _set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
6780 #endif // CONFIG_CONCURRENT_MODE                
6781                 
6782         }
6783         else
6784         {
6785                 DBG_871X( "[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__ );
6786 #ifdef CONFIG_INTEL_WIDI
6787                 _cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
6788                 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
6789                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
6790                 rtw_free_network_queue(padapter, _TRUE);                
6791                 _enter_critical_bh(&pmlmepriv->lock, &irqL);                            
6792                 rtw_sitesurvey_cmd(padapter, NULL, 0, NULL, 0);
6793                 _exit_critical_bh(&pmlmepriv->lock, &irqL);
6794 #endif //CONFIG_INTEL_WIDI
6795         }
6796 exit:
6797         
6798         return ret;
6799                 
6800 }
6801
6802 //      Added by Albert 20110328
6803 //      This function is used to inform the driver the user had specified the pin code value or pbc
6804 //      to application.
6805
6806 static int rtw_p2p_got_wpsinfo(struct net_device *dev,
6807                                struct iw_request_info *info,
6808                                union iwreq_data *wrqu, char *extra)
6809 {
6810         
6811         int ret = 0;    
6812         _adapter                                *padapter = (_adapter *)rtw_netdev_priv(dev);   
6813         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
6814         
6815
6816         DBG_871X( "[%s] data = %s\n", __FUNCTION__, extra );
6817         //      Added by Albert 20110328
6818         //      if the input data is P2P_NO_WPSINFO -> reset the wpsinfo
6819         //      if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device.
6820         //      if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself.
6821         //      if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC
6822         
6823         if ( *extra == '0' )
6824         {
6825                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
6826         }
6827         else if ( *extra == '1' )
6828         {
6829                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
6830         }
6831         else if ( *extra == '2' )
6832         {
6833                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
6834         }
6835         else if ( *extra == '3' )
6836         {
6837                 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
6838         }
6839         else
6840         {
6841                 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
6842         }
6843         
6844         return ret;
6845                 
6846 }
6847
6848 #endif //CONFIG_P2P
6849
6850 static int rtw_p2p_set(struct net_device *dev,
6851                                struct iw_request_info *info,
6852                                union iwreq_data *wrqu, char *extra)
6853 {
6854         
6855         int ret = 0;
6856 #ifdef CONFIG_P2P
6857
6858         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6859         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    
6860         struct iw_point *pdata = &wrqu->data;
6861         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
6862         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6863
6864         DBG_871X( "[%s] extra = %s\n", __FUNCTION__, extra );
6865
6866         if ( _rtw_memcmp( extra, "enable=", 7 ) )
6867         {
6868                 rtw_wext_p2p_enable( dev, info, wrqu, &extra[7] );
6869         }
6870         else if ( _rtw_memcmp( extra, "setDN=", 6 ) )
6871         {
6872                 wrqu->data.length -= 6;
6873                 rtw_p2p_setDN( dev, info, wrqu, &extra[6] );
6874         }
6875         else if ( _rtw_memcmp( extra, "profilefound=", 13 ) )
6876         {
6877                 wrqu->data.length -= 13;
6878                 rtw_p2p_profilefound( dev, info, wrqu, &extra[13] );
6879         }
6880         else if ( _rtw_memcmp( extra, "prov_disc=", 10 ) )
6881         {
6882                 wrqu->data.length -= 10;
6883                 rtw_p2p_prov_disc( dev, info, wrqu, &extra[10] );
6884         }
6885         else if ( _rtw_memcmp( extra, "nego=", 5 ) )
6886         {
6887                 wrqu->data.length -= 5;
6888                 rtw_p2p_connect( dev, info, wrqu, &extra[5] );
6889         }
6890         else if ( _rtw_memcmp( extra, "intent=", 7 ) )
6891         {
6892                 //      Commented by Albert 2011/03/23
6893                 //      The wrqu->data.length will include the null character
6894                 //      So, we will decrease 7 + 1
6895                 wrqu->data.length -= 8;
6896                 rtw_p2p_set_intent( dev, info, wrqu, &extra[7] );
6897         }
6898         else if ( _rtw_memcmp( extra, "ssid=", 5 ) )
6899         {
6900                 wrqu->data.length -= 5;
6901                 rtw_p2p_set_go_nego_ssid( dev, info, wrqu, &extra[5] );
6902         }
6903         else if ( _rtw_memcmp( extra, "got_wpsinfo=", 12 ) )
6904         {
6905                 wrqu->data.length -= 12;
6906                 rtw_p2p_got_wpsinfo( dev, info, wrqu, &extra[12] );
6907         }
6908         else if ( _rtw_memcmp( extra, "listen_ch=", 10 ) )
6909         {
6910                 //      Commented by Albert 2011/05/24
6911                 //      The wrqu->data.length will include the null character
6912                 //      So, we will decrease (10 + 1)   
6913                 wrqu->data.length -= 11;
6914                 rtw_p2p_set_listen_ch( dev, info, wrqu, &extra[10] );
6915         }
6916         else if ( _rtw_memcmp( extra, "op_ch=", 6 ) )
6917         {
6918                 //      Commented by Albert 2011/05/24
6919                 //      The wrqu->data.length will include the null character
6920                 //      So, we will decrease (6 + 1)    
6921                 wrqu->data.length -= 7;
6922                 rtw_p2p_set_op_ch( dev, info, wrqu, &extra[6] );
6923         }
6924         else if ( _rtw_memcmp( extra, "invite=", 7 ) )
6925         {
6926                 wrqu->data.length -= 8;
6927                 rtw_p2p_invite_req( dev, info, wrqu, &extra[7] );
6928         }
6929         else if ( _rtw_memcmp( extra, "persistent=", 11 ) )
6930         {
6931                 wrqu->data.length -= 11;
6932                 rtw_p2p_set_persistent( dev, info, wrqu, &extra[11] );
6933         }
6934         else if ( _rtw_memcmp ( extra, "uuid=", 5) )
6935         {
6936                 wrqu->data.length -= 5;
6937                 ret = rtw_p2p_set_wps_uuid( dev, info, wrqu, &extra[5] );
6938         }
6939 #ifdef CONFIG_WFD
6940         else if ( _rtw_memcmp( extra, "sa=", 3 ) )
6941         {
6942                 //      sa: WFD Session Available information
6943                 wrqu->data.length -= 3;
6944                 rtw_p2p_set_sa( dev, info, wrqu, &extra[3] );
6945         }
6946         else if ( _rtw_memcmp( extra, "pc=", 3 ) )
6947         {
6948                 //      pc: WFD Preferred Connection
6949                 wrqu->data.length -= 3;
6950                 rtw_p2p_set_pc( dev, info, wrqu, &extra[3] );
6951         }
6952         else if ( _rtw_memcmp( extra, "wfd_type=", 9 ) )
6953         {
6954                 //      pc: WFD Preferred Connection
6955                 wrqu->data.length -= 9;
6956                 rtw_p2p_set_wfd_device_type( dev, info, wrqu, &extra[9] );
6957         }
6958         else if ( _rtw_memcmp( extra, "wfd_enable=", 11 ) )
6959         {
6960                 wrqu->data.length -= 11;
6961                 rtw_p2p_set_wfd_enable( dev, info, wrqu, &extra[11] );
6962         }
6963         else if ( _rtw_memcmp( extra, "driver_iface=", 13 ) )
6964         {
6965                 wrqu->data.length -= 13;
6966                 rtw_p2p_set_driver_iface( dev, info, wrqu, &extra[13] );
6967         }
6968 #endif //CONFIG_WFD
6969
6970 #endif //CONFIG_P2P
6971
6972         return ret;
6973                 
6974 }
6975
6976 static int rtw_p2p_get(struct net_device *dev,
6977                                struct iw_request_info *info,
6978                                union iwreq_data *wrqu, char *extra)
6979 {
6980         
6981         int ret = 0;    
6982         
6983 #ifdef CONFIG_P2P
6984
6985         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6986         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    
6987         struct iw_point *pdata = &wrqu->data;
6988         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
6989         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6990
6991         if ( padapter->bShowGetP2PState )
6992         {
6993                 DBG_871X( "[%s] extra = %s\n", __FUNCTION__, (char*) wrqu->data.pointer );
6994         }
6995
6996         if ( _rtw_memcmp( wrqu->data.pointer, "status", 6 ) )
6997         {
6998                 rtw_p2p_get_status( dev, info, wrqu, extra );
6999         }
7000         else if ( _rtw_memcmp( wrqu->data.pointer, "role", 4 ) )
7001         {
7002                 rtw_p2p_get_role( dev, info, wrqu, extra);
7003         }
7004         else if ( _rtw_memcmp( wrqu->data.pointer, "peer_ifa", 8 ) )
7005         {
7006                 rtw_p2p_get_peer_ifaddr( dev, info, wrqu, extra);
7007         }
7008         else if ( _rtw_memcmp( wrqu->data.pointer, "req_cm", 6 ) )
7009         {
7010                 rtw_p2p_get_req_cm( dev, info, wrqu, extra);
7011         }
7012         else if ( _rtw_memcmp( wrqu->data.pointer, "peer_deva", 9 ) )
7013         {
7014                 //      Get the P2P device address when receiving the provision discovery request frame.
7015                 rtw_p2p_get_peer_devaddr( dev, info, wrqu, extra);
7016         }
7017         else if ( _rtw_memcmp( wrqu->data.pointer, "group_id", 8 ) )
7018         {
7019                 rtw_p2p_get_groupid( dev, info, wrqu, extra);
7020         }
7021         else if ( _rtw_memcmp( wrqu->data.pointer, "inv_peer_deva", 13 ) )
7022         {
7023                 //      Get the P2P device address when receiving the P2P Invitation request frame.
7024                 rtw_p2p_get_peer_devaddr_by_invitation( dev, info, wrqu, extra);
7025         }
7026         else if ( _rtw_memcmp( wrqu->data.pointer, "op_ch", 5 ) )
7027         {
7028                 rtw_p2p_get_op_ch( dev, info, wrqu, extra);
7029         }
7030 #ifdef CONFIG_WFD
7031         else if ( _rtw_memcmp( wrqu->data.pointer, "peer_port", 9 ) )
7032         {
7033                 rtw_p2p_get_peer_wfd_port( dev, info, wrqu, extra );
7034         }
7035         else if ( _rtw_memcmp( wrqu->data.pointer, "wfd_sa", 6 ) )
7036         {
7037                 rtw_p2p_get_peer_wfd_session_available( dev, info, wrqu, extra );
7038         }
7039         else if ( _rtw_memcmp( wrqu->data.pointer, "wfd_pc", 6 ) )
7040         {
7041                 rtw_p2p_get_peer_wfd_preferred_connection( dev, info, wrqu, extra );
7042         }
7043 #endif // CONFIG_WFD    
7044         
7045 #endif //CONFIG_P2P
7046
7047         return ret;
7048                 
7049 }
7050
7051 static int rtw_p2p_get2(struct net_device *dev,
7052                                                 struct iw_request_info *info,
7053                                                 union iwreq_data *wrqu, char *extra)
7054 {
7055
7056         int ret = 0;
7057
7058 #ifdef CONFIG_P2P
7059
7060         int length = wrqu->data.length;
7061         char *buffer = (u8 *)rtw_malloc(length);
7062
7063         if (buffer == NULL)
7064         {
7065                 ret = -ENOMEM;
7066                 goto bad;
7067         }
7068
7069         if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length))
7070         {
7071                 ret = -EFAULT;
7072                 goto bad;
7073         }
7074
7075         DBG_871X("[%s] buffer = %s\n", __FUNCTION__, buffer);
7076
7077         if (_rtw_memcmp(buffer, "wpsCM=", 6))
7078         {
7079                 ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, extra, &buffer[6]);
7080         } else if (_rtw_memcmp(buffer, "devN=", 5))
7081         {
7082                 ret = rtw_p2p_get_device_name(dev, info, wrqu, extra, &buffer[5]);
7083         } else if (_rtw_memcmp(buffer, "dev_type=", 9))
7084         {
7085                 ret = rtw_p2p_get_device_type(dev, info, wrqu, extra, &buffer[9]);
7086         } else if (_rtw_memcmp(buffer, "go_devadd=", 10))
7087         {
7088                 ret = rtw_p2p_get_go_device_address(dev, info, wrqu, extra, &buffer[10]);
7089         } else if (_rtw_memcmp(buffer, "InvProc=", 8))
7090         {
7091                 ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, extra, &buffer[8]);
7092         } else
7093         {
7094                 snprintf(extra, sizeof("Command not found."), "Command not found.");
7095                 wrqu->data.length = strlen(extra);
7096         }
7097
7098 bad:
7099         if (buffer)
7100         {
7101                 rtw_mfree(buffer, length);
7102         }
7103
7104 #endif //CONFIG_P2P
7105
7106         return ret;
7107
7108 }
7109
7110 static int rtw_cta_test_start(struct net_device *dev,
7111                                                            struct iw_request_info *info,
7112                                                            union iwreq_data *wrqu, char *extra)
7113 {
7114         int ret = 0;
7115         _adapter        *padapter = (_adapter *)rtw_netdev_priv(dev);
7116         DBG_871X("%s %s\n", __func__, extra);
7117         if (!strcmp(extra, "1"))
7118                 padapter->in_cta_test = 1;
7119         else
7120                 padapter->in_cta_test = 0;
7121
7122         if(padapter->in_cta_test)
7123         {
7124                 u32 v = rtw_read32(padapter, REG_RCR);
7125                 v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN );//| RCR_ADF
7126                 rtw_write32(padapter, REG_RCR, v);
7127                 DBG_871X("enable RCR_ADF\n");
7128         }
7129         else
7130         {
7131                 u32 v = rtw_read32(padapter, REG_RCR);
7132                 v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN ;//| RCR_ADF
7133                 rtw_write32(padapter, REG_RCR, v);
7134                 DBG_871X("disable RCR_ADF\n");
7135         }
7136         return ret;
7137 }
7138
7139
7140 extern int rtw_change_ifname(_adapter *padapter, const char *ifname);
7141 static int rtw_rereg_nd_name(struct net_device *dev,
7142                                struct iw_request_info *info,
7143                                union iwreq_data *wrqu, char *extra)
7144 {
7145         int ret = 0;    
7146         _adapter *padapter = rtw_netdev_priv(dev);
7147         struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
7148         char new_ifname[IFNAMSIZ];
7149
7150         if(rereg_priv->old_ifname[0] == 0) {
7151                 char *reg_ifname;
7152 #ifdef CONFIG_CONCURRENT_MODE 
7153                 if (padapter->isprimary)
7154                         reg_ifname = padapter->registrypriv.ifname;
7155                 else
7156 #endif
7157                 reg_ifname = padapter->registrypriv.if2name;
7158
7159                 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
7160                 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
7161         }
7162
7163         //DBG_871X("%s wrqu->data.length:%d\n", __FUNCTION__, wrqu->data.length);
7164         if(wrqu->data.length > IFNAMSIZ)
7165                 return -EFAULT;
7166
7167         if ( copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ) ) {
7168                 return -EFAULT;
7169         }
7170
7171         if( 0 == strcmp(rereg_priv->old_ifname, new_ifname) ) {
7172                 return ret;
7173         }
7174
7175         DBG_871X("%s new_ifname:%s\n", __FUNCTION__, new_ifname);
7176         if( 0 != (ret = rtw_change_ifname(padapter, new_ifname)) ) {
7177                 goto exit;
7178         }
7179
7180         if(_rtw_memcmp(rereg_priv->old_ifname, "disable%d", 9) == _TRUE) {
7181                 padapter->ledpriv.bRegUseLed= rereg_priv->old_bRegUseLed;
7182                 rtw_hal_sw_led_init(padapter);
7183                 //rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
7184         }
7185
7186         strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
7187         rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
7188         
7189         if(_rtw_memcmp(new_ifname, "disable%d", 9) == _TRUE) {
7190
7191                 DBG_871X("%s disable\n", __FUNCTION__);
7192                 // free network queue for Android's timming issue
7193                 rtw_free_network_queue(padapter, _TRUE);
7194                 
7195                 // close led
7196                 rtw_led_control(padapter, LED_CTL_POWER_OFF);
7197                 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
7198                 padapter->ledpriv.bRegUseLed= _FALSE;
7199                 rtw_hal_sw_led_deinit(padapter);
7200                 
7201                 // the interface is being "disabled", we can do deeper IPS
7202                 //rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
7203                 //rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
7204         }
7205 exit:
7206         return ret;
7207
7208 }
7209
7210 #ifdef CONFIG_IOL
7211 #include <rtw_iol.h>
7212 #endif
7213
7214 #ifdef DBG_CMD_QUEUE
7215 u8 dump_cmd_id=0;
7216 #endif
7217 static int rtw_dbg_port(struct net_device *dev,
7218                                struct iw_request_info *info,
7219                                union iwreq_data *wrqu, char *extra)
7220 {       
7221         _irqL irqL;
7222         int ret = 0;
7223         u8 major_cmd, minor_cmd;
7224         u16 arg;
7225         u32 extra_arg, *pdata, val32;
7226         struct sta_info *psta;                                          
7227         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7228         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7229         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7230         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7231         struct security_priv *psecuritypriv = &padapter->securitypriv;
7232         struct wlan_network *cur_network = &(pmlmepriv->cur_network);
7233         struct sta_priv *pstapriv = &padapter->stapriv;
7234         
7235
7236         pdata = (u32*)&wrqu->data;      
7237
7238         val32 = *pdata;
7239         arg = (u16)(val32&0x0000ffff);
7240         major_cmd = (u8)(val32>>24);
7241         minor_cmd = (u8)((val32>>16)&0x00ff);
7242
7243         extra_arg = *(pdata+1);
7244         
7245         switch(major_cmd)
7246         {
7247                 case 0x70://read_reg
7248                         switch(minor_cmd)
7249                         {
7250                                 case 1:
7251                                         DBG_871X("rtw_read8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
7252                                         break;
7253                                 case 2:
7254                                         DBG_871X("rtw_read16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
7255                                         break;
7256                                 case 4:
7257                                         DBG_871X("rtw_read32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
7258                                         break;
7259                         }                       
7260                         break;
7261                 case 0x71://write_reg
7262                         switch(minor_cmd)
7263                         {
7264                                 case 1:
7265                                         rtw_write8(padapter, arg, extra_arg);
7266                                         DBG_871X("rtw_write8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
7267                                         break;
7268                                 case 2:
7269                                         rtw_write16(padapter, arg, extra_arg);
7270                                         DBG_871X("rtw_write16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
7271                                         break;
7272                                 case 4:
7273                                         rtw_write32(padapter, arg, extra_arg);
7274                                         DBG_871X("rtw_write32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
7275                                         break;
7276                         }                       
7277                         break;
7278                 case 0x72://read_bb
7279                         DBG_871X("read_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
7280                         break;
7281                 case 0x73://write_bb
7282                         rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
7283                         DBG_871X("write_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
7284                         break;
7285                 case 0x74://read_rf
7286                         DBG_871X("read RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n",minor_cmd,arg,rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));       
7287                         break;
7288                 case 0x75://write_rf
7289                         rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
7290                         DBG_871X("write RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n",minor_cmd,arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
7291                         break;  
7292
7293                 case 0x76:
7294                         switch(minor_cmd)
7295                         {
7296                                 case 0x00: //normal mode, 
7297                                         padapter->recvpriv.is_signal_dbg = 0;
7298                                         break;
7299                                 case 0x01: //dbg mode
7300                                         padapter->recvpriv.is_signal_dbg = 1;
7301                                         extra_arg = extra_arg>100?100:extra_arg;
7302                                         padapter->recvpriv.signal_strength_dbg=extra_arg;
7303                                         break;
7304                         }
7305                         break;
7306                 case 0x78: //IOL test
7307                         switch(minor_cmd)
7308                         {
7309                                 #ifdef CONFIG_IOL
7310                                 case 0x04: //LLT table initialization test
7311                                 {
7312                                         u8 page_boundary = 0xf9;
7313                                         {
7314                                                 struct xmit_frame       *xmit_frame;
7315
7316                                                 if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
7317                                                         ret = -ENOMEM;  
7318                                                         break;
7319                                                 }
7320                                                 
7321                                                 rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
7322
7323
7324                                                 if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500,0) )
7325                                                         ret = -EPERM;
7326                                         }
7327                                 }
7328                                         break;
7329                                 case 0x05: //blink LED test
7330                                 {
7331                                         u16 reg = 0x4c;
7332                                         u32 blink_num = 50;
7333                                         u32 blink_delay_ms = 200;
7334                                         int i;
7335                                         
7336                                         {
7337                                                 struct xmit_frame       *xmit_frame;
7338
7339                                                 if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
7340                                                         ret = -ENOMEM;  
7341                                                         break;
7342                                                 }
7343
7344                                                 for(i=0;i<blink_num;i++){
7345                                                         #ifdef CONFIG_IOL_NEW_GENERATION
7346                                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00,0xff);
7347                                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
7348                                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08,0xff);
7349                                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
7350                                                         #else
7351                                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00);
7352                                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
7353                                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08);
7354                                                         rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
7355                                                         #endif
7356                                                 }
7357                                                 if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200,0) )
7358                                                         ret = -EPERM;
7359                                         }
7360                                 }
7361                                         break;
7362                                         
7363                                 case 0x06: //continuous wirte byte test
7364                                 {
7365                                         u16 reg = arg;
7366                                         u16 start_value = 0;
7367                                         u32 write_num = extra_arg;
7368                                         int i;
7369                                         u8 final;
7370                                         
7371                                         {
7372                                                 struct xmit_frame       *xmit_frame;
7373
7374                                                 if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
7375                                                         ret = -ENOMEM;  
7376                                                         break;
7377                                                 }
7378
7379                                                 for(i=0;i<write_num;i++){
7380                                                         #ifdef CONFIG_IOL_NEW_GENERATION
7381                                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value,0xFF);
7382                                                         #else
7383                                                         rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value);
7384                                                         #endif
7385                                                 }
7386                                                 if(_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000,0))
7387                                                         ret = -EPERM;
7388                                         }
7389
7390                                         if(start_value+write_num-1 == (final=rtw_read8(padapter, reg)) ) {
7391                                                 DBG_871X("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
7392                                         } else {
7393                                                 DBG_871X("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
7394                                         }
7395                                 }
7396                                         break;
7397                                         
7398                                 case 0x07: //continuous wirte word test
7399                                 {
7400                                         u16 reg = arg;
7401                                         u16 start_value = 200;
7402                                         u32 write_num = extra_arg;
7403                                 
7404                                         int i;
7405                                         u16 final;
7406
7407                                         {
7408                                                 struct xmit_frame       *xmit_frame;
7409
7410                                                 if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
7411                                                         ret = -ENOMEM;  
7412                                                         break;
7413                                                 }
7414
7415                                                 for(i=0;i<write_num;i++){
7416                                                         #ifdef CONFIG_IOL_NEW_GENERATION
7417                                                         rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value,0xFFFF);
7418                                                         #else
7419                                                         rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value);
7420                                                         #endif
7421                                                 }
7422                                                 if(_SUCCESS !=rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000,0))
7423                                                         ret = -EPERM;
7424                                         }
7425
7426                                         if(start_value+write_num-1 == (final=rtw_read16(padapter, reg)) ) {
7427                                                 DBG_871X("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
7428                                         } else {
7429                                                 DBG_871X("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
7430                                         }
7431                                 }
7432                                         break;
7433                                         
7434                                 case 0x08: //continuous wirte dword test
7435                                 {
7436                                         u16 reg = arg;
7437                                         u32 start_value = 0x110000c7;
7438                                         u32 write_num = extra_arg;
7439                                 
7440                                         int i;
7441                                         u32 final;
7442
7443                                         {
7444                                                 struct xmit_frame       *xmit_frame;
7445
7446                                                 if((xmit_frame=rtw_IOL_accquire_xmit_frame(padapter)) == NULL) {
7447                                                         ret = -ENOMEM;  
7448                                                         break;
7449                                                 }
7450
7451                                                 for(i=0;i<write_num;i++){
7452                                                         #ifdef CONFIG_IOL_NEW_GENERATION
7453                                                         rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value,0xFFFFFFFF);
7454                                                         #else
7455                                                         rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value);
7456                                                         #endif
7457                                                 }
7458                                                 if(_SUCCESS !=rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000,0))
7459                                                         ret = -EPERM;
7460                                                         
7461                                         }
7462
7463                                         if(start_value+write_num-1 == (final=rtw_read32(padapter, reg)) ) {
7464                                                 DBG_871X("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
7465                                         } else {
7466                                                 DBG_871X("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
7467                                         }
7468                                 }
7469                                         break;
7470                                 #endif //CONFIG_IOL
7471                         }
7472                         break;
7473                 case 0x79:
7474                         {
7475                                 /*
7476                                 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
7477                                 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
7478                                 */
7479                                 u8 value =  extra_arg & 0x0f;
7480                                 u8 sign = minor_cmd;
7481                                 u16 write_value = 0;
7482
7483                                 DBG_871X("%s set RESP_TXAGC to %s %u\n", __func__, sign?"minus":"plus", value);
7484
7485                                 if (sign)
7486                                         value = value | 0x10;
7487
7488                                 write_value = value | (value << 5);
7489                                 rtw_write16(padapter, 0x6d9, write_value);
7490                         }
7491                         break;
7492                 case 0x7a:
7493                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress
7494                                 , WLAN_REASON_EXPIRATION_CHK);
7495                         break;
7496                 case 0x7F:
7497                         switch(minor_cmd)
7498                         {
7499                                 case 0x0:
7500                                         DBG_871X("fwstate=0x%x\n", get_fwstate(pmlmepriv));
7501                                         break;
7502                                 case 0x01:
7503                                         DBG_871X("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", 
7504                                                 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
7505                                                 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
7506                                         break;
7507                                 case 0x02:
7508                                         DBG_871X("pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
7509                                         DBG_871X("DrvBcnEarly=%d\n", pmlmeext->DrvBcnEarly);
7510                                         DBG_871X("DrvBcnTimeOut=%d\n", pmlmeext->DrvBcnTimeOut);
7511                                         break;
7512                                 case 0x03:
7513                                         DBG_871X("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
7514 #ifdef CONFIG_80211N_HT
7515                                         DBG_871X("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
7516 #endif //CONFIG_80211N_HT
7517                                         break;
7518                                 case 0x04:
7519                                         DBG_871X("cur_ch=%d\n", pmlmeext->cur_channel);
7520                                         DBG_871X("cur_bw=%d\n", pmlmeext->cur_bwmode);
7521                                         DBG_871X("cur_ch_off=%d\n", pmlmeext->cur_ch_offset);
7522
7523                                         DBG_871X("oper_ch=%d\n", rtw_get_oper_ch(padapter));
7524                                         DBG_871X("oper_bw=%d\n", rtw_get_oper_bw(padapter));
7525                                         DBG_871X("oper_ch_offet=%d\n", rtw_get_oper_choffset(padapter));
7526                                 
7527                                         break;
7528                                 case 0x05:
7529                                         psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
7530                                         if(psta)
7531                                         {
7532                                                 DBG_871X("SSID=%s\n", cur_network->network.Ssid.Ssid);
7533                                                 DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
7534                                                 DBG_871X("cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
7535                                                 DBG_871X("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
7536                                                 DBG_871X("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
7537 #ifdef CONFIG_80211N_HT
7538                                                 DBG_871X("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
7539                                                 DBG_871X("bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
7540                                                 DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);     
7541                                                 DBG_871X("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
7542 #endif //CONFIG_80211N_HT
7543
7544                                                 sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
7545                                         }
7546                                         else
7547                                         {                                                       
7548                                                 DBG_871X("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
7549                                         }                                       
7550                                         break;
7551                                 case 0x06:
7552                                         {                                               
7553                                         }
7554                                         break;
7555                                 case 0x07:
7556                                         DBG_871X("bSurpriseRemoved=%d, bDriverStopped=%d\n", 
7557                                                 padapter->bSurpriseRemoved, padapter->bDriverStopped);
7558                                         break;
7559                                 case 0x08:
7560                                         {
7561                                                 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7562                                                 struct recv_priv  *precvpriv = &padapter->recvpriv;
7563                                                 
7564                                                 DBG_871X("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d"
7565                                                         ", free_xmit_extbuf_cnt=%d, free_xframe_ext_cnt=%d"
7566                                                         ", free_recvframe_cnt=%d\n",
7567                                                         pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt,
7568                                                         pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt,
7569                                                         precvpriv->free_recvframe_cnt);
7570                                                 #ifdef CONFIG_USB_HCI
7571                                                 DBG_871X("rx_urb_pending_cn=%d\n", ATOMIC_READ(&(precvpriv->rx_pending_cnt)));
7572                                                 #endif
7573                                         }
7574                                         break;  
7575                                 case 0x09:
7576                                         {
7577                                                 int i;
7578                                                 _list   *plist, *phead;
7579                                                 
7580 #ifdef CONFIG_AP_MODE
7581                                                 DBG_871X("sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
7582 #endif                                          
7583                                                 _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
7584
7585                                                 for(i=0; i< NUM_STA; i++)
7586                                                 {
7587                                                         phead = &(pstapriv->sta_hash[i]);
7588                                                         plist = get_next(phead);
7589                 
7590                                                         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
7591                                                         {
7592                                                                 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
7593
7594                                                                 plist = get_next(plist);
7595
7596                                                                 if(extra_arg == psta->aid)
7597                                                                 {
7598                                                                         DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
7599                                                                         DBG_871X("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
7600                                                                         DBG_871X("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
7601 #ifdef CONFIG_80211N_HT
7602                                                                         DBG_871X("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);     
7603                                                                         DBG_871X("bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
7604                                                                         DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);                                                                     
7605                                                                         DBG_871X("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
7606 #endif //CONFIG_80211N_HT
7607                                                                         
7608 #ifdef CONFIG_AP_MODE
7609                                                                         DBG_871X("capability=0x%x\n", psta->capability);
7610                                                                         DBG_871X("flags=0x%x\n", psta->flags);
7611                                                                         DBG_871X("wpa_psk=0x%x\n", psta->wpa_psk);
7612                                                                         DBG_871X("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
7613                                                                         DBG_871X("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
7614                                                                         DBG_871X("qos_info=0x%x\n", psta->qos_info);
7615 #endif
7616                                                                         DBG_871X("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
7617
7618                                                                         sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
7619                                                                 }                                                       
7620                         
7621                                                         }
7622                                                 }
7623         
7624                                                 _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
7625
7626                                         }
7627                                         break;
7628                                 case 0x0a:
7629                                         {
7630                                                 int max_mac_id = 0;
7631                                                 max_mac_id = rtw_search_max_mac_id( padapter);
7632                                                 printk("%s ==> max_mac_id = %d \n",__FUNCTION__,max_mac_id);
7633                                         }       
7634                                         break;
7635                                 case 0x0b: //Enable=1, Disable=0 driver control vrtl_carrier_sense.
7636                                         {
7637                                                 //u8 driver_vcs_en; //Enable=1, Disable=0 driver control vrtl_carrier_sense.
7638                                                 //u8 driver_vcs_type;//force 0:disable VCS, 1:RTS-CTS, 2:CTS-to-self when vcs_en=1.
7639
7640                                                 if(arg == 0){
7641                                                         DBG_871X("disable driver ctrl vcs\n");                                          
7642                                                         padapter->driver_vcs_en = 0;                                    
7643                                                 }
7644                                                 else if(arg == 1){                                                      
7645                                                         DBG_871X("enable driver ctrl vcs = %d\n", extra_arg);
7646                                                         padapter->driver_vcs_en = 1;
7647         
7648                                                         if(extra_arg>2)
7649                                                                 padapter->driver_vcs_type = 1;                                          
7650                                                         else
7651                                                                 padapter->driver_vcs_type = extra_arg;
7652                                                 }
7653                                         }
7654                                         break;
7655                                 case 0x0c://dump rx/tx packet
7656                                         {
7657                                                 if(arg == 0){
7658                                                         DBG_871X("dump rx packet (%d)\n",extra_arg);                                            
7659                                                         //pHalData->bDumpRxPkt =extra_arg;                                              
7660                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
7661                                                 }
7662                                                 else if(arg==1){
7663                                                         DBG_871X("dump tx packet (%d)\n",extra_arg);                                            
7664                                                         rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
7665                                                 }
7666                                         }
7667                                         break;
7668 #if 0                           
7669                                 case 0x0d://dump cam
7670                                         {
7671                                                 //u8 entry = (u8) extra_arg;
7672                                                 u8 entry=0;
7673                                                 //dump cam
7674                                                 for(entry=0;entry<32;entry++)
7675                                                         read_cam(padapter,entry);
7676                                         }                               
7677                                         break;
7678 #endif
7679                                 case 0x0e:
7680                                         {
7681                                                 if(arg == 0){
7682                                                         DBG_871X("disable driver ctrl rx_ampdu_factor\n");                                              
7683                                                         padapter->driver_rx_ampdu_factor = 0xFF;
7684                                                 }
7685                                                 else if(arg == 1){
7686                                                         
7687                                                         DBG_871X("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg);       
7688         
7689                                                         if(extra_arg > 0x03)
7690                                                                 padapter->driver_rx_ampdu_factor = 0xFF;                                                
7691                                                         else
7692                                                                 padapter->driver_rx_ampdu_factor = extra_arg;
7693                                                 }                                       
7694                                         }
7695                                         break;
7696                 #ifdef DBG_CONFIG_ERROR_DETECT
7697                                 case 0x0f:
7698                                                 {
7699                                                         if(extra_arg == 0){     
7700                                                                 DBG_871X("###### silent reset test.......#####\n");
7701                                                                 rtw_hal_sreset_reset(padapter);                                         
7702                                                         } else {
7703                                                                 HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
7704                                                                 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
7705                                                                 psrtpriv->dbg_trigger_point = extra_arg;
7706                                                         }
7707                                                         
7708                                                 }
7709                                         break;
7710                                 case 0x15:
7711                                         {
7712                                                 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
7713                                                 DBG_871X("==>silent resete cnts:%d\n",pwrpriv->ips_enter_cnts);
7714                                         }
7715                                         break;  
7716                                         
7717                 #endif  
7718
7719                                 case 0x10:// driver version display
7720                                         dump_drv_version(RTW_DBGDUMP);
7721                                         break;
7722                                 case 0x11://dump linked status
7723                                         {
7724                                                 int pre_mode;
7725                                                 pre_mode=padapter->bLinkInfoDump;
7726                                                 // linked_info_dump(padapter,extra_arg);
7727                                                  if(extra_arg==1 || (extra_arg==0 && pre_mode==1) ) //not consider pwr_saving 0:
7728                                                 {
7729                                                         padapter->bLinkInfoDump = extra_arg;    
7730                 
7731                                                 }
7732                                                 else if( (extra_arg==2 ) || (extra_arg==0 && pre_mode==2))//consider power_saving
7733                                                 {               
7734                                                 //DBG_871X("linked_info_dump =%s \n", (padapter->bLinkInfoDump)?"enable":"disable")
7735                                                         linked_info_dump(padapter,extra_arg);   
7736                                                 }
7737
7738
7739                                                  
7740                                         }                                       
7741                                         break;
7742 #ifdef CONFIG_80211N_HT
7743                                 case 0x12: //set rx_stbc
7744                                 {
7745                                         struct registry_priv    *pregpriv = &padapter->registrypriv;
7746                                         // 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g
7747                                         //default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
7748                                         if( pregpriv && (extra_arg == 0 || extra_arg == 1|| extra_arg == 2 || extra_arg == 3))
7749                                         {
7750                                                 pregpriv->rx_stbc= extra_arg;
7751                                                 DBG_871X("set rx_stbc=%d\n",pregpriv->rx_stbc);
7752                                         }
7753                                         else
7754                                                 DBG_871X("get rx_stbc=%d\n",pregpriv->rx_stbc);
7755                                         
7756                                 }
7757                                 break;
7758                                 case 0x13: //set ampdu_enable
7759                                 {
7760                                         struct registry_priv    *pregpriv = &padapter->registrypriv;
7761                                         // 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec)
7762                                         if( pregpriv && extra_arg < 3 )
7763                                         {
7764                                                 pregpriv->ampdu_enable= extra_arg;
7765                                                 DBG_871X("set ampdu_enable=%d\n",pregpriv->ampdu_enable);
7766                                         }
7767                                         else
7768                                                 DBG_871X("get ampdu_enable=%d\n",pregpriv->ampdu_enable);
7769                                         
7770                                 }
7771                                 break;
7772 #endif
7773                                 case 0x14: //get wifi_spec
7774                                 {
7775                                         struct registry_priv    *pregpriv = &padapter->registrypriv;
7776                                         DBG_871X("get wifi_spec=%d\n",pregpriv->wifi_spec);
7777                                         
7778                                 }
7779                                 break;
7780                                 case 0x16:
7781                                 {
7782                                         if(arg == 0xff){
7783                                                 rtw_odm_dbg_comp_msg(RTW_DBGDUMP,padapter);
7784                                         }
7785                                         else{
7786                                                 u64 dbg_comp = (u64)extra_arg;
7787                                                 rtw_odm_dbg_comp_set(padapter, dbg_comp);
7788                                         }
7789                                 }
7790                                         break;
7791 #ifdef DBG_FIXED_CHAN
7792                                 case 0x17:
7793                                         {
7794                                                 struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);                                           
7795                                                 printk("===>  Fixed channel to %d \n",extra_arg);
7796                                                 pmlmeext->fixed_chan = extra_arg;       
7797                                                 
7798                                         }
7799                                         break;
7800 #endif
7801                                 case 0x18:
7802                                         {
7803                                                 printk("===>  Switch USB Mode %d \n",extra_arg);
7804                                                 rtw_hal_set_hwreg(padapter, HW_VAR_USB_MODE, (u8 *)&extra_arg);
7805                                         }
7806                                         break;
7807 #ifdef CONFIG_80211N_HT                 
7808                                 case 0x19:
7809                                         {
7810                                                 struct registry_priv    *pregistrypriv = &padapter->registrypriv;
7811                                                 // extra_arg :
7812                                                 // BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, 
7813                                                 // BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx
7814                                                 if(arg == 0){
7815                                                         DBG_871X("driver disable LDPC\n");                                              
7816                                                         pregistrypriv->ldpc_cap = 0x00;
7817                                                 }
7818                                                 else if(arg == 1){                                                      
7819                                                         DBG_871X("driver set LDPC cap = 0x%x\n", extra_arg);
7820                                                         pregistrypriv->ldpc_cap = (u8)(extra_arg&0x33);                                         
7821                                                 }                                               
7822                                         }
7823                                         break;
7824                                 case 0x1a:
7825                                         {
7826                                                 struct registry_priv    *pregistrypriv = &padapter->registrypriv;
7827                                                 // extra_arg :
7828                                                 // BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, 
7829                                                 // BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx
7830                                                 if(arg == 0){
7831                                                         DBG_871X("driver disable STBC\n");                                              
7832                                                         pregistrypriv->stbc_cap = 0x00;
7833                                                 }
7834                                                 else if(arg == 1){                                                      
7835                                                         DBG_871X("driver set STBC cap = 0x%x\n", extra_arg);
7836                                                         pregistrypriv->stbc_cap = (u8)(extra_arg&0x33);                                         
7837                                                 }                                               
7838                                         }
7839                                         break;
7840 #endif //CONFIG_80211N_HT
7841                                 case 0x1b:
7842                                         {       
7843                                                 struct registry_priv    *pregistrypriv = &padapter->registrypriv;
7844                                                 
7845                                                 if(arg == 0){
7846                                                         DBG_871X("disable driver ctrl max_rx_rate, reset to default_rate_set\n");                                                       
7847                                                         init_mlme_default_rate_set(padapter);
7848 #ifdef CONFIG_80211N_HT                                         
7849                                                         pregistrypriv->ht_enable = (u8)rtw_ht_enable;
7850 #endif //CONFIG_80211N_HT
7851                                                 }
7852                                                 else if(arg == 1){
7853
7854                                                         int i;
7855                                                         u8 max_rx_rate;                                         
7856                                                         
7857                                                         DBG_871X("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg); 
7858
7859                                                         max_rx_rate = (u8)extra_arg;
7860
7861                                                         if(max_rx_rate < 0xc) // max_rx_rate < MSC0 -> B or G -> disable HT
7862                                                         {
7863 #ifdef CONFIG_80211N_HT                                         
7864                                                                 pregistrypriv->ht_enable = 0;
7865 #endif //CONFIG_80211N_HT
7866                                                                 for(i=0; i<NumRates; i++)
7867                                                                 {
7868                                                                         if(pmlmeext->datarate[i] > max_rx_rate)
7869                                                                                 pmlmeext->datarate[i] = 0xff;                                                                   
7870                                                                 }       
7871
7872                                                         }
7873 #ifdef CONFIG_80211N_HT 
7874                                                         else if(max_rx_rate < 0x1c) // mcs0~mcs15
7875                                                         {
7876                                                                 u32 mcs_bitmap=0x0;
7877                                                                                                         
7878                                                                 for(i=0; i<((max_rx_rate+1)-0xc); i++)
7879                                                                         mcs_bitmap |= BIT(i);
7880                                                                 
7881                                                                 set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
7882                                                         }
7883 #endif //CONFIG_80211N_HT                                                       
7884                                                 }                                                                                       
7885                                         }
7886                                         break;
7887                                 case 0x1c: //enable/disable driver control AMPDU Density for peer sta's rx
7888                                         {
7889                                                 if(arg == 0){
7890                                                         DBG_871X("disable driver ctrl ampdu density\n");                                                
7891                                                         padapter->driver_ampdu_spacing = 0xFF;
7892                                                 }
7893                                                 else if(arg == 1){
7894                                                         
7895                                                         DBG_871X("enable driver ctrl ampdu density = %d\n", extra_arg); 
7896         
7897                                                         if(extra_arg > 0x07)
7898                                                                 padapter->driver_ampdu_spacing = 0xFF;                                          
7899                                                         else
7900                                                                 padapter->driver_ampdu_spacing = extra_arg;
7901                                                 }
7902                                         }
7903                                         break;
7904 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
7905                                 case 0x1e:
7906                                         {
7907                                                 HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
7908                                                 PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
7909                                                 u8 chan = rtw_get_oper_ch(padapter);
7910                                                 DBG_871X("===========================================\n");
7911                                                 ODM_InbandNoise_Monitor(pDM_Odm,_TRUE,0x1e,100);
7912                                                 DBG_871X("channel(%d),noise_a = %d, noise_b = %d , noise_all:%d \n", 
7913                                                         chan,pDM_Odm->noise_level.noise[ODM_RF_PATH_A], 
7914                                                         pDM_Odm->noise_level.noise[ODM_RF_PATH_B],
7915                                                         pDM_Odm->noise_level.noise_all);
7916                                                 DBG_871X("===========================================\n");
7917                                                 
7918                                         }
7919                                         break;
7920 #endif
7921                                 case 0x23:
7922                                         {
7923                                                 DBG_871X("turn %s the bNotifyChannelChange Variable\n",(extra_arg==1)?"on":"off");
7924                                                 padapter->bNotifyChannelChange = extra_arg;
7925                                                 break;
7926                                         }
7927                                 case 0x24:
7928                                         {
7929 #ifdef CONFIG_P2P
7930                                                 DBG_871X("turn %s the bShowGetP2PState Variable\n",(extra_arg==1)?"on":"off");
7931                                                 padapter->bShowGetP2PState = extra_arg;
7932 #endif // CONFIG_P2P
7933                                                 break;                                          
7934                                         }
7935 #ifdef CONFIG_GPIO_API              
7936                             case 0x25: //Get GPIO register
7937                                     {
7938                                             /*
7939                                             * dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7
7940                                             */                
7941                               
7942                                             u8 value;
7943                                             DBG_871X("Read GPIO Value  extra_arg = %d\n",extra_arg);
7944                                             value = rtw_hal_get_gpio(padapter,extra_arg);
7945                                             DBG_871X("Read GPIO Value = %d\n",value);                                        
7946                                             break;
7947                                     }
7948                             case 0x26: //Set GPIO direction
7949                                     {
7950                                                                                 
7951                                             /* dbg 0x7f26000x [y], Set gpio direction, 
7952                                             * x: gpio_num,4~7  y: indicate direction, 0~1  
7953                                             */ 
7954                                         
7955                                             int value;
7956                                             DBG_871X("Set GPIO Direction! arg = %d ,extra_arg=%d\n",arg ,extra_arg);
7957                                             value = rtw_hal_config_gpio(padapter, arg, extra_arg);
7958                                             DBG_871X("Set GPIO Direction %s \n",(value==-1)?"Fail!!!":"Success");
7959                                             break;
7960                                         }
7961                                 case 0x27: //Set GPIO output direction value
7962                                         {
7963                                                 /*
7964                                                 * dbg 0x7f27000x [y], Set gpio output direction value, 
7965                                                 * x: gpio_num,4~7  y: indicate direction, 0~1  
7966                                                 */ 
7967                                         
7968                                                 int value;
7969                                                 DBG_871X("Set GPIO Value! arg = %d ,extra_arg=%d\n",arg ,extra_arg);
7970                                                 value = rtw_hal_set_gpio_output_value(padapter,arg,extra_arg);
7971                                                 DBG_871X("Set GPIO Value %s \n",(value==-1)?"Fail!!!":"Success");
7972                                                 break;
7973                                         }
7974 #endif          
7975 #ifdef DBG_CMD_QUEUE
7976                                 case 0x28:
7977                                         {
7978                                                 dump_cmd_id = extra_arg;
7979                                                 DBG_871X("dump_cmd_id:%d\n",dump_cmd_id);
7980                                         }
7981                                         break;
7982 #endif //DBG_CMD_QUEUE
7983                                 case 0xaa:
7984                                         {
7985                                                 if((extra_arg & 0x7F)> 0x3F) extra_arg = 0xFF;
7986                                                 DBG_871X("chang data rate to :0x%02x\n",extra_arg);
7987                                                 padapter->fix_rate = extra_arg;
7988                                         }
7989                                         break;  
7990                                 case 0xdd://registers dump , 0 for mac reg,1 for bb reg, 2 for rf reg
7991                                         {
7992                                                 if(extra_arg==0){
7993                                                         mac_reg_dump(RTW_DBGDUMP, padapter);
7994                                                 }
7995                                                 else if(extra_arg==1){
7996                                                         bb_reg_dump(RTW_DBGDUMP, padapter);
7997                                                 }
7998                                                 else if(extra_arg==2){
7999                                                         rf_reg_dump(RTW_DBGDUMP, padapter);
8000                                                 }
8001                                         }
8002                                         break;          
8003
8004                                 case 0xee:
8005                                         {
8006                                                 DBG_871X(" === please control /proc  to trun on/off PHYDM func === \n");
8007                                         }
8008                                         break;
8009
8010                                 case 0xfd:
8011                                         rtw_write8(padapter, 0xc50, arg);
8012                                         DBG_871X("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
8013                                         rtw_write8(padapter, 0xc58, arg);
8014                                         DBG_871X("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
8015                                         break;
8016                                 case 0xfe:
8017                                         DBG_871X("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
8018                                         DBG_871X("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
8019                                         break;
8020                                 case 0xff:
8021                                         {
8022                                                 DBG_871X("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
8023                                                 DBG_871X("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
8024                                                 DBG_871X("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
8025                                                 DBG_871X("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
8026                                                 DBG_871X("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
8027         
8028                                                 DBG_871X("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
8029
8030
8031                                                 DBG_871X("\n");
8032                 
8033                                                 DBG_871X("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
8034                                                 DBG_871X("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
8035
8036                                                 DBG_871X("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
8037         
8038                                                 DBG_871X("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
8039         
8040                                                 DBG_871X("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
8041                                                 DBG_871X("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
8042         
8043                                                 DBG_871X("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
8044                                                 DBG_871X("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
8045                                                 DBG_871X("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
8046                                                 DBG_871X("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
8047                                         }
8048                                         break;
8049                         }                       
8050                         break;
8051                 default:
8052                         DBG_871X("error dbg cmd!\n");
8053                         break;  
8054         }
8055         
8056
8057         return ret;
8058
8059 }
8060
8061 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
8062 {
8063         uint ret=0;
8064         u32 flags;
8065         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8066         
8067         switch (name){
8068         case IEEE_PARAM_WPA_ENABLED:
8069
8070                 padapter->securitypriv.dot11AuthAlgrthm= dot11AuthAlgrthm_8021X; //802.1x
8071                 
8072                 //ret = ieee80211_wpa_enable(ieee, value);
8073                 
8074                 switch((value)&0xff)
8075                 {
8076                         case 1 : //WPA
8077                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; //WPA_PSK
8078                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
8079                                 break;
8080                         case 2: //WPA2
8081                         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; //WPA2_PSK
8082                         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
8083                                 break;
8084                 }
8085                 
8086                 RT_TRACE(_module_rtl871x_ioctl_os_c,_drv_info_,("wpa_set_param:padapter->securitypriv.ndisauthtype=%d\n", padapter->securitypriv.ndisauthtype));
8087                 
8088                 break;
8089
8090         case IEEE_PARAM_TKIP_COUNTERMEASURES:
8091                 //ieee->tkip_countermeasures=value;
8092                 break;
8093
8094         case IEEE_PARAM_DROP_UNENCRYPTED: 
8095         {
8096                 /* HACK:
8097                  *
8098                  * wpa_supplicant calls set_wpa_enabled when the driver
8099                  * is loaded and unloaded, regardless of if WPA is being
8100                  * used.  No other calls are made which can be used to
8101                  * determine if encryption will be used or not prior to
8102                  * association being expected.  If encryption is not being
8103                  * used, drop_unencrypted is set to false, else true -- we
8104                  * can use this to determine if the CAP_PRIVACY_ON bit should
8105                  * be set.
8106                  */
8107                  
8108 #if 0    
8109                 struct ieee80211_security sec = {
8110                         .flags = SEC_ENABLED,
8111                         .enabled = value,
8112                 };
8113                 ieee->drop_unencrypted = value;
8114                 /* We only change SEC_LEVEL for open mode. Others
8115                  * are set by ipw_wpa_set_encryption.
8116                  */
8117                 if (!value) {
8118                         sec.flags |= SEC_LEVEL;
8119                         sec.level = SEC_LEVEL_0;
8120                 }
8121                 else {
8122                         sec.flags |= SEC_LEVEL;
8123                         sec.level = SEC_LEVEL_1;
8124                 }
8125                 if (ieee->set_security)
8126                         ieee->set_security(ieee->dev, &sec);
8127 #endif          
8128                 break;
8129
8130         }
8131         case IEEE_PARAM_PRIVACY_INVOKED:        
8132                 
8133                 //ieee->privacy_invoked=value;
8134                 
8135                 break;
8136
8137         case IEEE_PARAM_AUTH_ALGS:
8138                 
8139                 ret = wpa_set_auth_algs(dev, value);
8140                 
8141                 break;
8142
8143         case IEEE_PARAM_IEEE_802_1X:
8144                 
8145                 //ieee->ieee802_1x=value;               
8146                 
8147                 break;
8148                 
8149         case IEEE_PARAM_WPAX_SELECT:
8150                 
8151                 // added for WPA2 mixed mode
8152                 //DBG_871X(KERN_WARNING "------------------------>wpax value = %x\n", value);
8153                 /*
8154                 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
8155                 ieee->wpax_type_set = 1;
8156                 ieee->wpax_type_notify = value;
8157                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
8158                 */
8159                 
8160                 break;
8161
8162         default:                
8163
8164
8165                 
8166                 ret = -EOPNOTSUPP;
8167
8168                 
8169                 break;
8170         
8171         }
8172
8173         return ret;
8174         
8175 }
8176
8177 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
8178 {       
8179         int ret = 0;
8180         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8181
8182         switch (command)
8183         {
8184                 case IEEE_MLME_STA_DEAUTH:
8185
8186                         if(!rtw_set_802_11_disassociate(padapter))
8187                                 ret = -1;               
8188                         
8189                         break;
8190
8191                 case IEEE_MLME_STA_DISASSOC:
8192                 
8193                         if(!rtw_set_802_11_disassociate(padapter))
8194                                 ret = -1;               
8195         
8196                         break;
8197
8198                 default:
8199                         ret = -EOPNOTSUPP;
8200                         break;
8201         }
8202
8203         return ret;
8204         
8205 }
8206
8207 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
8208 {
8209         struct ieee_param *param;
8210         uint ret=0;
8211
8212         //down(&ieee->wx_sem);  
8213
8214         if (p->length < sizeof(struct ieee_param) || !p->pointer){
8215                 ret = -EINVAL;
8216                 goto out;
8217         }
8218         
8219         param = (struct ieee_param *)rtw_malloc(p->length);
8220         if (param == NULL)
8221         {
8222                 ret = -ENOMEM;
8223                 goto out;
8224         }
8225         
8226         if (copy_from_user(param, p->pointer, p->length))
8227         {
8228                 rtw_mfree((u8*)param, p->length);
8229                 ret = -EFAULT;
8230                 goto out;
8231         }
8232
8233         switch (param->cmd) {
8234
8235         case IEEE_CMD_SET_WPA_PARAM:
8236                 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
8237                 break;
8238
8239         case IEEE_CMD_SET_WPA_IE:
8240                 //ret = wpa_set_wpa_ie(dev, param, p->length);
8241                 ret =  rtw_set_wpa_ie((_adapter *)rtw_netdev_priv(dev), (char*)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
8242                 break;
8243
8244         case IEEE_CMD_SET_ENCRYPTION:
8245                 ret = wpa_set_encryption(dev, param, p->length);
8246                 break;
8247
8248         case IEEE_CMD_MLME:
8249                 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
8250                 break;
8251
8252         default:
8253                 DBG_871X("Unknown WPA supplicant request: %d\n", param->cmd);
8254                 ret = -EOPNOTSUPP;
8255                 break;
8256                 
8257         }
8258
8259         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
8260                 ret = -EFAULT;
8261
8262         rtw_mfree((u8 *)param, p->length);
8263         
8264 out:
8265         
8266         //up(&ieee->wx_sem);
8267         
8268         return ret;
8269         
8270 }
8271
8272 #ifdef CONFIG_AP_MODE
8273 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
8274 {
8275         int ret = 0;
8276         u32 wep_key_idx, wep_key_len,wep_total_len;
8277         NDIS_802_11_WEP  *pwep = NULL;
8278         struct sta_info *psta = NULL, *pbcmc_sta = NULL;        
8279         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8280         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
8281         struct security_priv* psecuritypriv=&(padapter->securitypriv);
8282         struct sta_priv *pstapriv = &padapter->stapriv;
8283
8284         DBG_871X("%s\n", __FUNCTION__);
8285
8286         param->u.crypt.err = 0;
8287         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
8288
8289         //sizeof(struct ieee_param) = 64 bytes;
8290         //if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
8291         if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len)
8292         {
8293                 ret =  -EINVAL;
8294                 goto exit;
8295         }
8296
8297         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8298             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8299             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
8300         {
8301                 if (param->u.crypt.idx >= WEP_KEYS)
8302                 {
8303                         ret = -EINVAL;
8304                         goto exit;
8305                 }       
8306         }
8307         else 
8308         {               
8309                 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
8310                 if(!psta)
8311                 {
8312                         //ret = -EINVAL;
8313                         DBG_871X("rtw_set_encryption(), sta has already been removed or never been added\n");
8314                         goto exit;
8315                 }                       
8316         }
8317
8318         if (strcmp(param->u.crypt.alg, "none") == 0 && (psta==NULL))
8319         {
8320                 //todo:clear default encryption keys
8321
8322                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
8323                 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
8324                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
8325                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
8326
8327                 DBG_871X("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
8328                 
8329                 goto exit;
8330         }
8331
8332
8333         if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta==NULL))
8334         {               
8335                 DBG_871X("r871x_set_encryption, crypt.alg = WEP\n");
8336                 
8337                 wep_key_idx = param->u.crypt.idx;
8338                 wep_key_len = param->u.crypt.key_len;
8339                                         
8340                 DBG_871X("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
8341
8342                 if((wep_key_idx >= WEP_KEYS) || (wep_key_len<=0))
8343                 {
8344                         ret = -EINVAL;
8345                         goto exit;
8346                 }
8347                         
8348
8349                 if (wep_key_len > 0) 
8350                 {                       
8351                         wep_key_len = wep_key_len <= 5 ? 5 : 13;
8352                         wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
8353                         pwep =(NDIS_802_11_WEP *)rtw_malloc(wep_total_len);
8354                         if(pwep == NULL){
8355                                 DBG_871X(" r871x_set_encryption: pwep allocate fail !!!\n");
8356                                 goto exit;
8357                         }
8358                         
8359                         _rtw_memset(pwep, 0, wep_total_len);
8360                 
8361                         pwep->KeyLength = wep_key_len;
8362                         pwep->Length = wep_total_len;
8363                         
8364                 }
8365                 
8366                 pwep->KeyIndex = wep_key_idx;
8367
8368                 _rtw_memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
8369
8370                 if(param->u.crypt.set_tx)
8371                 {
8372                         DBG_871X("wep, set_tx=1\n");
8373
8374                         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
8375                         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
8376                         psecuritypriv->dot11PrivacyAlgrthm=_WEP40_;
8377                         psecuritypriv->dot118021XGrpPrivacy=_WEP40_;
8378                         
8379                         if(pwep->KeyLength==13)
8380                         {
8381                                 psecuritypriv->dot11PrivacyAlgrthm=_WEP104_;
8382                                 psecuritypriv->dot118021XGrpPrivacy=_WEP104_;
8383                         }
8384
8385                 
8386                         psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
8387                         
8388                         _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
8389
8390                         psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
8391
8392                         rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
8393                 }
8394                 else
8395                 {
8396                         DBG_871X("wep, set_tx=0\n");
8397                         
8398                         //don't update "psecuritypriv->dot11PrivacyAlgrthm" and 
8399                         //"psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to cam
8400                                         
8401                       _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
8402
8403                         psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;                   
8404
8405                         rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
8406                 }
8407
8408                 goto exit;
8409                 
8410         }
8411
8412         
8413         if(!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) // //group key
8414         {
8415                 if(param->u.crypt.set_tx ==1)
8416                 {
8417                         if(strcmp(param->u.crypt.alg, "WEP") == 0)
8418                         {
8419                                 DBG_871X("%s, set group_key, WEP\n", __FUNCTION__);
8420                                 
8421                                 _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));
8422                                         
8423                                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
8424                                 if(param->u.crypt.key_len==13)
8425                                 {                                               
8426                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
8427                                 }
8428                                 
8429                         }
8430                         else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
8431                         {                                               
8432                                 DBG_871X("%s, set group_key, TKIP\n", __FUNCTION__);
8433                                 
8434                                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
8435
8436                                 _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));
8437                                 
8438                                 //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
8439                                 //set mic key
8440                                 _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
8441                                 _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
8442
8443                                 psecuritypriv->busetkipkey = _TRUE;
8444                                                                                         
8445                         }
8446                         else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
8447                         {
8448                                 DBG_871X("%s, set group_key, CCMP\n", __FUNCTION__);
8449                         
8450                                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
8451
8452                                 _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));
8453                         }
8454                         else
8455                         {
8456                                 DBG_871X("%s, set group_key, none\n", __FUNCTION__);
8457                                 
8458                                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
8459                         }
8460
8461                         psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
8462
8463                         psecuritypriv->binstallGrpkey = _TRUE;
8464
8465                         psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!
8466                                                                 
8467                         rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
8468                         
8469                         pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
8470                         if(pbcmc_sta)
8471                         {
8472                                 pbcmc_sta->ieee8021x_blocked = _FALSE;
8473                                 pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy                     
8474                         }       
8475                                                 
8476                 }
8477
8478                 goto exit;
8479                 
8480         }       
8481
8482         if(psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) // psk/802_1x
8483         {
8484                 if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
8485                 {
8486                         if(param->u.crypt.set_tx ==1)
8487                         { 
8488                                 _rtw_memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
8489                                 
8490                                 if(strcmp(param->u.crypt.alg, "WEP") == 0)
8491                                 {
8492                                         DBG_871X("%s, set pairwise key, WEP\n", __FUNCTION__);
8493                                         
8494                                         psta->dot118021XPrivacy = _WEP40_;
8495                                         if(param->u.crypt.key_len==13)
8496                                         {                                               
8497                                                 psta->dot118021XPrivacy = _WEP104_;
8498                                         }
8499                                 }
8500                                 else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
8501                                 {                                               
8502                                         DBG_871X("%s, set pairwise key, TKIP\n", __FUNCTION__);
8503                                         
8504                                         psta->dot118021XPrivacy = _TKIP_;
8505                                 
8506                                         //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
8507                                         //set mic key
8508                                         _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
8509                                         _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
8510
8511                                         psecuritypriv->busetkipkey = _TRUE;
8512                                                                                         
8513                                 }
8514                                 else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
8515                                 {
8516
8517                                         DBG_871X("%s, set pairwise key, CCMP\n", __FUNCTION__);
8518                                         
8519                                         psta->dot118021XPrivacy = _AES_;
8520                                 }
8521                                 else
8522                                 {
8523                                         DBG_871X("%s, set pairwise key, none\n", __FUNCTION__);
8524                                         
8525                                         psta->dot118021XPrivacy = _NO_PRIVACY_;
8526                                 }
8527                                                 
8528                                 rtw_ap_set_pairwise_key(padapter, psta);
8529                                         
8530                                 psta->ieee8021x_blocked = _FALSE;
8531                                         
8532                         }                       
8533                         else//group key???
8534                         { 
8535                                 if(strcmp(param->u.crypt.alg, "WEP") == 0)
8536                                 {
8537                                         _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));
8538                                         
8539                                         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
8540                                         if(param->u.crypt.key_len==13)
8541                                         {                                               
8542                                                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
8543                                         }
8544                                 }
8545                                 else if(strcmp(param->u.crypt.alg, "TKIP") == 0)
8546                                 {                                               
8547                                         psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
8548
8549                                         _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));
8550                                 
8551                                         //DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len);
8552                                         //set mic key
8553                                         _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
8554                                         _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
8555
8556                                         psecuritypriv->busetkipkey = _TRUE;
8557                                                                                         
8558                                 }
8559                                 else if(strcmp(param->u.crypt.alg, "CCMP") == 0)
8560                                 {
8561                                         psecuritypriv->dot118021XGrpPrivacy = _AES_;
8562
8563                                         _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));
8564                                 }
8565                                 else
8566                                 {
8567                                         psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
8568                                 }
8569
8570                                 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
8571
8572                                 psecuritypriv->binstallGrpkey = _TRUE;  
8573                                                                 
8574                                 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;//!!!
8575                                                                 
8576                                 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
8577                         
8578                                 pbcmc_sta=rtw_get_bcmc_stainfo(padapter);
8579                                 if(pbcmc_sta)
8580                                 {
8581                                         pbcmc_sta->ieee8021x_blocked = _FALSE;
8582                                         pbcmc_sta->dot118021XPrivacy= psecuritypriv->dot118021XGrpPrivacy;//rx will use bmc_sta's dot118021XPrivacy                     
8583                                 }                                       
8584
8585                         }
8586                         
8587                 }
8588                                 
8589         }
8590
8591 exit:
8592
8593         if(pwep)
8594         {
8595                 rtw_mfree((u8 *)pwep, wep_total_len);           
8596         }       
8597         
8598         return ret;
8599         
8600 }
8601
8602 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
8603 {
8604         int ret=0;      
8605         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8606         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8607         struct sta_priv *pstapriv = &padapter->stapriv;
8608         unsigned char *pbuf = param->u.bcn_ie.buf;
8609
8610
8611         DBG_871X("%s, len=%d\n", __FUNCTION__, len);
8612
8613         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8614                 return -EINVAL;
8615
8616         _rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
8617
8618         if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0))
8619                 pstapriv->max_num_sta = NUM_STA;
8620
8621
8622         if(rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)// 12 = param header, 2:no packed
8623                 ret = 0;
8624         else
8625                 ret = -EINVAL;
8626         
8627
8628         return ret;
8629         
8630 }
8631
8632 static int rtw_hostapd_sta_flush(struct net_device *dev)
8633 {
8634         //_irqL irqL;
8635         //_list *phead, *plist;
8636         int ret=0;      
8637         //struct sta_info *psta = NULL;
8638         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
8639         //struct sta_priv *pstapriv = &padapter->stapriv;
8640
8641         DBG_871X("%s\n", __FUNCTION__);
8642
8643         flush_all_cam_entry(padapter);  //clear CAM
8644
8645         ret = rtw_sta_flush(padapter);  
8646
8647         return ret;
8648
8649 }
8650
8651 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
8652 {
8653         _irqL irqL;
8654         int ret=0;      
8655         struct sta_info *psta = NULL;
8656         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8657         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8658         struct sta_priv *pstapriv = &padapter->stapriv;
8659
8660         DBG_871X("rtw_add_sta(aid=%d)=" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
8661         
8662         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)       
8663         {
8664                 return -EINVAL;         
8665         }
8666
8667         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8668             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8669             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
8670         {
8671                 return -EINVAL; 
8672         }
8673
8674 /*
8675         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
8676         if(psta)
8677         {
8678                 DBG_871X("rtw_add_sta(), free has been added psta=%p\n", psta);
8679                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                
8680                 rtw_free_stainfo(padapter,  psta);              
8681                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
8682
8683                 psta = NULL;
8684         }       
8685 */
8686         //psta = rtw_alloc_stainfo(pstapriv, param->sta_addr);
8687         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
8688         if(psta)
8689         {
8690                 int flags = param->u.add_sta.flags;                     
8691                 
8692                 //DBG_871X("rtw_add_sta(), init sta's variables, psta=%p\n", psta);
8693                 
8694                 psta->aid = param->u.add_sta.aid;//aid=1~2007
8695
8696                 _rtw_memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
8697                 
8698                 
8699                 //check wmm cap.
8700                 if(WLAN_STA_WME&flags)
8701                         psta->qos_option = 1;
8702                 else
8703                         psta->qos_option = 0;
8704
8705                 if(pmlmepriv->qospriv.qos_option == 0)  
8706                         psta->qos_option = 0;
8707
8708                 
8709 #ifdef CONFIG_80211N_HT         
8710                 //chec 802.11n ht cap.
8711                 if(WLAN_STA_HT&flags)
8712                 {
8713                         psta->htpriv.ht_option = _TRUE;
8714                         psta->qos_option = 1;
8715                         _rtw_memcpy((void*)&psta->htpriv.ht_cap, (void*)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
8716                 }
8717                 else            
8718                 {
8719                         psta->htpriv.ht_option = _FALSE;
8720                 }
8721                 
8722                 if(pmlmepriv->htpriv.ht_option == _FALSE)       
8723                         psta->htpriv.ht_option = _FALSE;
8724 #endif          
8725
8726
8727                 update_sta_info_apmode(padapter, psta);
8728                 
8729                 
8730         }
8731         else
8732         {
8733                 ret = -ENOMEM;
8734         }       
8735         
8736         return ret;
8737         
8738 }
8739
8740 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
8741 {
8742         _irqL irqL;
8743         int ret=0;      
8744         struct sta_info *psta = NULL;
8745         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8746         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8747         struct sta_priv *pstapriv = &padapter->stapriv;
8748
8749         DBG_871X("rtw_del_sta=" MAC_FMT "\n", MAC_ARG(param->sta_addr));
8750                 
8751         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)               
8752         {
8753                 return -EINVAL;         
8754         }
8755
8756         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8757             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8758             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
8759         {
8760                 return -EINVAL; 
8761         }
8762
8763         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
8764         if(psta)
8765         {
8766                 u8 updated=_FALSE;
8767         
8768                 //DBG_871X("free psta=%p, aid=%d\n", psta, psta->aid);
8769
8770                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
8771                 if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
8772                 {                       
8773                         rtw_list_delete(&psta->asoc_list);
8774                         pstapriv->asoc_list_cnt--;
8775                         updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);
8776
8777                 }
8778                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
8779                 
8780                 associated_clients_update(padapter, updated);
8781         
8782                 psta = NULL;
8783                 
8784         }
8785         else
8786         {
8787                 DBG_871X("rtw_del_sta(), sta has already been removed or never been added\n");
8788                 
8789                 //ret = -1;
8790         }
8791         
8792         
8793         return ret;
8794         
8795 }
8796
8797 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
8798 {
8799         int ret=0;      
8800         struct sta_info *psta = NULL;
8801         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8802         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8803         struct sta_priv *pstapriv = &padapter->stapriv;
8804         struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
8805         struct sta_data *psta_data = (struct sta_data *)param_ex->data;
8806
8807         DBG_871X("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
8808
8809         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)               
8810         {
8811                 return -EINVAL;         
8812         }
8813
8814         if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
8815             param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
8816             param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) 
8817         {
8818                 return -EINVAL; 
8819         }
8820
8821         psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
8822         if(psta)
8823         {
8824 #if 0
8825                 struct {
8826                         u16 aid;
8827                         u16 capability;
8828                         int flags;
8829                         u32 sta_set;
8830                         u8 tx_supp_rates[16];   
8831                         u32 tx_supp_rates_len;
8832                         struct rtw_ieee80211_ht_cap ht_cap;
8833                         u64     rx_pkts;
8834                         u64     rx_bytes;
8835                         u64     rx_drops;
8836                         u64     tx_pkts;
8837                         u64     tx_bytes;
8838                         u64     tx_drops;
8839                 } get_sta;              
8840 #endif
8841                 psta_data->aid = (u16)psta->aid;
8842                 psta_data->capability = psta->capability;
8843                 psta_data->flags = psta->flags;
8844
8845 /*
8846                 nonerp_set : BIT(0)
8847                 no_short_slot_time_set : BIT(1)
8848                 no_short_preamble_set : BIT(2)
8849                 no_ht_gf_set : BIT(3)
8850                 no_ht_set : BIT(4)
8851                 ht_20mhz_set : BIT(5)
8852 */
8853
8854                 psta_data->sta_set =((psta->nonerp_set) |
8855                                                         (psta->no_short_slot_time_set <<1) |
8856                                                         (psta->no_short_preamble_set <<2) |
8857                                                         (psta->no_ht_gf_set <<3) |
8858                                                         (psta->no_ht_set <<4) |
8859                                                         (psta->ht_20mhz_set <<5));
8860
8861                 psta_data->tx_supp_rates_len =  psta->bssratelen;
8862                 _rtw_memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
8863 #ifdef CONFIG_80211N_HT
8864                 _rtw_memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
8865 #endif //CONFIG_80211N_HT
8866                 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
8867                 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
8868                 psta_data->rx_drops = psta->sta_stats.rx_drops;
8869
8870                 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
8871                 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
8872                 psta_data->tx_drops = psta->sta_stats.tx_drops;
8873                 
8874
8875         }
8876         else
8877         {
8878                 ret = -1;
8879         }
8880
8881         return ret;
8882
8883 }
8884
8885 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
8886 {
8887         int ret=0;      
8888         struct sta_info *psta = NULL;
8889         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8890         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8891         struct sta_priv *pstapriv = &padapter->stapriv;
8892
8893         DBG_871X("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
8894
8895         if(check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != _TRUE)               
8896         {
8897                 return -EINVAL;         
8898         }
8899
8900         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
8901             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
8902             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
8903         {
8904                 return -EINVAL; 
8905         }
8906
8907         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
8908         if(psta)
8909         {
8910                 if((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC))
8911                 {
8912                         int wpa_ie_len;
8913                         int copy_len;
8914
8915                         wpa_ie_len = psta->wpa_ie[1];
8916                         
8917                         copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
8918                                 
8919                         param->u.wpa_ie.len = copy_len;
8920
8921                         _rtw_memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
8922                 }
8923                 else
8924                 {
8925                         //ret = -1;
8926                         DBG_871X("sta's wpa_ie is NONE\n");
8927                 }               
8928         }
8929         else
8930         {
8931                 ret = -1;
8932         }
8933
8934         return ret;
8935
8936 }
8937
8938 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
8939 {
8940         int ret=0;
8941         unsigned char wps_oui[4]={0x0,0x50,0xf2,0x04};
8942         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
8943         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8944         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8945         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8946         int ie_len;
8947
8948         DBG_871X("%s, len=%d\n", __FUNCTION__, len);
8949
8950         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8951                 return -EINVAL;
8952
8953         ie_len = len-12-2;// 12 = param header, 2:no packed
8954
8955
8956         if(pmlmepriv->wps_beacon_ie)
8957         {
8958                 rtw_mfree(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
8959                 pmlmepriv->wps_beacon_ie = NULL;                        
8960         }       
8961
8962         if(ie_len>0)
8963         {
8964                 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
8965                 pmlmepriv->wps_beacon_ie_len = ie_len;
8966                 if ( pmlmepriv->wps_beacon_ie == NULL) {
8967                         DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
8968                         return -EINVAL;
8969                 }
8970
8971                 _rtw_memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
8972
8973                 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE);
8974                 
8975                 pmlmeext->bstart_bss = _TRUE;
8976                 
8977         }
8978         
8979         
8980         return ret;             
8981
8982 }
8983
8984 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
8985 {
8986         int ret=0;
8987         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
8988         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8989         int ie_len;
8990
8991         DBG_871X("%s, len=%d\n", __FUNCTION__, len);
8992
8993         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
8994                 return -EINVAL;
8995
8996         ie_len = len-12-2;// 12 = param header, 2:no packed
8997
8998
8999         if(pmlmepriv->wps_probe_resp_ie)
9000         {
9001                 rtw_mfree(pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
9002                 pmlmepriv->wps_probe_resp_ie = NULL;                    
9003         }       
9004
9005         if(ie_len>0)
9006         {
9007                 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
9008                 pmlmepriv->wps_probe_resp_ie_len = ie_len;
9009                 if ( pmlmepriv->wps_probe_resp_ie == NULL) {
9010                         DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
9011                         return -EINVAL;
9012                 }
9013                 _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);         
9014         }
9015         
9016         
9017         return ret;
9018
9019 }
9020
9021 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
9022 {
9023         int ret=0;
9024         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
9025         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9026         int ie_len;
9027
9028         DBG_871X("%s, len=%d\n", __FUNCTION__, len);
9029
9030         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
9031                 return -EINVAL;
9032
9033         ie_len = len-12-2;// 12 = param header, 2:no packed
9034
9035
9036         if(pmlmepriv->wps_assoc_resp_ie)
9037         {
9038                 rtw_mfree(pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
9039                 pmlmepriv->wps_assoc_resp_ie = NULL;                    
9040         }       
9041
9042         if(ie_len>0)
9043         {
9044                 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
9045                 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
9046                 if ( pmlmepriv->wps_assoc_resp_ie == NULL) {
9047                         DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
9048                         return -EINVAL;
9049                 }
9050                 
9051                 _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);         
9052         }
9053         
9054         
9055         return ret;
9056
9057 }
9058
9059 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
9060 {
9061         int ret=0;
9062         _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9063         struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
9064         struct mlme_ext_priv    *mlmeext = &(adapter->mlmeextpriv);
9065         struct mlme_ext_info    *mlmeinfo = &(mlmeext->mlmext_info);
9066         int ie_len;
9067         u8 *ssid_ie;
9068         char ssid[NDIS_802_11_LENGTH_SSID + 1];
9069         sint ssid_len = 0;
9070         u8 ignore_broadcast_ssid;
9071
9072         if(check_fwstate(mlmepriv, WIFI_AP_STATE) != _TRUE)
9073                 return -EPERM;
9074
9075         if (param->u.bcn_ie.reserved[0] != 0xea)
9076                 return -EINVAL;
9077
9078         mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
9079
9080         ie_len = len-12-2;// 12 = param header, 2:no packed
9081         ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
9082
9083         if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
9084                 WLAN_BSSID_EX *pbss_network = &mlmepriv->cur_network.network;
9085                 WLAN_BSSID_EX *pbss_network_ext = &mlmeinfo->network;
9086
9087                 _rtw_memcpy(ssid, ssid_ie+2, ssid_len);
9088                 ssid[ssid_len] = 0x0;
9089
9090                 if(0)
9091                         DBG_871X(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
9092                                 ssid, ssid_len,
9093                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
9094                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
9095
9096                 _rtw_memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
9097                 pbss_network->Ssid.SsidLength = ssid_len;
9098                 _rtw_memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
9099                 pbss_network_ext->Ssid.SsidLength = ssid_len;
9100
9101                 if(0)
9102                         DBG_871X(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
9103                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
9104                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
9105         }
9106
9107         DBG_871X(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
9108                 ignore_broadcast_ssid, ssid, ssid_len);
9109
9110         return ret;
9111 }
9112
9113 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
9114 {
9115         int ret=0;
9116         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
9117         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);    
9118
9119         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
9120                 return -EINVAL;
9121
9122         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
9123             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
9124             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
9125         {
9126                 return -EINVAL; 
9127         }
9128
9129         ret = rtw_acl_remove_sta(padapter, param->sta_addr);    
9130
9131         return ret;             
9132
9133 }
9134
9135 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
9136 {
9137         int ret=0;
9138         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
9139         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9140         
9141         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
9142                 return -EINVAL;
9143
9144         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
9145             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
9146             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) 
9147         {
9148                 return -EINVAL; 
9149         }
9150
9151         ret = rtw_acl_add_sta(padapter, param->sta_addr);       
9152
9153         return ret;             
9154
9155 }
9156
9157 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
9158 {
9159         int ret=0;
9160         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);  
9161         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9162         
9163         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
9164                 return -EINVAL; 
9165         
9166         rtw_set_macaddr_acl(padapter, param->u.mlme.command);   
9167
9168         return ret;
9169 }
9170
9171 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
9172 {
9173         struct ieee_param *param;
9174         int ret=0;
9175         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
9176
9177         //DBG_871X("%s\n", __FUNCTION__);
9178
9179         /*
9180         * this function is expect to call in master mode, which allows no power saving
9181         * so, we just check hw_init_completed
9182         */
9183
9184         if (padapter->hw_init_completed==_FALSE){
9185                 ret = -EPERM;
9186                 goto out;
9187         }
9188
9189
9190         //if (p->length < sizeof(struct ieee_param) || !p->pointer){
9191         if(!p->pointer){
9192                 ret = -EINVAL;
9193                 goto out;
9194         }
9195         
9196         param = (struct ieee_param *)rtw_malloc(p->length);
9197         if (param == NULL)
9198         {
9199                 ret = -ENOMEM;
9200                 goto out;
9201         }
9202         
9203         if (copy_from_user(param, p->pointer, p->length))
9204         {
9205                 rtw_mfree((u8*)param, p->length);
9206                 ret = -EFAULT;
9207                 goto out;
9208         }
9209
9210         //DBG_871X("%s, cmd=%d\n", __FUNCTION__, param->cmd);
9211
9212         switch (param->cmd) 
9213         {       
9214                 case RTL871X_HOSTAPD_FLUSH:
9215
9216                         ret = rtw_hostapd_sta_flush(dev);
9217
9218                         break;
9219         
9220                 case RTL871X_HOSTAPD_ADD_STA:   
9221                         
9222                         ret = rtw_add_sta(dev, param);                                  
9223                         
9224                         break;
9225
9226                 case RTL871X_HOSTAPD_REMOVE_STA:
9227
9228                         ret = rtw_del_sta(dev, param);
9229
9230                         break;
9231         
9232                 case RTL871X_HOSTAPD_SET_BEACON:
9233
9234                         ret = rtw_set_beacon(dev, param, p->length);
9235
9236                         break;
9237                         
9238                 case RTL871X_SET_ENCRYPTION:
9239
9240                         ret = rtw_set_encryption(dev, param, p->length);
9241                         
9242                         break;
9243                         
9244                 case RTL871X_HOSTAPD_GET_WPAIE_STA:
9245
9246                         ret = rtw_get_sta_wpaie(dev, param);
9247         
9248                         break;
9249                         
9250                 case RTL871X_HOSTAPD_SET_WPS_BEACON:
9251
9252                         ret = rtw_set_wps_beacon(dev, param, p->length);
9253
9254                         break;
9255
9256                 case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
9257
9258                         ret = rtw_set_wps_probe_resp(dev, param, p->length);
9259                         
9260                         break;
9261                         
9262                 case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
9263
9264                         ret = rtw_set_wps_assoc_resp(dev, param, p->length);
9265                         
9266                         break;
9267
9268                 case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
9269
9270                         ret = rtw_set_hidden_ssid(dev, param, p->length);
9271
9272                         break;
9273
9274                 case RTL871X_HOSTAPD_GET_INFO_STA:
9275
9276                         ret = rtw_ioctl_get_sta_data(dev, param, p->length);
9277
9278                         break;
9279                         
9280                 case RTL871X_HOSTAPD_SET_MACADDR_ACL:
9281
9282                         ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
9283
9284                         break;
9285
9286                 case RTL871X_HOSTAPD_ACL_ADD_STA:
9287
9288                         ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
9289
9290                         break;
9291
9292                 case RTL871X_HOSTAPD_ACL_REMOVE_STA:
9293
9294                         ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
9295
9296                         break;
9297                         
9298                 default:
9299                         DBG_871X("Unknown hostapd request: %d\n", param->cmd);
9300                         ret = -EOPNOTSUPP;
9301                         break;
9302                 
9303         }
9304
9305         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
9306                 ret = -EFAULT;
9307
9308
9309         rtw_mfree((u8 *)param, p->length);
9310         
9311 out:
9312                 
9313         return ret;
9314         
9315 }
9316 #endif
9317
9318 static int rtw_wx_set_priv(struct net_device *dev,
9319                                 struct iw_request_info *info,
9320                                 union iwreq_data *awrq,
9321                                 char *extra)
9322 {
9323
9324 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
9325         char *ext_dbg;
9326 #endif
9327
9328         int ret = 0;
9329         int len = 0;
9330         char *ext;
9331         int i;
9332
9333         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
9334         struct iw_point *dwrq = (struct iw_point*)awrq;
9335
9336         //RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n"));
9337         if(dwrq->length == 0)
9338                 return -EFAULT;
9339         
9340         len = dwrq->length;
9341         if (!(ext = rtw_vmalloc(len)))
9342                 return -ENOMEM;
9343
9344         if (copy_from_user(ext, dwrq->pointer, len)) {
9345                 rtw_vmfree(ext, len);
9346                 return -EFAULT;
9347         }
9348
9349
9350         //RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_,
9351         //       ("rtw_wx_set_priv: %s req=%s\n",
9352         //        dev->name, ext));
9353
9354         #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV     
9355         if (!(ext_dbg = rtw_vmalloc(len)))
9356         {
9357                 rtw_vmfree(ext, len);
9358                 return -ENOMEM;
9359         }       
9360         
9361         _rtw_memcpy(ext_dbg, ext, len);
9362         #endif
9363
9364         //added for wps2.0 @20110524
9365         if(dwrq->flags == 0x8766 && len > 8)
9366         {
9367                 u32 cp_sz;              
9368                 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
9369                 u8 *probereq_wpsie = ext;
9370                 int probereq_wpsie_len = len;
9371                 u8 wps_oui[4]={0x0,0x50,0xf2,0x04};             
9372         
9373                 if((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
9374                         (_rtw_memcmp(&probereq_wpsie[2], wps_oui, 4) ==_TRUE))
9375                 {
9376                         cp_sz = probereq_wpsie_len>MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN:probereq_wpsie_len;
9377
9378                         if(pmlmepriv->wps_probe_req_ie)
9379                         {
9380                                 u32 free_len = pmlmepriv->wps_probe_req_ie_len;
9381                                 pmlmepriv->wps_probe_req_ie_len = 0;
9382                                 rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
9383                                 pmlmepriv->wps_probe_req_ie = NULL;                     
9384                         }       
9385
9386                         pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
9387                         if ( pmlmepriv->wps_probe_req_ie == NULL) {
9388                                 printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
9389                                 ret =  -EINVAL;
9390                                 goto FREE_EXT;
9391                         
9392                         }
9393                         
9394                         _rtw_memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
9395                         pmlmepriv->wps_probe_req_ie_len = cp_sz;                                        
9396                         
9397                 }       
9398                 
9399                 goto FREE_EXT;
9400                 
9401         }
9402
9403         if(     len >= WEXT_CSCAN_HEADER_SIZE
9404                 && _rtw_memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
9405         ){
9406                 ret = rtw_wx_set_scan(dev, info, awrq, ext);
9407                 goto FREE_EXT;
9408         }
9409         
9410 #ifdef CONFIG_ANDROID
9411         //DBG_871X("rtw_wx_set_priv: %s req=%s\n", dev->name, ext);
9412
9413         i = rtw_android_cmdstr_to_num(ext);
9414
9415         switch(i) {
9416                 case ANDROID_WIFI_CMD_START :
9417                         indicate_wx_custom_event(padapter, "START");
9418                         break;
9419                 case ANDROID_WIFI_CMD_STOP :
9420                         indicate_wx_custom_event(padapter, "STOP");
9421                         break;
9422                 case ANDROID_WIFI_CMD_RSSI :
9423                         {
9424                                 struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);     
9425                                 struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
9426
9427                                 if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
9428                                         sprintf(ext, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
9429                                 } else {
9430                                         sprintf(ext, "OK");
9431                                 }
9432                         }
9433                         break;
9434                 case ANDROID_WIFI_CMD_LINKSPEED :
9435                         {
9436                                 u16 mbps = rtw_get_cur_max_rate(padapter)/10;
9437                                 sprintf(ext, "LINKSPEED %d", mbps);
9438                         }
9439                         break;
9440                 case ANDROID_WIFI_CMD_MACADDR :
9441                         sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
9442                         break;
9443                 case ANDROID_WIFI_CMD_SCAN_ACTIVE :
9444                         {
9445                                 //rtw_set_scan_mode(padapter, SCAN_ACTIVE);
9446                                 sprintf(ext, "OK");
9447                         }
9448                         break;
9449                 case ANDROID_WIFI_CMD_SCAN_PASSIVE :
9450                         {
9451                                 //rtw_set_scan_mode(padapter, SCAN_PASSIVE);
9452                                 sprintf(ext, "OK");
9453                         }
9454                         break;
9455
9456                 case ANDROID_WIFI_CMD_COUNTRY :
9457                         {
9458                                 char country_code[10];
9459                                 sscanf(ext, "%*s %s", country_code);
9460                                 rtw_set_country(padapter, country_code);
9461                                 sprintf(ext, "OK");
9462                         }
9463                         break;
9464                 default :
9465                         #ifdef  CONFIG_DEBUG_RTW_WX_SET_PRIV
9466                         DBG_871X("%s: %s unknowned req=%s\n", __FUNCTION__,
9467                                 dev->name, ext_dbg);
9468                         #endif
9469
9470                         sprintf(ext, "OK");
9471                 
9472         }
9473
9474         if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext)+1)) ) )
9475                 ret = -EFAULT;
9476
9477         #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
9478         DBG_871X("%s: %s req=%s rep=%s dwrq->length=%d, strlen(ext)+1=%d\n", __FUNCTION__,
9479                 dev->name, ext_dbg ,ext, dwrq->length, (u16)(strlen(ext)+1));
9480         #endif
9481 #endif //end of CONFIG_ANDROID
9482
9483
9484 FREE_EXT:
9485
9486         rtw_vmfree(ext, len);
9487         #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
9488         rtw_vmfree(ext_dbg, len);
9489         #endif
9490
9491         //DBG_871X("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret=%d\n", 
9492         //              dev->name, ret);
9493
9494         return ret;
9495         
9496 }
9497 #ifdef CONFIG_WOWLAN
9498 static int rtw_wowlan_ctrl(struct net_device *dev,
9499                                                 struct iw_request_info *info,
9500                                                 union iwreq_data *wrqu, char *extra)
9501 {
9502         _adapter *padapter =  (_adapter *)rtw_netdev_priv(dev);
9503         struct wowlan_ioctl_param poidparam;
9504         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
9505         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9506         struct net_device *pnetdev = padapter->pnetdev;
9507 #ifdef CONFIG_CONCURRENT_MODE
9508         struct net_device *pbuddy_netdev = padapter->pbuddy_adapter->pnetdev;   
9509 #endif
9510         struct sta_info *psta = NULL;
9511         int ret = 0;
9512         u32 start_time = rtw_get_current_time();
9513         poidparam.subcode = 0;
9514
9515         DBG_871X("+rtw_wowlan_ctrl: %s\n", extra);
9516         
9517         if(pwrctrlpriv->bSupportRemoteWakeup==_FALSE){
9518                 ret = -EPERM;
9519                 DBG_871X("+rtw_wowlan_ctrl: Device didn't support the remote wakeup!!\n");
9520                 goto _rtw_wowlan_ctrl_exit_free;
9521         }
9522
9523         if (!check_fwstate(pmlmepriv, _FW_LINKED) && 
9524                         check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
9525 #ifdef CONFIG_PNO_SUPPORT
9526                         pwrctrlpriv->wowlan_pno_enable = _TRUE;
9527 #else
9528                         DBG_871X("[%s] WARNING: Please Connect With AP First!!\n", __func__);
9529                         goto _rtw_wowlan_ctrl_exit_free;
9530 #endif //CONFIG_PNO_SUPPORT
9531         }
9532
9533         if (_rtw_memcmp( extra, "enable", 6 )) {
9534
9535                 padapter->registrypriv.mp_mode = 1;
9536
9537                 pwrctrlpriv->wowlan_from_cmd = _TRUE;
9538
9539                 rtw_suspend_common(padapter);
9540
9541         } else if (_rtw_memcmp( extra, "disable", 6 )) {
9542
9543                 rtw_resume_common(padapter);
9544
9545                 pwrctrlpriv->wowlan_from_cmd = _FALSE;
9546
9547 #ifdef CONFIG_PNO_SUPPORT
9548                 pwrctrlpriv->wowlan_pno_enable = _FALSE;
9549 #endif //CONFIG_PNO_SUPPORT
9550
9551                 padapter->registrypriv.mp_mode = 0;
9552         } else {
9553                 DBG_871X("[%s] Invalid Parameter.\n", __func__);
9554                 goto _rtw_wowlan_ctrl_exit_free;
9555         }
9556         //mutex_lock(&ioctl_mutex);
9557 _rtw_wowlan_ctrl_exit_free:
9558         DBG_871X("-rtw_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
9559         DBG_871X_LEVEL(_drv_always_, "%s in %d ms\n", __func__,
9560                         rtw_get_passing_time_ms(start_time));
9561 _rtw_wowlan_ctrl_exit:
9562         return ret;
9563 }
9564 #endif //CONFIG_WOWLAN
9565
9566 #ifdef CONFIG_AP_WOWLAN
9567 static int rtw_ap_wowlan_ctrl(struct net_device *dev,
9568                                                 struct iw_request_info *info,
9569                                                 union iwreq_data *wrqu, char *extra)
9570 {
9571         _adapter *padapter =  (_adapter *)rtw_netdev_priv(dev);
9572         struct wowlan_ioctl_param poidparam;
9573         struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
9574         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9575         struct sta_info *psta = NULL;
9576         int ret = 0;
9577         u32 start_time = rtw_get_current_time();
9578         poidparam.subcode = 0;
9579
9580         DBG_871X("+rtw_ap_wowlan_ctrl: %s\n", extra);
9581
9582         if(pwrctrlpriv->bSupportRemoteWakeup==_FALSE){
9583                 ret = -EPERM;
9584                 DBG_871X("+rtw_wowlan_ctrl: Device didn't support the remote wakeup!!\n");
9585                 goto _rtw_ap_wowlan_ctrl_exit_free;
9586         }
9587
9588         if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
9589                 DBG_871X("[%s] It is not AP mode!!\n", __func__);
9590                 goto _rtw_ap_wowlan_ctrl_exit_free;
9591         }
9592
9593         if (_rtw_memcmp( extra, "enable", 6 )) {
9594                 pwrctrlpriv->wowlan_ap_mode = _TRUE;
9595                 while (pwrctrlpriv->bips_processing == _TRUE)
9596                         rtw_msleep_os(1);
9597
9598                 rtw_cancel_all_timer(padapter);
9599
9600                 padapter->bDriverStopped = _TRUE;       //for stop thread
9601                 rtw_stop_drv_threads(padapter);
9602                 padapter->bDriverStopped = _FALSE;      //for 32k command
9603
9604 #ifdef CONFIG_LPS
9605                 LeaveAllPowerSaveModeDirect(padapter);
9606 #endif
9607                 rtw_hal_disable_interrupt(padapter); // It need wait for leaving 32K.
9608
9609                 // 2.1 clean interupt
9610                 rtw_hal_clear_interrupt(padapter);
9611
9612                 poidparam.subcode = WOWLAN_AP_ENABLE;
9613
9614                 rtw_hal_set_hwreg(padapter, HW_VAR_AP_WOWLAN,(u8 *)&poidparam);
9615         } else if (_rtw_memcmp( extra, "disable", 6 )) {
9616 #ifdef CONFIG_LPS
9617                 LeaveAllPowerSaveModeDirect(padapter);
9618 #endif //CONFIG_LPS
9619                 pwrctrlpriv->bFwCurrentInPSMode = _FALSE;
9620
9621                 rtw_hal_disable_interrupt(padapter);
9622
9623                 rtw_hal_clear_interrupt(padapter);
9624
9625                 poidparam.subcode = WOWLAN_AP_ENABLE;
9626
9627                 rtw_hal_set_hwreg(padapter, HW_VAR_AP_WOWLAN,(u8 *)&poidparam);
9628
9629                 pwrctrlpriv->wowlan_ap_mode = _FALSE;
9630
9631                 psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
9632                 if (psta) {
9633                         set_sta_rate(padapter, psta);
9634                 }
9635
9636                 padapter->bDriverStopped = _FALSE;
9637                 DBG_871X("%s: wowmode resuming, DriverStopped:%d\n", __func__, padapter->bDriverStopped);
9638                 rtw_start_drv_threads(padapter);
9639
9640                 rtw_hal_enable_interrupt(padapter);
9641
9642                 _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
9643                 pwrctrlpriv->bips_processing = _FALSE;
9644                 rtw_set_pwr_state_check_timer(pwrctrlpriv);
9645
9646         } else {
9647                 DBG_871X("[%s] Invalid Parameter.\n", __func__);
9648                 goto _rtw_ap_wowlan_ctrl_exit_free;
9649         }
9650         //mutex_lock(&ioctl_mutex);
9651 _rtw_ap_wowlan_ctrl_exit_free:
9652         DBG_871X("-rtw_ap_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
9653         DBG_871X_LEVEL(_drv_always_, "%s in %d ms\n", __func__,
9654                         rtw_get_passing_time_ms(start_time));
9655 _rtw_ap_wowlan_ctrl_exit:
9656         return ret;
9657 }
9658 #endif //CONFIG_AP_WOWLAN
9659
9660 static int rtw_pm_set(struct net_device *dev,
9661                                struct iw_request_info *info,
9662                                union iwreq_data *wrqu, char *extra)
9663 {
9664         int ret = 0;
9665         unsigned        mode = 0;
9666         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
9667
9668         DBG_871X( "[%s] extra = %s\n", __FUNCTION__, extra );
9669
9670         if ( _rtw_memcmp( extra, "lps=", 4 ) )
9671         {
9672                 sscanf(extra+4, "%u", &mode);   
9673                 ret = rtw_pm_set_lps(padapter,mode);
9674         }
9675         else if ( _rtw_memcmp( extra, "ips=", 4 ) )
9676         {
9677                 sscanf(extra+4, "%u", &mode);
9678                 ret = rtw_pm_set_ips(padapter,mode);
9679         }
9680         else{
9681                 ret = -EINVAL;
9682         }
9683
9684         return ret;
9685 }
9686
9687 static int rtw_mp_efuse_get(struct net_device *dev,
9688                         struct iw_request_info *info,
9689                         union iwreq_data *wdata, char *extra)
9690 {
9691         PADAPTER padapter = rtw_netdev_priv(dev);
9692         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
9693         
9694         PEFUSE_HAL pEfuseHal;
9695         struct iw_point *wrqu;
9696         
9697         u8      *PROMContent = pHalData->efuse_eeprom_data;
9698         u8 ips_mode = IPS_NUM; // init invalid value
9699         u8 lps_mode = PS_MODE_NUM; // init invalid value
9700         struct pwrctrl_priv *pwrctrlpriv ;
9701         u8 *data = NULL;
9702         u8 *rawdata = NULL;
9703         char *pch, *ptmp, *token, *tmp[3]={0x00,0x00,0x00};
9704         u16 i=0, j=0, mapLen=0, addr=0, cnts=0;
9705         u16 max_available_size=0, raw_cursize=0, raw_maxsize=0;
9706         int err;
9707         #ifdef CONFIG_IOL
9708         u8 org_fw_iol = padapter->registrypriv.fw_iol;// 0:Disable, 1:enable, 2:by usb speed
9709         #endif
9710         
9711         wrqu = (struct iw_point*)wdata;
9712         pwrctrlpriv = adapter_to_pwrctl(padapter);
9713         pEfuseHal = &pHalData->EfuseHal;
9714
9715         err = 0;
9716         data = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
9717         if (data == NULL)
9718         {
9719                 err = -ENOMEM;
9720                 goto exit;
9721         }
9722         rawdata = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
9723         if (rawdata == NULL)
9724         {
9725                 err = -ENOMEM;
9726                 goto exit;
9727         }
9728
9729         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
9730         {
9731                 err = -EFAULT;
9732                 goto exit;
9733         }
9734         #ifdef CONFIG_LPS
9735         lps_mode = pwrctrlpriv->power_mgnt;//keep org value
9736         rtw_pm_set_lps(padapter,PS_MODE_ACTIVE);
9737         #endif  
9738         
9739         #ifdef CONFIG_IPS       
9740         ips_mode = pwrctrlpriv->ips_mode;//keep org value
9741         rtw_pm_set_ips(padapter,IPS_NONE);
9742         #endif  
9743         
9744         pch = extra;
9745         DBG_871X("%s: in=%s\n", __FUNCTION__, extra);
9746
9747         i = 0;
9748         //mac 16 "00e04c871200" rmap,00,2
9749         while ((token = strsep(&pch, ",")) != NULL)
9750         {
9751                 if (i > 2) break;
9752                 tmp[i] = token;
9753                 i++;
9754         }
9755         #ifdef CONFIG_IOL
9756         padapter->registrypriv.fw_iol = 0;// 0:Disable, 1:enable, 2:by usb speed
9757         #endif
9758         
9759         if(strcmp(tmp[0], "status") == 0){
9760                 sprintf(extra, "Load File efuse=%s,Load File MAC=%s",(pHalData->bloadfile_fail_flag? "FAIL" : "OK"),(pHalData->bloadmac_fail_flag? "FAIL" : "OK"));
9761
9762                   goto exit;
9763         }
9764         else if (strcmp(tmp[0], "drvmap") == 0)
9765         {
9766                 mapLen = EFUSE_MAP_SIZE;
9767                 
9768                 sprintf(extra, "\n");
9769                 for (i = 0; i < EFUSE_MAP_SIZE; i += 16)
9770                 {
9771 //                      DBG_871X("0x%02x\t", i);
9772                         sprintf(extra, "%s0x%02x\t", extra, i);
9773                         for (j=0; j<8; j++) {
9774 //                              DBG_871X("%02X ", data[i+j]);
9775                                 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
9776                         }
9777 //                      DBG_871X("\t");
9778                         sprintf(extra, "%s\t", extra);
9779                         for (; j<16; j++) {
9780 //                              DBG_871X("%02X ", data[i+j]);
9781                                 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
9782                         }
9783 //                      DBG_871X("\n");
9784                         sprintf(extra,"%s\n",extra);
9785                 }
9786 //              DBG_871X("\n");
9787         }
9788         else if (strcmp(tmp[0], "realmap") == 0)
9789         {
9790                 mapLen = EFUSE_MAP_SIZE;
9791                 if (rtw_efuse_mask_map_read(padapter, EFUSE_WIFI , mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL)
9792                 {
9793                         DBG_871X("%s: read realmap Fail!!\n", __FUNCTION__);
9794                         err = -EFAULT;
9795                         goto exit;
9796                 }
9797
9798 //              DBG_871X("OFFSET\tVALUE(hex)\n");
9799                 sprintf(extra, "\n");
9800                 for (i = 0; i < EFUSE_MAP_SIZE; i += 16)
9801                 {
9802 //                      DBG_871X("0x%02x\t", i);
9803                         sprintf(extra, "%s0x%02x\t", extra, i);
9804                         for (j=0; j<8; j++) {
9805 //                              DBG_871X("%02X ", data[i+j]);
9806                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
9807                         }
9808 //                      DBG_871X("\t");
9809                         sprintf(extra, "%s\t", extra);
9810                         for (; j<16; j++) {
9811 //                              DBG_871X("%02X ", data[i+j]);
9812                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
9813                         }
9814 //                      DBG_871X("\n");
9815                         sprintf(extra,"%s\n",extra);
9816                 }
9817 //              DBG_871X("\n");
9818         }
9819         else if (strcmp(tmp[0], "rmap") == 0)
9820         {
9821                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
9822                 {
9823                         DBG_871X("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
9824                         err = -EINVAL;
9825                         goto exit;
9826                 }
9827
9828                 // rmap addr cnts
9829                 addr = simple_strtoul(tmp[1], &ptmp, 16);
9830                 DBG_871X("%s: addr=%x\n", __FUNCTION__, addr);
9831
9832                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9833                 if (cnts == 0)
9834                 {
9835                         DBG_871X("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
9836                         err = -EINVAL;
9837                         goto exit;
9838                 }
9839                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
9840
9841                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (PVOID)&max_available_size, _FALSE);
9842                 if ((addr+ cnts) > max_available_size)
9843                 {
9844                         DBG_871X("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9845                         err = -EINVAL;
9846                         goto exit;
9847                 }
9848
9849                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL)
9850                 {
9851                         DBG_871X("%s: rtw_efuse_mask_map_read error!\n", __func__);
9852                         err = -EFAULT;
9853                         goto exit;
9854                 }
9855
9856 //              DBG_871X("%s: data={", __FUNCTION__);
9857                 *extra = 0;
9858                 for (i=0; i<cnts; i++) {
9859 //                      DBG_871X("0x%02x ", data[i]);
9860                         sprintf(extra, "%s0x%02X ", extra, data[i]);
9861                 }
9862 //              DBG_871X("}\n");
9863         }
9864         else if (strcmp(tmp[0], "realraw") == 0)
9865         {
9866                 addr = 0;
9867                 mapLen = EFUSE_MAX_SIZE;
9868                 DBG_871X("EFUSE_MAX_SIZE =%d\n",EFUSE_MAX_SIZE);
9869                 if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL)
9870                 {
9871                         DBG_871X("%s: rtw_efuse_access Fail!!\n", __FUNCTION__);
9872                         err = -EFAULT;
9873                         goto exit;
9874                 }
9875                 _rtw_memset(extra,'\0',strlen(extra));
9876                 //              DBG_871X("%s: realraw={\n", __FUNCTION__);
9877                                 sprintf(extra, "\n0x00\t");
9878
9879                                 for (i=0; i< 512 ; i++)
9880                                 {
9881                 //                      DBG_871X("%02X", rawdata[i]);
9882                                         sprintf(extra, "%s%02X", extra, rawdata[i]);
9883                                         if ((i & 0xF) == 0xF) {
9884                 //                              DBG_871X("\n");
9885                                                 sprintf(extra, "%s\n", extra);
9886                                                 sprintf(extra, "%s0x%02x\t", extra, i+1);
9887                                         }
9888                                         else if ((i & 0x7) == 0x7){
9889                 //                              DBG_871X("\t");
9890                                                 sprintf(extra, "%s \t", extra);
9891                                         } else {
9892                 //                              DBG_871X(" ");
9893                                                 sprintf(extra, "%s ", extra);
9894                                         }
9895                                 }
9896                 //              DBG_871X("}\n");
9897         }
9898         else if (strcmp(tmp[0], "realrawb") == 0)
9899         {
9900                 addr = 0;
9901                 mapLen = EFUSE_MAX_SIZE;
9902                 DBG_871X("EFUSE_MAX_SIZE =%d   \n",EFUSE_MAX_SIZE);
9903                 if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL)
9904                 {
9905                         DBG_871X("%s: rtw_efuse_access Fail!!\n", __FUNCTION__);
9906                         err = -EFAULT;
9907                         goto exit;
9908                 }
9909                 _rtw_memset(extra,'\0',strlen(extra));
9910                 //              DBG_871X("%s: realraw={\n", __FUNCTION__);
9911                                 sprintf(extra, "\n0x00\t");
9912                                 for (i= 512; i< mapLen; i++)
9913                                 {
9914                 //                      DBG_871X("%02X", rawdata[i]);
9915                                         sprintf(extra, "%s%02X", extra, rawdata[i]);
9916                                         if ((i & 0xF) == 0xF) {
9917                 //                              DBG_871X("\n");
9918                                                 sprintf(extra, "%s\n", extra);
9919                                                 sprintf(extra, "%s0x%02x\t", extra, i+1);
9920                                         }
9921                                         else if ((i & 0x7) == 0x7){
9922                 //                              DBG_871X("\t");
9923                                                 sprintf(extra, "%s \t", extra);
9924                                         } else {
9925                 //                              DBG_871X(" ");
9926                                                 sprintf(extra, "%s ", extra);
9927                                         }
9928                                 }
9929                 //              DBG_871X("}\n");
9930         }
9931         else if (strcmp(tmp[0], "mac") == 0)
9932         {               
9933                 #ifdef CONFIG_RTL8188E
9934                         #ifdef CONFIG_USB_HCI
9935                         addr = EEPROM_MAC_ADDR_88EU;
9936                         #endif
9937                         #ifdef CONFIG_SDIO_HCI
9938                         addr = EEPROM_MAC_ADDR_88ES;
9939                         #endif
9940                         #ifdef CONFIG_PCI_HCI
9941                         addr = EEPROM_MAC_ADDR_88EE;
9942                         #endif
9943                 #endif // CONFIG_RTL8188E
9944
9945                 #ifdef CONFIG_RTL8192E
9946                         #ifdef CONFIG_USB_HCI
9947                         addr = EEPROM_MAC_ADDR_8192EU;
9948                         #endif
9949                         #ifdef CONFIG_SDIO_HCI
9950                         addr = EEPROM_MAC_ADDR_8192ES;
9951                         #endif
9952                         #ifdef CONFIG_PCI_HCI
9953                         addr = EEPROM_MAC_ADDR_8192EE;
9954                         #endif
9955                 #endif
9956                 #ifdef CONFIG_RTL8723B
9957                 #ifdef CONFIG_SDIO_HCI
9958                 addr = EEPROM_MAC_ADDR_8723BS;
9959                 #endif
9960                 #ifdef CONFIG_GSPI_HCI
9961                 addr = EEPROM_MAC_ADDR_8723BS;
9962                 #endif
9963                 #ifdef CONFIG_USB_HCI
9964                 addr = EEPROM_MAC_ADDR_8723BU;
9965                 #endif
9966                 #endif // CONFIG_RTL8723B
9967                 cnts = 6;
9968
9969                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
9970                 if ((addr + cnts) > max_available_size) {
9971                         DBG_871X("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9972                         err = -EFAULT;
9973                         goto exit;
9974                 }
9975
9976                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL)
9977                 {
9978                         DBG_871X("%s: rtw_efuse_mask_map_read error!\n", __func__);
9979                         err = -EFAULT;
9980                         goto exit;
9981                 }
9982
9983 //              DBG_871X("%s: MAC address={", __FUNCTION__);
9984                 *extra = 0;
9985                 for (i=0; i<cnts; i++)
9986                 {
9987 //                      DBG_871X("%02X", data[i]);
9988                         sprintf(extra, "%s%02X", extra, data[i]);
9989                         if (i != (cnts-1))
9990                         {
9991 //                              DBG_871X(":");
9992                                 sprintf(extra,"%s:",extra);
9993                         }
9994                 }
9995 //              DBG_871X("}\n");
9996         }
9997         else if (strcmp(tmp[0], "vidpid") == 0)
9998         {
9999                 #ifdef CONFIG_RTL8188E
10000                         #ifdef CONFIG_USB_HCI
10001                         addr = EEPROM_VID_88EU;
10002                         #endif
10003                         #ifdef CONFIG_PCI_HCI
10004                         addr = EEPROM_VID_88EE;
10005                         #endif
10006                 #endif // CONFIG_RTL8188E
10007
10008                 #ifdef CONFIG_RTL8192E
10009                         #ifdef CONFIG_USB_HCI
10010                         addr = EEPROM_VID_8192EU;
10011                         #endif
10012                         #ifdef CONFIG_PCI_HCI
10013                         addr = EEPROM_VID_8192EE;
10014                         #endif
10015                 #endif // CONFIG_RTL8192E
10016                 #ifdef CONFIG_RTL8723B
10017                 addr = EEPROM_VID_8723BU;
10018                 #endif // CONFIG_RTL8192E
10019                 cnts = 4;
10020
10021                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
10022                 if ((addr + cnts) > max_available_size)
10023                 {
10024                         DBG_871X("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10025                         err = -EFAULT;
10026                         goto exit;
10027                 }
10028                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL)
10029                 {
10030                         DBG_871X("%s: rtw_efuse_access error!!\n", __FUNCTION__);
10031                         err = -EFAULT;
10032                         goto exit;
10033                 }
10034
10035 //              DBG_871X("%s: {VID,PID}={", __FUNCTION__);
10036                 *extra = 0;
10037                 for (i=0; i<cnts; i++)
10038                 {
10039 //                      DBG_871X("0x%02x", data[i]);
10040                         sprintf(extra, "%s0x%02X", extra, data[i]);
10041                         if (i != (cnts-1))
10042                         {
10043 //                              DBG_871X(",");
10044                                 sprintf(extra,"%s,",extra);
10045                         }
10046                 }
10047 //              DBG_871X("}\n");
10048         }
10049         else if (strcmp(tmp[0], "ableraw") == 0)
10050         {
10051                 efuse_GetCurrentSize(padapter,&raw_cursize);
10052                 raw_maxsize = efuse_GetMaxSize(padapter);
10053                 sprintf(extra, "[available raw size]= %d bytes", raw_maxsize-raw_cursize);
10054         }
10055         else if (strcmp(tmp[0], "btfmap") == 0)
10056         {
10057                 BTEfuse_PowerSwitch(padapter,1,_TRUE);
10058                                 
10059                 mapLen = EFUSE_BT_MAX_MAP_LEN;
10060                 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL)
10061                 {
10062                         DBG_871X("%s: rtw_BT_efuse_map_read Fail!!\n", __FUNCTION__);
10063                         err = -EFAULT;
10064                         goto exit;
10065                 }
10066
10067 //              DBG_871X("OFFSET\tVALUE(hex)\n");
10068                 sprintf(extra, "\n");
10069                 for (i=0; i<512; i+=16) // set 512 because the iwpriv's extra size have limit 0x7FF
10070                 {
10071 //                      DBG_871X("0x%03x\t", i);
10072                         sprintf(extra, "%s0x%03x\t", extra, i);
10073                         for (j=0; j<8; j++) {
10074 //                              DBG_871X("%02X ", pEfuseHal->BTEfuseInitMap[i+j]);
10075                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
10076                         }
10077 //                      DBG_871X("\t");
10078                         sprintf(extra,"%s\t",extra);
10079                         for (; j<16; j++) {
10080 //                              DBG_871X("%02X ", pEfuseHal->BTEfuseInitMap[i+j]);
10081                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
10082                         }
10083 //                      DBG_871X("\n");
10084                         sprintf(extra, "%s\n", extra);
10085                 }
10086 //              DBG_871X("\n");
10087         }
10088         else if (strcmp(tmp[0],"btbmap") == 0)
10089         {
10090                 BTEfuse_PowerSwitch(padapter,1,_TRUE);
10091                 
10092                 mapLen = EFUSE_BT_MAX_MAP_LEN;
10093                 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL)
10094                 {
10095                         DBG_871X("%s: rtw_BT_efuse_map_read Fail!!\n", __FUNCTION__);
10096                         err = -EFAULT;
10097                         goto exit;
10098                 }
10099
10100 //              DBG_871X("OFFSET\tVALUE(hex)\n");
10101                 sprintf(extra, "\n");
10102                 for (i=512; i<1024 ; i+=16)
10103                 {
10104 //                      DBG_871X("0x%03x\t", i);
10105                         sprintf(extra, "%s0x%03x\t", extra, i);
10106                         for (j=0; j<8; j++)
10107                         {
10108 //                              DBG_871X("%02X ", data[i+j]);
10109                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
10110                         }
10111 //                      DBG_871X("\t");
10112                         sprintf(extra,"%s\t",extra);
10113                         for (; j<16; j++) {
10114 //                              DBG_871X("%02X ", data[i+j]);
10115                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
10116                         }
10117 //                      DBG_871X("\n");
10118                         sprintf(extra, "%s\n", extra);
10119                 }
10120 //              DBG_871X("\n");
10121         }
10122         else if (strcmp(tmp[0],"btrmap") == 0)
10123         {
10124                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10125                 {
10126                         err = -EINVAL;
10127                         goto exit;
10128                 }
10129
10130                 BTEfuse_PowerSwitch(padapter,1,_TRUE);
10131                 
10132                 // rmap addr cnts
10133                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10134                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10135
10136                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
10137                 if (cnts == 0)
10138                 {
10139                         DBG_871X("%s: btrmap Fail!! cnts error!\n", __FUNCTION__);
10140                         err = -EINVAL;
10141                         goto exit;
10142                 }
10143                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10144
10145                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
10146                 if ((addr + cnts) > max_available_size)
10147                 {
10148                         DBG_871X("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10149                         err = -EFAULT;
10150                         goto exit;
10151                 }
10152
10153                 if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) 
10154                 {
10155                         DBG_871X("%s: rtw_BT_efuse_map_read error!!\n", __FUNCTION__);
10156                         err = -EFAULT;
10157                         goto exit;
10158                 }
10159
10160                 *extra = 0;
10161 //              DBG_871X("%s: bt efuse data={", __FUNCTION__);
10162                 for (i=0; i<cnts; i++)
10163                 {
10164 //                      DBG_871X("0x%02x ", data[i]);
10165                         sprintf(extra, "%s 0x%02X ", extra, data[i]);
10166                 }
10167 //              DBG_871X("}\n");
10168                 DBG_871X(FUNC_ADPT_FMT ": BT MAC=[%s]\n", FUNC_ADPT_ARG(padapter), extra);
10169         }
10170         else if (strcmp(tmp[0], "btffake") == 0)
10171         {
10172 //              DBG_871X("OFFSET\tVALUE(hex)\n");
10173                 sprintf(extra, "\n");
10174                 for (i=0; i<512; i+=16)
10175                 {
10176 //                      DBG_871X("0x%03x\t", i);
10177                         sprintf(extra, "%s0x%03x\t", extra, i);
10178                         for (j=0; j<8; j++) {
10179 //                              DBG_871X("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10180                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10181                         }
10182 //                      DBG_871X("\t");
10183                         sprintf(extra, "%s\t", extra);
10184                         for (; j<16; j++) {
10185 //                              DBG_871X("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10186                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10187                         }
10188 //                      DBG_871X("\n");
10189                         sprintf(extra, "%s\n", extra);
10190                 }
10191 //              DBG_871X("\n");
10192         }
10193         else if (strcmp(tmp[0],"btbfake") == 0)
10194         {
10195 //              DBG_871X("OFFSET\tVALUE(hex)\n");
10196                 sprintf(extra, "\n");
10197                 for (i=512; i<1024; i+=16)
10198                 {
10199 //                      DBG_871X("0x%03x\t", i);
10200                         sprintf(extra, "%s0x%03x\t", extra, i);
10201                         for (j=0; j<8; j++) {
10202 //                              DBG_871X("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10203                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10204                         }
10205 //                      DBG_871X("\t");
10206                         sprintf(extra, "%s\t", extra);
10207                         for (; j<16; j++) {
10208 //                              DBG_871X("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10209                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10210                         }
10211 //                      DBG_871X("\n");
10212                         sprintf(extra, "%s\n", extra);
10213                 }
10214 //              DBG_871X("\n");
10215         }
10216         else if (strcmp(tmp[0],"wlrfkmap")== 0)
10217         {
10218 //              DBG_871X("OFFSET\tVALUE(hex)\n");
10219                 sprintf(extra, "\n");
10220                 for (i=0; i<EFUSE_MAP_SIZE; i+=16)
10221                 {
10222 //                      DBG_871X("\t0x%02x\t", i);
10223                         sprintf(extra, "%s0x%02x\t", extra, i);
10224                         for (j=0; j<8; j++) {
10225 //                              DBG_871X("%02X ", pEfuseHal->fakeEfuseModifiedMap[i+j]);
10226                                 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
10227                         }
10228 //                      DBG_871X("\t");
10229                         sprintf(extra, "%s\t", extra);
10230                         for (; j<16; j++) {
10231 //                              DBG_871X("%02X ", pEfuseHal->fakeEfuseModifiedMap[i+j]);
10232                                 sprintf(extra, "%s %02X", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
10233                         }
10234 //                      DBG_871X("\n");
10235                         sprintf(extra, "%s\n", extra);
10236                 }
10237 //              DBG_871X("\n");
10238
10239         }
10240         else if (strcmp(tmp[0],"wlrfkrmap")== 0)
10241         {
10242                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10243                                 {
10244                                         DBG_871X("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
10245                                         err = -EINVAL;
10246                                         goto exit;
10247                                 }
10248                                 // rmap addr cnts
10249                                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10250                                 DBG_871X("%s: addr=%x\n", __FUNCTION__, addr);
10251                 
10252                                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
10253                                 if (cnts == 0)
10254                                 {
10255                                         DBG_871X("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
10256                                         err = -EINVAL;
10257                                         goto exit;
10258                                 }
10259                                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10260                 
10261                 //              DBG_871X("%s: data={", __FUNCTION__);
10262                         *extra = 0;
10263                         for (i=0; i<cnts; i++) {
10264                                         DBG_871X("wlrfkrmap = 0x%02x \n", pEfuseHal->fakeEfuseModifiedMap[addr+i]);
10265                                         sprintf(extra, "%s0x%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[addr+i]);
10266                         }
10267         }
10268         else if (strcmp(tmp[0],"btrfkrmap")== 0)
10269         {
10270                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10271                                 {
10272                                         DBG_871X("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
10273                                         err = -EINVAL;
10274                                         goto exit;
10275                                 }
10276                                 // rmap addr cnts
10277                                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10278                                 DBG_871X("%s: addr=%x\n", __FUNCTION__, addr);
10279                 
10280                                 cnts = simple_strtoul(tmp[2], &ptmp, 10);
10281                                 if (cnts == 0)
10282                                 {
10283                                         DBG_871X("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
10284                                         err = -EINVAL;
10285                                         goto exit;
10286                                 }
10287                                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10288                 
10289                 //              DBG_871X("%s: data={", __FUNCTION__);
10290                         *extra = 0;
10291                         for (i=0; i<cnts; i++) {
10292                                         DBG_871X("wlrfkrmap = 0x%02x \n", pEfuseHal->fakeBTEfuseModifiedMap[addr+i]);
10293                                         sprintf(extra, "%s0x%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[addr+i]);
10294                         }
10295         }
10296         else
10297         {
10298                  sprintf(extra, "Command not found!");
10299         }
10300
10301 exit:
10302         if (data)
10303                 rtw_mfree(data, EFUSE_BT_MAX_MAP_LEN);
10304         if (rawdata)
10305                 rtw_mfree(rawdata, EFUSE_BT_MAX_MAP_LEN);
10306         if (!err)
10307                 wrqu->length = strlen(extra);
10308         
10309         if (padapter->registrypriv.mp_mode == 0)
10310         {
10311         #ifdef CONFIG_IPS               
10312         rtw_pm_set_ips(padapter, ips_mode);
10313 #endif // CONFIG_IPS
10314
10315         #ifdef CONFIG_LPS       
10316         rtw_pm_set_lps(padapter, lps_mode);
10317 #endif // CONFIG_LPS
10318         }
10319
10320         #ifdef CONFIG_IOL
10321         padapter->registrypriv.fw_iol = org_fw_iol;// 0:Disable, 1:enable, 2:by usb speed
10322         #endif
10323         return err;
10324 }
10325
10326 static int rtw_mp_efuse_set(struct net_device *dev,
10327                         struct iw_request_info *info,
10328                         union iwreq_data *wdata, char *extra)
10329 {
10330         struct iw_point *wrqu;
10331         PADAPTER padapter;
10332         struct pwrctrl_priv *pwrctrlpriv ;
10333         PHAL_DATA_TYPE pHalData;
10334         PEFUSE_HAL pEfuseHal;
10335
10336         u8 ips_mode = IPS_NUM; // init invalid value
10337         u8 lps_mode = PS_MODE_NUM; // init invalid value
10338         u32 i=0,j=0, jj, kk;
10339         u8 *setdata = NULL;
10340         u8 *ShadowMapBT = NULL;
10341         u8 *ShadowMapWiFi = NULL;
10342         u8 *setrawdata = NULL;
10343         char *pch, *ptmp, *token, *tmp[3]={0x00,0x00,0x00};
10344         u16 addr=0xFF, cnts=0, BTStatus=0 , max_available_size=0;
10345         int err;
10346
10347         wrqu = (struct iw_point*)wdata;
10348         padapter = rtw_netdev_priv(dev);
10349         pwrctrlpriv = adapter_to_pwrctl(padapter);
10350         pHalData = GET_HAL_DATA(padapter);
10351         pEfuseHal = &pHalData->EfuseHal;
10352         err = 0;
10353         
10354         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
10355                         return -EFAULT;
10356                         
10357         setdata = rtw_zmalloc(1024);
10358         if (setdata == NULL)
10359         {
10360                 err = -ENOMEM;
10361                 goto exit;
10362         }
10363         ShadowMapBT = rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
10364         if (ShadowMapBT == NULL)
10365         {
10366                 err = -ENOMEM;
10367                 goto exit;
10368         }
10369         ShadowMapWiFi = rtw_malloc(EFUSE_MAP_SIZE);
10370         if (ShadowMapWiFi == NULL)
10371         {
10372                 err = -ENOMEM;
10373                 goto exit;
10374         }
10375         setrawdata = rtw_malloc(EFUSE_MAX_SIZE);
10376         if (setrawdata == NULL)
10377         {
10378                 err = -ENOMEM;
10379                 goto exit;
10380         }
10381
10382         #ifdef CONFIG_LPS
10383         lps_mode = pwrctrlpriv->power_mgnt;//keep org value
10384         rtw_pm_set_lps(padapter,PS_MODE_ACTIVE);
10385         #endif  
10386         
10387         #ifdef CONFIG_IPS       
10388         ips_mode = pwrctrlpriv->ips_mode;//keep org value
10389         rtw_pm_set_ips(padapter,IPS_NONE);
10390         #endif  
10391                         
10392         pch = extra;
10393         DBG_871X("%s: in=%s\n", __FUNCTION__, extra);
10394         
10395         i = 0;
10396         while ((token = strsep(&pch, ",")) != NULL)
10397         {
10398                 if (i > 2) break;
10399                 tmp[i] = token;
10400                 i++;
10401         }
10402
10403         // tmp[0],[1],[2]
10404         // wmap,addr,00e04c871200
10405         if (strcmp(tmp[0], "wmap") == 0)
10406         {
10407                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10408                 {
10409                         err = -EINVAL;
10410                         goto exit;
10411                 }
10412
10413 #if 1
10414                 // unknown bug workaround, need to fix later
10415                 addr=0x1ff;
10416                 rtw_write8(padapter, EFUSE_CTRL+1, (addr & 0xff));
10417                 rtw_msleep_os(10);
10418                 rtw_write8(padapter, EFUSE_CTRL+2, ((addr >> 8) & 0x03));
10419                 rtw_msleep_os(10);
10420                 rtw_write8(padapter, EFUSE_CTRL+3, 0x72);
10421                 rtw_msleep_os(10);
10422                 rtw_read8(padapter, EFUSE_CTRL);
10423 #endif
10424
10425                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10426                 addr &= 0xFFF;
10427
10428                 cnts = strlen(tmp[2]);
10429                 if (cnts%2)
10430                 {
10431                         err = -EINVAL;
10432                         goto exit;
10433                 }
10434                 cnts /= 2;
10435                 if (cnts == 0)
10436                 {
10437                         err = -EINVAL;
10438                         goto exit;
10439                 }
10440
10441                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10442                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10443                 DBG_871X("%s: map data=%s\n", __FUNCTION__, tmp[2]);
10444                                 
10445                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
10446                 {
10447                         setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk+1]);
10448                 }
10449 #ifndef CONFIG_RTL8188E
10450                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
10451 #else
10452                 //Change to check TYPE_EFUSE_MAP_LEN ,beacuse 8188E raw 256,logic map over 256.
10453                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_size, _FALSE);
10454 #endif
10455                 if ((addr+cnts) > max_available_size)
10456                 {
10457                         DBG_871X("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10458                         err = -EFAULT;
10459                         goto exit;
10460                 }
10461
10462                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL)
10463                 {
10464                         DBG_871X("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
10465                         err = -EFAULT;
10466                         goto exit;
10467                 }
10468                 *extra = 0;
10469                 DBG_871X("%s: after rtw_efuse_map_write to _rtw_memcmp\n", __func__);
10470                 if (rtw_efuse_mask_map_read(padapter, addr, cnts, ShadowMapWiFi) == _SUCCESS)
10471                 {
10472                         if (_rtw_memcmp((void*)ShadowMapWiFi ,(void*)setdata,cnts))
10473                         { 
10474                                 DBG_871X("%s: WiFi write map afterf compare success\n", __FUNCTION__);
10475                                 sprintf(extra, "WiFi write map compare OK\n");
10476                                 err = 0;
10477                                 goto exit;
10478                         }
10479                         else
10480                         {
10481                                 sprintf(extra, "WiFi write map compare FAIL\n");
10482                                 DBG_871X("%s: WiFi write map compare Fail\n", __FUNCTION__);
10483                                 err = 0;
10484                                 goto exit;
10485                         }
10486                 }
10487         }
10488         else if (strcmp(tmp[0], "wraw") == 0)
10489         {
10490                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10491                 {
10492                         err = -EINVAL;
10493                         goto exit;
10494                 }
10495
10496                 addr = simple_strtoul( tmp[1], &ptmp, 16 );
10497                 addr &= 0xFFF;
10498
10499                 cnts = strlen(tmp[2]);
10500                 if (cnts%2)
10501                 {
10502                         err = -EINVAL;
10503                         goto exit;
10504                 }
10505                 cnts /= 2;
10506                 if (cnts == 0)
10507                 {
10508                         err = -EINVAL;
10509                         goto exit;
10510                 }
10511
10512                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10513                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10514                 DBG_871X("%s: raw data=%s\n", __FUNCTION__, tmp[2]);
10515
10516                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
10517                 {
10518                         setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk+1]);
10519                 }
10520
10521                 if (rtw_efuse_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL)
10522                 {
10523                         DBG_871X("%s: rtw_efuse_access error!!\n", __FUNCTION__);
10524                         err = -EFAULT;
10525                         goto exit;
10526                 }
10527         }
10528         else if (strcmp(tmp[0], "mac") == 0)
10529         {
10530                 if (tmp[1]==NULL)
10531                 {
10532                         err = -EINVAL;
10533                         goto exit;
10534                 }
10535
10536                 //mac,00e04c871200
10537                 
10538                 #ifdef CONFIG_RTL8188E
10539                         #ifdef CONFIG_USB_HCI
10540                         addr = EEPROM_MAC_ADDR_88EU;
10541                         #endif
10542                         #ifdef CONFIG_SDIO_HCI
10543                         addr = EEPROM_MAC_ADDR_88ES;
10544                         #endif
10545                         #ifdef CONFIG_PCI_HCI
10546                         addr = EEPROM_MAC_ADDR_88EE;
10547                         #endif
10548                 #endif //#ifdef CONFIG_RTL8188E
10549
10550                 #ifdef CONFIG_RTL8192E
10551                         #ifdef CONFIG_USB_HCI
10552                         addr = EEPROM_MAC_ADDR_8192EU;
10553                         #endif
10554                         #ifdef CONFIG_SDIO_HCI
10555                         addr = EEPROM_MAC_ADDR_8192ES;
10556                         #endif
10557                         #ifdef CONFIG_PCI_HCI
10558                         addr = EEPROM_MAC_ADDR_8192EE;
10559                         #endif
10560                 #endif //#ifdef CONFIG_RTL8192E
10561                 
10562                 #ifdef CONFIG_RTL8723B
10563                 #ifdef CONFIG_SDIO_HCI
10564                 addr = EEPROM_MAC_ADDR_8723BS;
10565                 #endif
10566                 #ifdef CONFIG_GSPI_HCI
10567                 addr = EEPROM_MAC_ADDR_8723BS;
10568                 #endif
10569                 #ifdef CONFIG_USB_HCI
10570                 addr = EEPROM_MAC_ADDR_8723BU;
10571                 #endif
10572                 #endif // CONFIG_RTL8723B
10573                 
10574                 #if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
10575                 #ifdef CONFIG_SDIO_HCI
10576                                 addr = EEPROM_MAC_ADDR_8821AS;
10577                 #endif
10578                 #ifdef CONFIG_PCI_HCI
10579                                 addr = EEPROM_MAC_ADDR_8821AE;
10580                 #endif
10581                 #ifdef CONFIG_USB_HCI
10582                                 addr = EEPROM_MAC_ADDR_8821AU;
10583                 #endif
10584                 
10585                 #endif // CONFIG_RTL8812A/CONFIG_RTL8821A
10586                 
10587                 cnts = strlen(tmp[1]);
10588                 if (cnts%2)
10589                 {
10590                         err = -EINVAL;
10591                         goto exit;
10592                 }
10593                 cnts /= 2;
10594                 if (cnts == 0)
10595                 {
10596                         err = -EINVAL;
10597                         goto exit;
10598                 }
10599                 if (cnts > 6)
10600                 {
10601                         DBG_871X("%s: error data for mac addr=\"%s\"\n", __FUNCTION__, tmp[1]);
10602                         err = -EFAULT;
10603                         goto exit;
10604                 }
10605
10606                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10607                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10608                 DBG_871X("%s: MAC address=%s\n", __FUNCTION__, tmp[1]);
10609
10610                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
10611                 {
10612                         setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+1]);
10613                 }
10614 #ifndef CONFIG_RTL8188E
10615                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
10616 #else
10617                 //Change to check TYPE_EFUSE_MAP_LEN ,beacuse 8188E raw 256,logic map over 256.
10618                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&max_available_size, _FALSE);
10619 #endif
10620                 if ((addr+cnts) > max_available_size)
10621                 {
10622                         DBG_871X("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10623                         err = -EFAULT;
10624                         goto exit;
10625                 }
10626
10627                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL)
10628                 {
10629                         DBG_871X("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
10630                         err = -EFAULT;
10631                         goto exit;
10632                 }
10633         }
10634         else if (strcmp(tmp[0], "vidpid") == 0)
10635         {
10636                 if (tmp[1]==NULL)
10637                 {
10638                         err = -EINVAL;
10639                         goto exit;
10640                 }
10641
10642                 // pidvid,da0b7881              
10643                 #ifdef CONFIG_RTL8188E
10644                         #ifdef CONFIG_USB_HCI
10645                         addr = EEPROM_VID_88EU;
10646                         #endif
10647                         #ifdef CONFIG_PCI_HCI
10648                         addr = EEPROM_VID_88EE;
10649                         #endif
10650                 #endif // CONFIG_RTL8188E
10651
10652                 #ifdef CONFIG_RTL8192E
10653                         #ifdef CONFIG_USB_HCI
10654                         addr = EEPROM_VID_8192EU;
10655                         #endif
10656                         #ifdef CONFIG_PCI_HCI
10657                         addr = EEPROM_VID_8192EE;
10658                         #endif
10659                 #endif // CONFIG_RTL8188E
10660
10661                 #ifdef CONFIG_RTL8723B
10662                 addr = EEPROM_VID_8723BU;
10663                 #endif
10664                 
10665                 cnts = strlen(tmp[1]);
10666                 if (cnts%2)
10667                 {
10668                         err = -EINVAL;
10669                         goto exit;
10670                 }
10671                 cnts /= 2;
10672                 if (cnts == 0)
10673                 {
10674                         err = -EINVAL;
10675                         goto exit;
10676                 }
10677
10678                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10679                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10680                 DBG_871X("%s: VID/PID=%s\n", __FUNCTION__, tmp[1]);
10681
10682                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
10683                 {
10684                         setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+1]);
10685                 }
10686
10687                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
10688                 if ((addr+cnts) > max_available_size)
10689                 {
10690                         DBG_871X("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10691                         err = -EFAULT;
10692                         goto exit;
10693                 }
10694
10695                 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL)
10696                 {
10697                         DBG_871X("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
10698                         err = -EFAULT;
10699                         goto exit;
10700                 }
10701         }
10702         else if (strcmp(tmp[0], "wldumpfake") == 0)
10703         {
10704                 if (rtw_efuse_mask_map_read(padapter, 0, EFUSE_MAP_SIZE, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) {
10705                         DBG_871X("%s: WiFi hw efuse dump to Fake map success\n", __func__);
10706                 } else {
10707                         DBG_871X("%s: WiFi hw efuse dump to Fake map Fail\n", __func__);
10708                         err = -EFAULT;
10709                 }
10710         }
10711         else if (strcmp(tmp[0], "btwmap") == 0)
10712         {
10713                 rtw_write8(padapter, 0xa3, 0x05); //For 8723AB ,8821S ?
10714                 BTStatus=rtw_read8(padapter, 0xa0);
10715                 DBG_871X("%s: btwmap before read 0xa0 BT Status =0x%x \n", __FUNCTION__,BTStatus);
10716                 if (BTStatus != 0x04)
10717                 {
10718                         sprintf(extra, "BT Status not Active Write FAIL\n");
10719                         goto exit;
10720                 }
10721
10722                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10723                 {
10724                         err = -EINVAL;
10725                         goto exit;
10726                 }
10727                 BTEfuse_PowerSwitch(padapter,1,_TRUE);
10728                 
10729                 addr=0x1ff;
10730                 rtw_write8(padapter, EFUSE_CTRL+1, (addr & 0xff));
10731                 rtw_msleep_os(10);
10732                 rtw_write8(padapter, EFUSE_CTRL+2, ((addr >> 8) & 0x03));
10733                 rtw_msleep_os(10);
10734                 rtw_write8(padapter, EFUSE_CTRL+3, 0x72);
10735                 rtw_msleep_os(10);
10736                 rtw_read8(padapter, EFUSE_CTRL);
10737
10738                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10739                 addr &= 0xFFF;
10740
10741                 cnts = strlen(tmp[2]);
10742                 if (cnts%2)
10743                 {
10744                         err = -EINVAL;
10745                         goto exit;
10746                 }
10747                 cnts /= 2;
10748                 if (cnts == 0)
10749                 {
10750                         err = -EINVAL;
10751                         goto exit;
10752                 }
10753
10754                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10755                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10756                 DBG_871X("%s: BT data=%s\n", __FUNCTION__, tmp[2]);
10757
10758                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
10759                 {
10760                         setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk+1]);
10761                 }
10762
10763                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
10764                 if ((addr+cnts) > max_available_size)
10765                 {
10766                         DBG_871X("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
10767                         err = -EFAULT;
10768                         goto exit;
10769                 }
10770
10771                 if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL)
10772                 {
10773                         DBG_871X("%s: rtw_BT_efuse_map_write error!!\n", __FUNCTION__);
10774                         err = -EFAULT;
10775                         goto exit;
10776                 }
10777                 *extra = 0;
10778                 DBG_871X("%s: after rtw_BT_efuse_map_write to _rtw_memcmp \n", __FUNCTION__);
10779                 if ( (rtw_BT_efuse_map_read(padapter, addr, cnts, ShadowMapBT ) == _SUCCESS ) )
10780                 {
10781                         if (_rtw_memcmp((void*)ShadowMapBT ,(void*)setdata,cnts))
10782                         { 
10783                                 DBG_871X("%s: BT write map compare OK BTStatus=0x%x\n", __FUNCTION__,BTStatus);
10784                                 sprintf(extra, "BT write map compare OK");
10785                                 err = 0;
10786                                 goto exit;
10787                         }
10788                         else
10789                         {
10790                                 sprintf(extra, "BT write map compare FAIL");
10791                                 DBG_871X("%s: BT write map compare FAIL BTStatus=0x%x\n", __FUNCTION__,BTStatus);
10792                                 err = 0;
10793                                 goto exit;
10794                         }
10795                 }
10796         }
10797         else if (strcmp(tmp[0], "btwfake") == 0)
10798         {
10799                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10800                 {
10801                         err = -EINVAL;
10802                         goto exit;
10803                 }
10804
10805                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10806                 addr &= 0xFFF;
10807
10808                 cnts = strlen(tmp[2]);
10809                 if (cnts%2)
10810                 {
10811                         err = -EINVAL;
10812                         goto exit;
10813                 }
10814                 cnts /= 2;
10815                 if (cnts == 0)
10816                 {
10817                         err = -EINVAL;
10818                         goto exit;
10819                 }
10820
10821                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10822                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10823                 DBG_871X("%s: BT tmp data=%s\n", __FUNCTION__, tmp[2]);
10824                                 
10825                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
10826                 {
10827                         pEfuseHal->fakeBTEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk+1]);
10828                 }
10829         }
10830         else if (strcmp(tmp[0], "btdumpfake") == 0)
10831         {
10832                 if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS) {
10833                         DBG_871X("%s: BT read all map success\n", __FUNCTION__);
10834                 } else {
10835                         DBG_871X("%s: BT read all map Fail!\n", __FUNCTION__);
10836                         err = -EFAULT;
10837                 }
10838         }
10839         else if (strcmp(tmp[0], "btfk2map") == 0)
10840         {
10841                 rtw_write8(padapter, 0xa3, 0x05);
10842                 BTStatus=rtw_read8(padapter, 0xa0);
10843                 DBG_871X("%s: btwmap before read 0xa0 BT Status =0x%x \n", __FUNCTION__,BTStatus);
10844                 if (BTStatus != 0x04)
10845                 {
10846                         sprintf(extra, "BT Status not Active Write FAIL\n");
10847                         goto exit;
10848                 }
10849                 
10850                 BTEfuse_PowerSwitch(padapter,1,_TRUE);
10851
10852                 addr=0x1ff;
10853                 rtw_write8(padapter, EFUSE_CTRL+1, (addr & 0xff));
10854                 rtw_msleep_os(10);
10855                 rtw_write8(padapter, EFUSE_CTRL+2, ((addr >> 8) & 0x03));
10856                 rtw_msleep_os(10);
10857                 rtw_write8(padapter, EFUSE_CTRL+3, 0x72);
10858                 rtw_msleep_os(10);
10859                 rtw_read8(padapter, EFUSE_CTRL);
10860
10861                 _rtw_memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
10862                         
10863                 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);     
10864                 if (max_available_size < 1)
10865                 {
10866                         err = -EFAULT;
10867                         goto exit;
10868                 }
10869
10870                 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL)
10871                 {
10872                         DBG_871X("%s: rtw_BT_efuse_map_write error!\n", __FUNCTION__);
10873                         err = -EFAULT;
10874                         goto exit;
10875                 }
10876                 
10877                 DBG_871X("pEfuseHal->fakeBTEfuseModifiedMap OFFSET\tVALUE(hex)\n");
10878                 for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16)
10879                 {
10880                         printk("0x%02x\t", i);
10881                         for (j=0; j<8; j++) {
10882                                 printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10883                         }
10884                         printk("\t");
10885
10886                         for (; j<16; j++) {
10887                                 printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
10888                         }
10889                         printk("\n");
10890                 }
10891                 printk("\n");
10892 #if 1           
10893                 err = -EFAULT;
10894                 DBG_871X("%s: rtw_BT_efuse_map_read _rtw_memcmp \n", __FUNCTION__);
10895                 if ( (rtw_BT_efuse_map_read(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS ) )
10896                 { 
10897                         if (_rtw_memcmp((void*)pEfuseHal->fakeBTEfuseModifiedMap,(void*)pEfuseHal->fakeBTEfuseInitMap,EFUSE_BT_MAX_MAP_LEN))
10898                         { 
10899                                 sprintf(extra, "BT write map compare OK");
10900                                 DBG_871X("%s: BT write map afterf compare success BTStatus=0x%x \n", __FUNCTION__,BTStatus);
10901                                 err = 0;
10902                                 goto exit;
10903                         }
10904                         else
10905                         {
10906                                 sprintf(extra, "BT write map compare FAIL");
10907                                 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL)
10908                                 {
10909                                         DBG_871X("%s: rtw_BT_efuse_map_write compare error,retry = %d!\n", __FUNCTION__,i);
10910                                 }
10911
10912                                 if (rtw_BT_efuse_map_read(padapter, EFUSE_BT, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS)
10913                                 {
10914                                         DBG_871X("pEfuseHal->fakeBTEfuseInitMap OFFSET\tVALUE(hex)\n");
10915
10916                                         for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16)
10917                                         {
10918                                                 printk("0x%02x\t", i);
10919                                                 for (j=0; j<8; j++) {
10920                                                         printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i+j]);
10921                                                 }
10922                                                 printk("\t");
10923                                                 for (; j<16; j++) {
10924                                                         printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i+j]);
10925                                                 }
10926                                                 printk("\n");
10927                                         }
10928                                         printk("\n"); 
10929                                 }
10930                                 DBG_871X("%s: BT write map afterf compare not match to write efuse try write Map again , BTStatus=0x%x\n", __FUNCTION__,BTStatus);      
10931                                 goto exit;
10932                         }
10933                 }
10934 #endif
10935
10936         }
10937         else if (strcmp(tmp[0], "wlfk2map") == 0)
10938         {
10939                 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);                                   
10940                 if (max_available_size < 1)
10941                 {
10942                         err = -EFAULT;
10943                         goto exit;
10944                 }
10945                 if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAP_SIZE, pEfuseHal->fakeEfuseModifiedMap) == _FAIL)
10946                 {
10947                         DBG_871X("%s: rtw_efuse_map_write fakeEfuseModifiedMap error!\n", __FUNCTION__);
10948                         err = -EFAULT;
10949                         goto exit;
10950                 }
10951                 *extra = 0;
10952                 DBG_871X("%s: after rtw_BT_efuse_map_write to _rtw_memcmp\n", __func__);
10953                 if (rtw_efuse_mask_map_read(padapter, 0x00, EFUSE_MAP_SIZE, ShadowMapWiFi) == _SUCCESS)
10954                 {
10955                         if (_rtw_memcmp((void*)ShadowMapWiFi ,(void*)setdata,cnts))
10956                         {
10957                                 DBG_871X("%s: WiFi write map afterf compare OK\n", __FUNCTION__);
10958                                 sprintf(extra, "WiFi write map compare OK\n");
10959                                 err = 0;
10960                                 goto exit;
10961                         }
10962                         else
10963                         {
10964                                 sprintf(extra, "WiFi write map compare FAIL\n");
10965                                 DBG_871X("%s: WiFi write map compare Fail\n", __FUNCTION__);
10966                                 err = 0;
10967                                 goto exit;
10968                         }
10969                 }
10970         }
10971         else if (strcmp(tmp[0], "wlwfake") == 0)
10972         {
10973                 if ((tmp[1]==NULL) || (tmp[2]==NULL))
10974                 {
10975                         err = -EINVAL;
10976                         goto exit;
10977                 }
10978
10979                 addr = simple_strtoul(tmp[1], &ptmp, 16);
10980                 addr &= 0xFFF;
10981
10982                 cnts = strlen(tmp[2]);
10983                 if (cnts%2)
10984                 {
10985                         err = -EINVAL;
10986                         goto exit;
10987                 }
10988                 cnts /= 2;
10989                 if (cnts == 0)
10990                 {
10991                         err = -EINVAL;
10992                         goto exit;
10993                 }
10994
10995                 DBG_871X("%s: addr=0x%X\n", __FUNCTION__, addr);
10996                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
10997                 DBG_871X("%s: map tmp data=%s\n", __FUNCTION__, tmp[2]);
10998
10999                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
11000                 {
11001                         pEfuseHal->fakeEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk+1]);
11002                 }
11003                 _rtw_memset(extra, '\0', strlen(extra));
11004                 sprintf(extra, "wlwfake OK\n");
11005         }
11006
11007 exit:
11008         if (setdata)
11009                 rtw_mfree(setdata, 1024);
11010         if (ShadowMapBT)
11011                 rtw_mfree(ShadowMapBT, EFUSE_BT_MAX_MAP_LEN);
11012         if (ShadowMapWiFi)
11013                 rtw_mfree(ShadowMapWiFi, EFUSE_MAP_SIZE);
11014         if (setrawdata)
11015                 rtw_mfree(setrawdata, EFUSE_MAX_SIZE);
11016         
11017         wrqu->length = strlen(extra);
11018
11019         if (padapter->registrypriv.mp_mode == 0)
11020         {
11021         #ifdef CONFIG_IPS               
11022         rtw_pm_set_ips(padapter, ips_mode);
11023         #endif // CONFIG_IPS
11024
11025         #ifdef CONFIG_LPS       
11026         rtw_pm_set_lps(padapter, lps_mode);
11027         #endif // CONFIG_LPS
11028         }
11029
11030         return err;
11031 }
11032
11033 #if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_MP_IWPRIV_SUPPORT)
11034 /*
11035  * Input Format: %s,%d,%d
11036  *      %s is width, could be
11037  *              "b" for 1 byte
11038  *              "w" for WORD (2 bytes)
11039  *              "dw" for DWORD (4 bytes)
11040  *      1st %d is address(offset)
11041  *      2st %d is data to write
11042  */
11043 static int rtw_mp_write_reg(struct net_device *dev,
11044                         struct iw_request_info *info,
11045                         struct iw_point *wrqu, char *extra)
11046 {
11047         char *pch, *pnext, *ptmp;
11048         char *width_str;
11049         char width;
11050         u32 addr, data;
11051         int ret;
11052         PADAPTER padapter = rtw_netdev_priv(dev);
11053         char input[wrqu->length];
11054
11055         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11056                                  return -EFAULT;
11057                                  
11058         _rtw_memset(extra, 0, wrqu->length);    
11059           
11060         pch = input;
11061
11062         pnext = strpbrk(pch, " ,.-");
11063         if (pnext == NULL) return -EINVAL;
11064         *pnext = 0;
11065         width_str = pch;
11066
11067         pch = pnext + 1;
11068         pnext = strpbrk(pch, " ,.-");
11069         if (pnext == NULL) return -EINVAL;
11070         *pnext = 0;
11071         addr = simple_strtoul(pch, &ptmp, 16);
11072         if (addr > 0x3FFF) return -EINVAL;
11073
11074         pch = pnext + 1;
11075         if ((pch - extra) >= wrqu->length) return -EINVAL;
11076         data = simple_strtoul(pch, &ptmp, 16);
11077
11078         ret = 0;
11079         width = width_str[0];
11080         switch (width) {
11081                 case 'b':
11082                         // 1 byte
11083                         if (data > 0xFF) {
11084                                 ret = -EINVAL;
11085                                 break;
11086                         }
11087                         rtw_write8(padapter, addr, data);
11088                         break;
11089                 case 'w':
11090                         // 2 bytes
11091                         if (data > 0xFFFF) {
11092                                 ret = -EINVAL;
11093                                 break;
11094                         }
11095                         rtw_write16(padapter, addr, data);
11096                         break;
11097                 case 'd':
11098                         // 4 bytes
11099                         rtw_write32(padapter, addr, data);
11100                         break;
11101                 default:
11102                         ret = -EINVAL;
11103                         break;
11104         }
11105
11106         return ret;
11107 }
11108
11109 /*
11110  * Input Format: %s,%d
11111  *      %s is width, could be
11112  *              "b" for 1 byte
11113  *              "w" for WORD (2 bytes)
11114  *              "dw" for DWORD (4 bytes)
11115  *      %d is address(offset)
11116  *
11117  * Return:
11118  *      %d for data readed
11119  */
11120 static int rtw_mp_read_reg(struct net_device *dev,
11121                         struct iw_request_info *info,
11122                         struct iw_point *wrqu, char *extra)
11123 {
11124         char input[wrqu->length];
11125         char *pch, *pnext, *ptmp;
11126         char *width_str;
11127         char width;
11128         char data[20],tmp[20];
11129         u32 addr;
11130         //u32 *data = (u32*)extra;
11131         u32 ret, i=0, j=0, strtout=0;
11132         PADAPTER padapter = rtw_netdev_priv(dev);
11133
11134
11135         if (wrqu->length > 128) 
11136                 return -EFAULT;
11137
11138         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11139                 return -EFAULT;
11140
11141         _rtw_memset(data, 0, 20);
11142         _rtw_memset(tmp, 0, 20);
11143         _rtw_memset(extra, 0, wrqu->length);
11144
11145         pch = input;
11146         pnext = strpbrk(pch, " ,.-");
11147         if (pnext == NULL) return -EINVAL;
11148         *pnext = 0;
11149         width_str = pch;
11150
11151         pch = pnext + 1;
11152         if ((pch - input) >= wrqu->length) return -EINVAL;
11153         
11154         addr = simple_strtoul(pch, &ptmp, 16);
11155         if (addr > 0x3FFF) return -EINVAL;
11156
11157         ret = 0;
11158         width = width_str[0];
11159         switch (width)
11160         {
11161                 case 'b':
11162                         // 1 byte
11163                         // *(u8*)data = rtw_read8(padapter, addr);
11164                         sprintf(extra, "%d\n",  rtw_read8(padapter, addr));
11165                         wrqu->length = strlen(extra);
11166                         break;
11167                 case 'w':
11168                         // 2 bytes
11169                         //*(u16*)data = rtw_read16(padapter, addr);
11170                         sprintf(data, "%04x\n", rtw_read16(padapter, addr));
11171                         for( i=0 ; i <= strlen(data) ; i++)
11172                                 {
11173                                           if( i%2==0 )
11174                                           {
11175                                                    tmp[j]=' ';
11176                                                    j++;
11177                                           }
11178                                           if ( data[i] != '\0' )
11179                                                  tmp[j] = data[i];
11180                                                 
11181                                                  j++;
11182                                 }
11183                                 pch = tmp;              
11184                                 DBG_871X("pch=%s",pch);
11185                                 
11186                                 while( *pch != '\0' )
11187                                 {
11188                                         pnext = strpbrk(pch, " ");
11189                                         if (!pnext)
11190                                                 break;
11191                                         
11192                                         pnext++;
11193                                         if ( *pnext != '\0' )
11194                                         {
11195                                                   strtout = simple_strtoul (pnext , &ptmp, 16);
11196                                                   sprintf( extra, "%s %d" ,extra ,strtout );
11197                                         }
11198                                         else{
11199                                                   break;
11200                                         }
11201                                         pch = pnext;
11202                                 }
11203                         wrqu->length = 7;
11204                         break;
11205                 case 'd':
11206                         // 4 bytes
11207                         //*data = rtw_read32(padapter, addr);
11208                         sprintf(data, "%08x", rtw_read32(padapter, addr));
11209                                 //add read data format blank
11210                                 for( i=0 ; i <= strlen(data) ; i++)
11211                                 {
11212                                           if( i%2==0 )
11213                                           {
11214                                                    tmp[j]=' ';
11215                                                    j++;
11216                                           }
11217                                         if ( data[i] != '\0' )
11218                                                 tmp[j] = data[i];
11219                                           
11220                                           j++;
11221                                 }
11222                                 pch = tmp;              
11223                                 DBG_871X("pch=%s",pch);
11224                                 
11225                                 while( *pch != '\0' )
11226                                 {
11227                                         pnext = strpbrk(pch, " ");
11228                                         if (!pnext)
11229                                                 break;
11230                                         
11231                                         pnext++;
11232                                         if ( *pnext != '\0' )
11233                                         {
11234                                                   strtout = simple_strtoul (pnext , &ptmp, 16);
11235                                                   sprintf( extra, "%s %d" ,extra ,strtout );
11236                                         }
11237                                         else{
11238                         break;
11239                                         }
11240                                         pch = pnext;
11241                                 }
11242                         wrqu->length = strlen(extra);
11243                         break;
11244                         
11245                 default:
11246                         wrqu->length = 0;
11247                         ret = -EINVAL;
11248                         break;
11249                         
11250         }
11251
11252         return ret;
11253 }
11254
11255 /*
11256  * Input Format: %d,%x,%x
11257  *      %d is RF path, should be smaller than MAX_RF_PATH_NUMS
11258  *      1st %x is address(offset)
11259  *      2st %x is data to write
11260  */
11261  static int rtw_mp_write_rf(struct net_device *dev,
11262                         struct iw_request_info *info,
11263                         struct iw_point *wrqu, char *extra)
11264 {                       
11265 /*static int rtw_mp_write_rf(struct net_device *dev,
11266                         struct iw_request_info *info,
11267                         union iwreq_data *wrqu, char *extra)
11268 */
11269         u32 path, addr, data;
11270         int ret;
11271         PADAPTER padapter = rtw_netdev_priv(dev);
11272         char input[wrqu->length];
11273
11274
11275         _rtw_memset(input, 0, wrqu->length);
11276         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11277                          return -EFAULT;
11278
11279
11280         ret = sscanf(input, "%d,%x,%x", &path, &addr, &data);
11281         if (ret < 3) return -EINVAL;
11282
11283         if (path >= GET_HAL_RFPATH_NUM(padapter)) return -EINVAL;
11284         if (addr > 0xFF) return -EINVAL;
11285         if (data > 0xFFFFF) return -EINVAL;
11286         
11287         _rtw_memset(extra, 0, wrqu->length);
11288         
11289         write_rfreg(padapter, path, addr, data);
11290         
11291         sprintf(extra, "write_rf completed \n");
11292         wrqu->length = strlen(extra);
11293         
11294         return 0;
11295 }
11296
11297 /*
11298  * Input Format: %d,%x
11299  *      %d is RF path, should be smaller than MAX_RF_PATH_NUMS
11300  *      %x is address(offset)
11301  *
11302  * Return:
11303  *      %d for data readed
11304  */
11305 static int rtw_mp_read_rf(struct net_device *dev,
11306                         struct iw_request_info *info,
11307                         struct iw_point *wrqu, char *extra)
11308 {
11309         char input[wrqu->length];
11310         char *pch, *pnext, *ptmp;
11311         char data[20],tmp[20];
11312         //u32 *data = (u32*)extra;
11313         u32 path, addr;
11314         u32 ret,i=0 ,j=0,strtou=0;
11315         PADAPTER padapter = rtw_netdev_priv(dev);
11316
11317
11318         if (wrqu->length > 128) return -EFAULT;
11319         _rtw_memset(input, 0, wrqu->length);
11320         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11321                 return -EFAULT;
11322
11323         ret = sscanf(input, "%d,%x", &path, &addr);
11324         if (ret < 2) return -EINVAL;
11325
11326         if (path >= GET_HAL_RFPATH_NUM(padapter)) return -EINVAL;
11327         if (addr > 0xFF) return -EINVAL;
11328         
11329         _rtw_memset(extra, 0, wrqu->length);
11330         
11331         //*data = read_rfreg(padapter, path, addr);
11332         sprintf(data, "%08x", read_rfreg(padapter, path, addr));
11333                                 //add read data format blank
11334                                 for( i=0 ; i <= strlen(data) ; i++)
11335                                 {
11336                                           if( i%2==0 )
11337                                           {
11338                                                    tmp[j]=' ';
11339                                                    j++;
11340                                           }
11341                                           tmp[j] = data[i];
11342                                           j++;
11343                                 }
11344                                 pch = tmp;              
11345                                 DBG_871X("pch=%s",pch);
11346                                 
11347                                 while( *pch != '\0' )
11348                                 {
11349                                         pnext = strpbrk(pch, " ");
11350                                         if (!pnext)
11351                                                 break;
11352                                         pnext++;
11353                                         if ( *pnext != '\0' )
11354                                         {
11355                                                   strtou = simple_strtoul (pnext , &ptmp, 16);
11356                                                   sprintf( extra, "%s %d" ,extra ,strtou );
11357                                         }
11358                                         else{
11359                                                   break;
11360                                         }
11361                                         pch = pnext;
11362                                 }
11363                         wrqu->length = strlen(extra);   
11364
11365         return 0;
11366 }
11367
11368 static int rtw_mp_start(struct net_device *dev,
11369                         struct iw_request_info *info,
11370                         struct iw_point *wrqu, char *extra)
11371 {
11372         u8 val8;
11373         PADAPTER padapter = rtw_netdev_priv(dev);
11374         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
11375         struct hal_ops *pHalFunc = &padapter->HalFunc;
11376
11377         rtw_pm_set_ips(padapter,IPS_NONE);
11378         LeaveAllPowerSaveMode(padapter);
11379
11380         if(padapter->registrypriv.mp_mode ==0)
11381         {               
11382                 pHalFunc->hal_deinit(padapter);
11383                 padapter->registrypriv.mp_mode =1;
11384                 pHalFunc->hal_init(padapter);
11385
11386                 rtw_pm_set_ips(padapter,IPS_NONE);
11387                 LeaveAllPowerSaveMode(padapter);
11388         }
11389
11390         if (padapter->registrypriv.mp_mode == 0)
11391                 return -EPERM;
11392
11393         if (padapter->mppriv.mode == MP_OFF) {
11394                 if (mp_start_test(padapter) == _FAIL)
11395                         return -EPERM;
11396                 padapter->mppriv.mode = MP_ON;
11397                 MPT_PwrCtlDM(padapter,0);
11398         }
11399         padapter->mppriv.bmac_filter = _FALSE;
11400 #ifdef CONFIG_RTL8723B
11401 #ifdef CONFIG_USB_HCI
11402         rtw_write32(padapter, 0x765, 0x0000);
11403         rtw_write32(padapter, 0x948, 0x0280);
11404 #else
11405         rtw_write32(padapter, 0x765, 0x0000);
11406         rtw_write32(padapter, 0x948, 0x0000);
11407 #endif  
11408 #ifdef CONFIG_FOR_RTL8723BS_VQ0
11409         rtw_write32(padapter, 0x765, 0x0000);
11410         rtw_write32(padapter, 0x948, 0x0280);
11411 #endif
11412         rtw_write8(padapter, 0x66, 0x27); //Open BT uart Log
11413         rtw_write8(padapter, 0xc50, 0x20); //for RX init Gain
11414 #endif  
11415         ODM_Write_DIG(&pHalData->odmpriv,0x20);
11416
11417         return 0;
11418 }
11419
11420 static int rtw_mp_stop(struct net_device *dev,
11421                         struct iw_request_info *info,
11422                         struct iw_point *wrqu, char *extra)
11423 {
11424         PADAPTER padapter = rtw_netdev_priv(dev);
11425         struct hal_ops *pHalFunc = &padapter->HalFunc;
11426
11427         if(padapter->registrypriv.mp_mode ==1)
11428         {
11429                 
11430                 MPT_DeInitAdapter(padapter);
11431                 pHalFunc->hal_deinit(padapter);
11432                 padapter->registrypriv.mp_mode=0;
11433                 pHalFunc->hal_init(padapter);
11434         }
11435         
11436         if (padapter->mppriv.mode != MP_OFF) {
11437                 mp_stop_test(padapter);
11438                 padapter->mppriv.mode = MP_OFF;
11439         }
11440
11441         return 0;
11442 }
11443
11444 extern int wifirate2_ratetbl_inx(unsigned char rate);
11445
11446 static int rtw_mp_rate(struct net_device *dev,
11447                         struct iw_request_info *info,
11448                         struct iw_point *wrqu, char *extra)
11449 {
11450         u32 rate = MPT_RATE_1M;
11451         u8              input[wrqu->length];
11452         PADAPTER padapter = rtw_netdev_priv(dev);
11453
11454         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11455                         return -EFAULT;
11456                         
11457         rate = rtw_mpRateParseFunc(padapter,input);
11458
11459         if (rate ==0 && strcmp(input,"1M")!=0)
11460         {
11461         rate = rtw_atoi(input); 
11462         if(rate <= 0x7f)
11463                 rate = wifirate2_ratetbl_inx( (u8)rate);        
11464         else if (rate < 0xC8)
11465                 rate =(rate - 0x80 + MPT_RATE_MCS0);
11466                 //HT  rate 0x80(MCS0)  ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159 
11467         //VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179
11468         //VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199 
11469         //else
11470                 //VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153
11471         //      rate =(rate - MPT_RATE_VHT1SS_MCS0); 
11472         }
11473         _rtw_memset(extra, 0, wrqu->length);
11474
11475         sprintf( extra, "Set data rate to %s index %d" ,input,rate );
11476         DBG_871X("%s: %s rate index=%d \n", __func__,input,rate);
11477         
11478         if (rate >= MPT_RATE_LAST )     
11479                 return -EINVAL;
11480
11481         padapter->mppriv.rateidx = rate;
11482         Hal_SetDataRate(padapter);
11483         
11484         wrqu->length = strlen(extra);
11485         return 0;
11486 }
11487
11488 static int rtw_mp_channel(struct net_device *dev,
11489                         struct iw_request_info *info,
11490                         struct iw_point *wrqu, char *extra)
11491 {
11492
11493         PADAPTER padapter = rtw_netdev_priv(dev);
11494         HAL_DATA_TYPE   *pHalData       = GET_HAL_DATA(padapter);
11495         u8              input[wrqu->length];
11496         u32     channel = 1;
11497         int cur_ch_offset;
11498
11499         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11500                         return -EFAULT;
11501         
11502         channel = rtw_atoi(input);
11503         //DBG_871X("%s: channel=%d\n", __func__, channel);
11504         _rtw_memset(extra, 0, wrqu->length);
11505         sprintf( extra, "Change channel %d to channel %d", padapter->mppriv.channel , channel );
11506         padapter->mppriv.channel = channel;
11507         Hal_SetChannel(padapter);
11508         pHalData->CurrentChannel = channel;
11509
11510         wrqu->length = strlen(extra);
11511         return 0;
11512 }
11513
11514 static int rtw_mp_bandwidth(struct net_device *dev,
11515                         struct iw_request_info *info,
11516                         struct iw_point *wrqu, char *extra)
11517 {
11518         u32 bandwidth=0, sg=0;
11519         int cur_ch_offset;
11520         //u8 buffer[40];
11521         PADAPTER padapter = rtw_netdev_priv(dev);
11522         HAL_DATA_TYPE   *pHalData       = GET_HAL_DATA(padapter);
11523         //if (copy_from_user(buffer, (void*)wrqu->data.pointer, wrqu->data.length))
11524     //            return -EFAULT;
11525                 
11526         //DBG_871X("%s:iwpriv in=%s\n", __func__, extra);
11527         
11528         sscanf(extra, "40M=%d,shortGI=%d", &bandwidth, &sg);
11529         
11530         if (bandwidth == 1)
11531                 bandwidth=CHANNEL_WIDTH_40;
11532         else if (bandwidth == 2)
11533                 bandwidth=CHANNEL_WIDTH_80;
11534         DBG_871X("%s: bw=%d sg=%d \n", __func__, bandwidth , sg);
11535         
11536         padapter->mppriv.bandwidth = (u8)bandwidth;
11537         padapter->mppriv.preamble = sg;
11538         
11539         SetBandwidth(padapter);
11540         pHalData->CurrentChannelBW = bandwidth;
11541         //cur_ch_offset =  rtw_get_offset_by_ch(padapter->mppriv.channel);
11542         //set_channel_bwmode(padapter, padapter->mppriv.channel, cur_ch_offset, bandwidth);
11543
11544         return 0;
11545 }
11546
11547
11548 static int rtw_mp_txpower_index(struct net_device *dev,
11549                         struct iw_request_info *info,
11550                         struct iw_point *wrqu, char *extra)
11551 {
11552         PADAPTER padapter = rtw_netdev_priv(dev);
11553         char input[wrqu->length];
11554         u32 rfpath;
11555         u32 txpower_inx;
11556
11557         if (wrqu->length > 128)
11558                 return -EFAULT;
11559
11560         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11561                 return -EFAULT;
11562
11563         rfpath = rtw_atoi(input);
11564         txpower_inx = mpt_ProQueryCalTxPower(padapter, rfpath);
11565         sprintf(extra, " %d", txpower_inx);
11566         wrqu->length = strlen(extra);
11567
11568         return 0;
11569 }
11570
11571
11572 static int rtw_mp_txpower(struct net_device *dev,
11573                         struct iw_request_info *info,
11574                         struct iw_point *wrqu, char *extra)
11575 {
11576         u32 idx_a = 0, idx_b = 0, idx_c = 0, idx_d = 0, status = 0;
11577         int MsetPower = 1;
11578         u8              input[wrqu->length];
11579
11580         PADAPTER padapter = rtw_netdev_priv(dev);
11581
11582         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11583                         return -EFAULT;
11584
11585         MsetPower = strncmp(input, "off", 3);
11586         if (MsetPower == 0) {
11587                 padapter->mppriv.bSetTxPower = 0;
11588                 sprintf( extra, "MP Set power off");
11589         } else {
11590                 if (sscanf(input, "patha=%d,pathb=%d,pathc=%d,pathd=%d", &idx_a, &idx_b, &idx_c, &idx_d) < 3)
11591                         DBG_871X("Invalid format on line %s ,patha=%d,pathb=%d,pathc=%d,pathd=%d\n", input , idx_a , idx_b , idx_c , idx_d);
11592
11593                 sprintf(extra, "Set power level path_A:%d path_B:%d path_C:%d path_D:%d", idx_a , idx_b , idx_c , idx_d);
11594                 padapter->mppriv.txpoweridx = (u8)idx_a;
11595                 padapter->mppriv.txpoweridx_b = (u8)idx_b;
11596                 padapter->mppriv.txpoweridx_c = (u8)idx_c;
11597                 padapter->mppriv.txpoweridx_d = (u8)idx_d;
11598                 padapter->mppriv.bSetTxPower = 1;
11599
11600                 Hal_SetAntennaPathPower(padapter);
11601         }
11602
11603         wrqu->length = strlen(extra);
11604         return 0;
11605 }
11606
11607 static int rtw_mp_ant_tx(struct net_device *dev,
11608                         struct iw_request_info *info,
11609                         struct iw_point *wrqu, char *extra)
11610 {
11611         u8 i;
11612         u8              input[wrqu->length];
11613         u16 antenna = 0;
11614         PADAPTER padapter = rtw_netdev_priv(dev);
11615         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
11616
11617         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11618                         return -EFAULT;
11619                         
11620         //DBG_871X("%s: input=%s\n", __func__, input);  
11621         
11622         sprintf( extra, "switch Tx antenna to %s", input);
11623         
11624         for (i=0; i < strlen(input); i++)
11625         {
11626                 switch(input[i])
11627                         {
11628                                 case 'a':
11629                                                                 antenna |= ANTENNA_A;
11630                                                                 break;
11631                                 case 'b':
11632                                                                 antenna |= ANTENNA_B;
11633                                                                 break;
11634                                 case 'c':
11635                                                                 antenna |= ANTENNA_C;
11636                                                                 break;
11637                                 case 'd':
11638                                                                 antenna |= ANTENNA_D;
11639                                                                 break;                          
11640                         }
11641         }
11642         //antenna |= BIT(extra[i]-'a');
11643         DBG_871X("%s: antenna=0x%x\n", __func__, antenna);
11644         padapter->mppriv.antenna_tx = antenna;
11645         padapter->mppriv.antenna_rx = antenna;
11646         //DBG_871X("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_tx);
11647         pHalData->AntennaTxPath = antenna;
11648         
11649         Hal_SetAntenna(padapter);
11650
11651         wrqu->length = strlen(extra);
11652         return 0;
11653 }
11654
11655 static int rtw_mp_ant_rx(struct net_device *dev,
11656                         struct iw_request_info *info,
11657                         struct iw_point *wrqu, char *extra)
11658 {
11659         u8 i;
11660         u16 antenna = 0;
11661         u8              input[wrqu->length];
11662         PADAPTER padapter = rtw_netdev_priv(dev);
11663         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
11664         
11665         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11666                         return -EFAULT;
11667         //DBG_871X("%s: input=%s\n", __func__, input);
11668         _rtw_memset(extra, 0, wrqu->length);
11669         
11670         sprintf( extra, "switch Rx antenna to %s", input );
11671         
11672         for (i=0; i < strlen(input); i++) {
11673         switch( input[i] )
11674                         {
11675                                 case 'a':
11676                                                                 antenna |= ANTENNA_A;
11677                                                                 break;
11678                                 case 'b':
11679                                                                 antenna |= ANTENNA_B;
11680                                                                 break;
11681                                 case 'c':
11682                                                                 antenna |= ANTENNA_C;
11683                                                                 break;
11684                                 case 'd':
11685                                                                 antenna |= ANTENNA_D;
11686                                                                 break;
11687                         }
11688         }
11689         
11690         DBG_871X("%s: antenna=0x%x\n", __func__, antenna);
11691         padapter->mppriv.antenna_tx = antenna;
11692         padapter->mppriv.antenna_rx = antenna;
11693         pHalData->AntennaRxPath = antenna;
11694         //DBG_871X("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_rx);
11695         Hal_SetAntenna(padapter);
11696         wrqu->length = strlen(extra);
11697         
11698         return 0;
11699 }
11700
11701 static int rtw_set_ctx_destAddr(struct net_device *dev,
11702                         struct iw_request_info *info,
11703                         struct iw_point *wrqu, char *extra)
11704 {
11705         int jj,kk=0;
11706         
11707         struct pkt_attrib *pattrib;
11708         struct mp_priv *pmp_priv;
11709         PADAPTER padapter = rtw_netdev_priv(dev);
11710         pmp_priv = &padapter->mppriv;
11711         pattrib = &pmp_priv->tx.attrib;
11712
11713         if( strlen(extra) < 5 )
11714                 return _FAIL;
11715                 
11716         DBG_871X("%s: in=%s\n", __func__, extra);
11717         for(jj = 0,kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
11718         {
11719                 pattrib->dst[ jj ] = key_2char2num( extra[kk], extra[kk+ 1] );
11720         }
11721
11722         DBG_871X("pattrib->dst:%x %x %x %x %x %x\n",pattrib->dst[0],pattrib->dst[1],pattrib->dst[2],pattrib->dst[3],pattrib->dst[4],pattrib->dst[5]);
11723         return 0;
11724 }
11725
11726 static int rtw_mp_ctx(struct net_device *dev,
11727                         struct iw_request_info *info,
11728                         struct iw_point *wrqu, char *extra)
11729 {
11730         u32 pkTx = 1;
11731         int countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
11732         u32 bStartTest = 1;
11733         u32 count = 0,pktinterval=0,pktlen=0;
11734         struct mp_priv *pmp_priv;
11735         struct pkt_attrib *pattrib;
11736         PADAPTER padapter = rtw_netdev_priv(dev);
11737         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
11738
11739         pmp_priv = &padapter->mppriv;
11740         pattrib = &pmp_priv->tx.attrib;
11741
11742         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
11743                         return -EFAULT;
11744                         
11745         DBG_871X("%s: in=%s\n", __func__, extra);
11746
11747         countPkTx = strncmp(extra, "count=", 5); // strncmp TRUE is 0
11748         cotuTx = strncmp(extra, "background", 20);
11749         CarrSprTx = strncmp(extra, "background,cs", 20);
11750         scTx = strncmp(extra, "background,sc", 20);
11751         sgleTx = strncmp(extra, "background,stone", 20);
11752         pkTx = strncmp(extra, "background,pkt", 20);
11753         stop = strncmp(extra, "stop", 4);
11754         sscanf(extra, "count=%d,pkt", &count);
11755         sscanf(extra, "pktinterval=%d", &pktinterval);
11756         sscanf(extra, "pktlen=%d", &pktlen);
11757         
11758         if ( _rtw_memcmp( extra, "destmac=", 8 ) )
11759         {
11760                 wrqu->length -= 8;
11761                 rtw_set_ctx_destAddr (dev,info,wrqu,&extra[8]);
11762                 sprintf( extra, "Set dest mac OK ! \n");
11763                 return 0;
11764         }
11765         
11766         //DBG_871X("%s: count=%d countPkTx=%d cotuTx=%d CarrSprTx=%d scTx=%d sgleTx=%d pkTx=%d stop=%d\n", __func__, count, countPkTx, cotuTx, CarrSprTx, pkTx, sgleTx, scTx, stop);
11767         _rtw_memset(extra, '\0', strlen(extra));
11768
11769         if( pktinterval !=0 )
11770         {
11771                 sprintf( extra, "Pkt Interval = %d",pktinterval);
11772                 padapter->mppriv.pktInterval = pktinterval;
11773                 wrqu->length = strlen(extra);
11774                 return 0;
11775         }
11776         if( pktlen !=0 )
11777         {
11778                 sprintf( extra, "Pkt len = %d",pktlen);
11779                 pattrib->pktlen = pktlen ;
11780                 wrqu->length = strlen(extra);
11781                 return 0;
11782         }
11783         if (stop == 0) {
11784                 bStartTest = 0; // To set Stop
11785                 pmp_priv->tx.stop = 1;
11786                 sprintf( extra, "Stop continuous Tx");
11787         } else {
11788                 bStartTest = 1;
11789                 if (pmp_priv->mode != MP_ON) {
11790                         if (pmp_priv->tx.stop != 1) {
11791                                 DBG_871X("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
11792                                 return  -EFAULT;
11793                         }
11794                 }
11795         }
11796
11797         if (pkTx == 0 || countPkTx == 0)
11798                 pmp_priv->mode = MP_PACKET_TX;
11799         if (sgleTx == 0)
11800                 pmp_priv->mode = MP_SINGLE_TONE_TX;
11801         if (cotuTx == 0)
11802                 pmp_priv->mode = MP_CONTINUOUS_TX;
11803         if (CarrSprTx == 0)
11804                 pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
11805         if (scTx == 0)
11806                 pmp_priv->mode = MP_SINGLE_CARRIER_TX;
11807
11808         switch (pmp_priv->mode)
11809         {
11810                 case MP_PACKET_TX:
11811                 
11812                         //DBG_871X("%s:pkTx %d\n", __func__,bStartTest);
11813                         if (bStartTest == 0)
11814                         {
11815                                 pmp_priv->tx.stop = 1;
11816                                 pmp_priv->mode = MP_ON;
11817                                 sprintf( extra, "Stop continuous Tx");
11818                         }
11819                         else if (pmp_priv->tx.stop == 1)
11820                         {
11821                                 sprintf( extra, "Start continuous DA=ffffffffffff len=1500 count=%u\n",count);
11822                                 //DBG_871X("%s:countPkTx %d\n", __func__,count);
11823                                 pmp_priv->tx.stop = 0;
11824                                 pmp_priv->tx.count = count;
11825                         
11826                                 SetPacketTx(padapter);
11827                         } 
11828                         else {
11829                                 //DBG_871X("%s: pkTx not stop\n", __func__);
11830                                 return -EFAULT;
11831                         }
11832                                 wrqu->length = strlen(extra);
11833                                 return 0;
11834
11835                 case MP_SINGLE_TONE_TX:
11836                         //DBG_871X("%s: sgleTx %d \n", __func__, bStartTest);
11837                         if (bStartTest != 0){
11838                                 sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
11839             }
11840                         Hal_SetSingleToneTx(padapter, (u8)bStartTest);
11841                         break;
11842
11843                 case MP_CONTINUOUS_TX:
11844                         //DBG_871X("%s: cotuTx %d\n", __func__, bStartTest);
11845                         if (bStartTest != 0){
11846                                 sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
11847                          }
11848                         Hal_SetContinuousTx(padapter, (u8)bStartTest);
11849                         break;
11850
11851                 case MP_CARRIER_SUPPRISSION_TX:
11852                         //DBG_871X("%s: CarrSprTx %d\n", __func__, bStartTest);
11853                         if (bStartTest != 0){
11854                                 if( pmp_priv->rateidx <= MPT_RATE_11M ) 
11855                                 {
11856                                         sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
11857                                         
11858                                 }else
11859                                         sprintf( extra, "Specify carrier suppression but not CCK rate");
11860                         }
11861                         Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
11862                         break;
11863
11864                 case MP_SINGLE_CARRIER_TX:
11865                         //DBG_871X("%s: scTx %d\n", __func__, bStartTest);
11866                         if (bStartTest != 0){
11867                                 sprintf( extra, "Start continuous DA=ffffffffffff len=1500 \n infinite=yes.");
11868                         }
11869                         Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
11870                         break;
11871
11872                 default:
11873                         //DBG_871X("%s:No Match MP_MODE\n", __func__);
11874                         sprintf( extra, "Error! Continuous-Tx is not on-going.");
11875                         return -EFAULT;
11876         }
11877
11878         if ( bStartTest==1 && pmp_priv->mode != MP_ON) {
11879                 struct mp_priv *pmp_priv = &padapter->mppriv;
11880                 if (pmp_priv->tx.stop == 0) {
11881                         pmp_priv->tx.stop = 1;
11882                         //DBG_871X("%s: pkt tx is running...\n", __func__);
11883                         rtw_msleep_os(5);
11884                 }
11885 #ifdef CONFIG_80211N_HT
11886                 pmp_priv->tx.attrib.ht_en = 1;
11887 #endif
11888                 pmp_priv->tx.stop = 0;
11889                 pmp_priv->tx.count = 1;
11890                 SetPacketTx(padapter);
11891         } else {
11892                 pmp_priv->mode = MP_ON;
11893         }
11894
11895         wrqu->length = strlen(extra);
11896         return 0;
11897 }
11898
11899
11900 static int rtw_mp_disable_bt_coexist(struct net_device *dev,
11901                         struct iw_request_info *info,
11902                         union iwreq_data *wrqu, char *extra)
11903 {
11904         PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
11905         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);     
11906         struct hal_ops *pHalFunc = &padapter->HalFunc;
11907         
11908         u8 input[wrqu->data.length];
11909         u32 bt_coexist;
11910
11911         if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
11912                 return -EFAULT;
11913         
11914         bt_coexist = rtw_atoi(input);
11915         
11916         if( bt_coexist == 0 )
11917         {
11918                 RT_TRACE(_module_mp_, _drv_info_,
11919                         ("Set OID_RT_SET_DISABLE_BT_COEXIST: disable BT_COEXIST\n"));
11920                 DBG_871X("Set OID_RT_SET_DISABLE_BT_COEXIST: disable BT_COEXIST\n");
11921 #ifdef CONFIG_BT_COEXIST
11922                 rtw_btcoex_HaltNotify(padapter);
11923                 rtw_btcoex_SetManualControl(padapter, _TRUE);           
11924                 // Force to switch Antenna to WiFi
11925                 rtw_write16(padapter, 0x870, 0x300);
11926                 rtw_write16(padapter, 0x860, 0x110); 
11927 #endif // CONFIG_BT_COEXIST
11928         }
11929         else
11930         {
11931                 RT_TRACE(_module_mp_, _drv_info_,
11932                         ("Set OID_RT_SET_DISABLE_BT_COEXIST: enable BT_COEXIST\n"));
11933 #ifdef CONFIG_BT_COEXIST                        
11934                 rtw_btcoex_SetManualControl(padapter, _FALSE);
11935 #endif
11936         }
11937
11938         return 0;       
11939 }
11940
11941
11942 static int rtw_mp_arx(struct net_device *dev,
11943                         struct iw_request_info *info,
11944                         struct iw_point *wrqu, char *extra)
11945 {
11946         int bStartRx = 0, bStopRx = 0, bQueryPhy = 0, bQueryMac = 0, bSetBssid = 0;
11947         int bmac_filter = 0, bfilter_init = 0, bmon = 0, bSmpCfg = 0;
11948         u8              input[wrqu->length];
11949         char *pch, *ptmp, *token, *tmp[2]={0x00,0x00};
11950         u32 i = 0, ii = 0, jj = 0, kk = 0, cnts = 0, ret;
11951         PADAPTER padapter = rtw_netdev_priv(dev);
11952         struct mp_priv *pmppriv = &padapter->mppriv;
11953         struct dbg_rx_counter rx_counter;
11954
11955         if (copy_from_user(input, wrqu->pointer, wrqu->length))
11956                         return -EFAULT;
11957
11958         DBG_871X("%s: %s\n", __func__, input);
11959
11960         bStartRx = (strncmp(input, "start", 5)==0)?1:0; // strncmp TRUE is 0
11961         bStopRx = (strncmp(input, "stop", 5)==0)?1:0; // strncmp TRUE is 0
11962         bQueryPhy = (strncmp(input, "phy", 3)==0)?1:0; // strncmp TRUE is 0
11963         bQueryMac = (strncmp(input, "mac", 3)==0)?1:0; // strncmp TRUE is 0
11964         bSetBssid = (strncmp(input, "setbssid=", 8)==0)?1:0; // strncmp TRUE is 0
11965         //bfilter_init = (strncmp(input, "filter_init",11)==0)?1:0;
11966         bmac_filter = (strncmp(input, "accept_mac",10)==0)?1:0;
11967         bmon = (strncmp(input, "mon=",4)==0)?1:0;
11968         bSmpCfg = (strncmp(input , "smpcfg=" , 7) == 0)?1:0;
11969
11970         if(bSetBssid==1){
11971                 pch = input;
11972                 while ((token = strsep(&pch, "=")) != NULL)
11973                 {
11974                         if (i > 1) break;
11975                         tmp[i] = token;
11976                         i++;
11977                 }
11978                 if ((tmp[0]==NULL) && (tmp[1]==NULL)){
11979                         return -EFAULT;
11980                 }
11981                 else{
11982                         cnts = strlen(tmp[1])/2;
11983                         if (cnts<1) return -EFAULT;
11984                         DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
11985                         DBG_871X("%s: data=%s\n", __FUNCTION__, tmp[1]);
11986                         for (jj=0, kk=0; jj < cnts ; jj++, kk+=2){
11987                                          pmppriv->network_macaddr[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+1]);
11988                                         DBG_871X("network_macaddr[%d]=%x \n",jj, pmppriv->network_macaddr[jj]);
11989                         }
11990                 }
11991                 pmppriv->bSetRxBssid = _TRUE;
11992         }
11993
11994         if(bmac_filter)
11995         {
11996                 pmppriv->bmac_filter = bmac_filter;
11997                 pch = input;
11998                 while ((token = strsep(&pch, "=")) != NULL)
11999                 {
12000                         if (i > 1) break;
12001                         tmp[i] = token;
12002                         i++;
12003                 }
12004                 if ((tmp[0]==NULL) && (tmp[1]==NULL)){
12005                         return -EFAULT;
12006                 }
12007                 else{
12008                         cnts = strlen(tmp[1])/2;
12009                         if (cnts<1) return -EFAULT;
12010                         DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
12011                         DBG_871X("%s: data=%s\n", __FUNCTION__, tmp[1]);
12012                         for (jj=0, kk=0; jj < cnts ; jj++, kk+=2){
12013                                         pmppriv->mac_filter[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+1]);
12014                                         DBG_871X("%s mac_filter[%d]=%x \n",__FUNCTION__,jj, pmppriv->mac_filter[jj]);
12015                         }
12016                 }
12017         }
12018         
12019         if(bStartRx)
12020         {
12021                 sprintf( extra, "start");
12022                 SetPacketRx(padapter, bStartRx, _FALSE);
12023         }
12024         else if(bStopRx)
12025         {
12026                 SetPacketRx(padapter, bStartRx, _FALSE);
12027                 pmppriv->bmac_filter = _FALSE;
12028                 sprintf( extra, "Received packet OK:%d CRC error:%d ,Filter out:%d",padapter->mppriv.rx_pktcount,padapter->mppriv.rx_crcerrpktcount,padapter->mppriv.rx_pktcount_filter_out);
12029         }
12030         else if(bQueryPhy)
12031         {
12032                 _rtw_memset(&rx_counter,0,sizeof(struct dbg_rx_counter));
12033                 rtw_dump_phy_rx_counters(padapter,&rx_counter);
12034                 
12035                 DBG_871X("%s: OFDM_FA =%d\n", __FUNCTION__, rx_counter.rx_ofdm_fa);
12036                 DBG_871X("%s: CCK_FA =%d\n", __FUNCTION__, rx_counter.rx_cck_fa);
12037                 sprintf( extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d",rx_counter.rx_pkt_ok,rx_counter.rx_pkt_crc_error,rx_counter.rx_cck_fa+rx_counter.rx_ofdm_fa);
12038                 
12039         
12040         }
12041         else if(bQueryMac)
12042         {
12043                 _rtw_memset(&rx_counter,0,sizeof(struct dbg_rx_counter));
12044                 rtw_dump_mac_rx_counters(padapter,&rx_counter);
12045                 sprintf( extra, "Mac Received packet OK: %d , CRC error: %d , Drop Packets: %d\n",
12046                                 rx_counter.rx_pkt_ok,rx_counter.rx_pkt_crc_error,rx_counter.rx_pkt_drop);                       
12047
12048         }
12049
12050         if( bmon==1 ) { 
12051                 sscanf(input, "mon=%d", &bmon);
12052                 
12053                 if(bmon==1)
12054                 {
12055                         pmppriv->rx_bindicatePkt= _TRUE;
12056                         sprintf( extra, "Indicating Receive Packet to network start\n");
12057                 }else {
12058                         pmppriv->rx_bindicatePkt= _FALSE;
12059                         sprintf( extra, "Indicating Receive Packet to network Stop\n");
12060                 }       
12061         }
12062         if (bSmpCfg == 1) {     
12063                 ret = sscanf(input, "smpcfg=%d", &bSmpCfg);
12064                 
12065                 if (bSmpCfg == 1) {
12066                         pmppriv->bRTWSmbCfg = _TRUE;
12067                         sprintf(extra , "Indicate By Simple Config Format\n");
12068                         SetPacketRx(padapter, _TRUE, _TRUE);
12069                 } else {
12070                         pmppriv->bRTWSmbCfg = _FALSE;
12071                         sprintf(extra , "Indicate By Normal Format\n");
12072                         SetPacketRx(padapter, _TRUE, _FALSE);
12073                 }
12074         }
12075         
12076         wrqu->length = strlen(extra) + 1;
12077
12078         return 0;
12079 }
12080
12081 static int rtw_mp_trx_query(struct net_device *dev,
12082                         struct iw_request_info *info,
12083                         struct iw_point *wrqu, char *extra)
12084 {
12085         u32 txok,txfail,rxok,rxfail,rxfilterout;
12086         PADAPTER padapter = rtw_netdev_priv(dev);
12087         //if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
12088         //      return -EFAULT;
12089
12090         txok=padapter->mppriv.tx.sended;
12091         txfail=0;
12092         rxok = padapter->mppriv.rx_pktcount;
12093         rxfail = padapter->mppriv.rx_crcerrpktcount;
12094         rxfilterout = padapter->mppriv.rx_pktcount_filter_out;
12095
12096         _rtw_memset(extra, '\0', 128);
12097
12098         sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ,Rx Filter out:%d \n", txok, txfail,rxok,rxfail,rxfilterout);
12099
12100         wrqu->length=strlen(extra)+1;
12101
12102         return 0;
12103 }
12104
12105 static int rtw_mp_pwrtrk(struct net_device *dev,
12106                         struct iw_request_info *info,
12107                         struct iw_point *wrqu, char *extra)
12108 {
12109         u8 enable;
12110         u32 thermal;
12111         s32 ret;
12112         PADAPTER padapter = rtw_netdev_priv(dev);
12113         HAL_DATA_TYPE                   *pHalData = GET_HAL_DATA(padapter);
12114         u8              input[wrqu->length];
12115
12116         if (copy_from_user(input, wrqu->pointer, wrqu->length))
12117                         return -EFAULT;
12118
12119         _rtw_memset(extra, 0, wrqu->length);
12120
12121         enable = 1;
12122         if (wrqu->length > 1) { // not empty string
12123                 if (strncmp(input, "stop", 4) == 0)
12124                 {       
12125                         enable = 0;
12126                         sprintf(extra, "mp tx power tracking stop");            
12127                 }
12128                 else if (sscanf(input, "ther=%d", &thermal)) {          
12129                         ret = Hal_SetThermalMeter(padapter, (u8)thermal);
12130                         if (ret == _FAIL) return -EPERM;
12131                                 sprintf(extra, "mp tx power tracking start,target value=%d ok ",thermal);
12132                 }else{
12133                         return -EINVAL;
12134                 }
12135         }
12136
12137         ret = Hal_SetPowerTracking(padapter, enable);
12138         if (ret == _FAIL) return -EPERM;
12139
12140         wrqu->length = strlen(extra);
12141
12142         return 0;
12143 }
12144
12145 static int rtw_mp_psd(struct net_device *dev,
12146                         struct iw_request_info *info,
12147                         struct iw_point *wrqu, char *extra)
12148 {
12149         PADAPTER padapter = rtw_netdev_priv(dev);
12150         u8              input[wrqu->length];
12151         
12152         if (copy_from_user(input, wrqu->pointer, wrqu->length))
12153                 return -EFAULT;
12154         
12155         strcpy(extra,input);
12156         
12157         wrqu->length = mp_query_psd(padapter, extra);
12158         
12159         return 0;
12160 }
12161
12162 static int rtw_mp_thermal(struct net_device *dev,
12163                         struct iw_request_info *info,
12164                         struct iw_point *wrqu, char *extra)
12165 {
12166         u8 val;
12167         int bwrite=1;   
12168         
12169         #ifdef CONFIG_RTL8188E
12170                         u16 addr=EEPROM_THERMAL_METER_88E;
12171         #endif
12172         #if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A)
12173                         u16 addr=EEPROM_THERMAL_METER_8812;
12174         #endif
12175         #ifdef CONFIG_RTL8192E
12176                         u16 addr=EEPROM_THERMAL_METER_8192E;
12177         #endif
12178         #ifdef CONFIG_RTL8723B
12179                         u16 addr=EEPROM_THERMAL_METER_8723B;
12180         #endif
12181         u16 cnt=1;
12182         u16 max_available_size=0;
12183         PADAPTER padapter = rtw_netdev_priv(dev);       
12184
12185         if (copy_from_user(extra, wrqu->pointer, wrqu->length))
12186                 return -EFAULT;
12187
12188         //DBG_871X("print extra %s \n",extra); 
12189          
12190          bwrite = strncmp(extra, "write", 6); // strncmp TRUE is 0
12191          
12192          Hal_GetThermalMeter(padapter, &val);
12193          
12194          if( bwrite == 0 )      
12195          {
12196                  //DBG_871X("to write val:%d",val);
12197                         EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
12198                         if( 2 > max_available_size )
12199                         {                       
12200                                 DBG_871X("no available efuse!\n");
12201                                 return -EFAULT;
12202                         }       
12203                         if ( rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL )
12204                         {
12205                                 DBG_871X("rtw_efuse_map_write error \n");                       
12206                                 return -EFAULT;
12207                         } 
12208                         else
12209                         {
12210                                  sprintf(extra, " efuse write ok :%d", val);    
12211                         }
12212           }
12213           else
12214           {
12215                          sprintf(extra, "%d", val);
12216           }
12217         wrqu->length = strlen(extra);
12218         
12219         return 0;
12220 }
12221
12222 static int rtw_mp_reset_stats(struct net_device *dev,
12223                         struct iw_request_info *info,
12224                         struct iw_point *wrqu, char *extra)
12225 {
12226         struct mp_priv *pmp_priv;
12227         struct pkt_attrib *pattrib;
12228         PADAPTER padapter = rtw_netdev_priv(dev);
12229         
12230         pmp_priv = &padapter->mppriv;
12231         
12232         pmp_priv->tx.sended = 0;
12233         pmp_priv->tx_pktcount = 0;
12234         pmp_priv->rx_pktcount = 0;
12235         pmp_priv->rx_pktcount_filter_out=0;
12236         pmp_priv->rx_crcerrpktcount = 0;
12237
12238         rtw_reset_phy_rx_counters(padapter);
12239         rtw_reset_mac_rx_counters(padapter);
12240
12241         return 0;
12242 }
12243
12244 static int rtw_mp_dump(struct net_device *dev,
12245                         struct iw_request_info *info,
12246                         struct iw_point *wrqu, char *extra)
12247 {
12248         struct mp_priv *pmp_priv;
12249         struct pkt_attrib *pattrib;
12250         u32 value;
12251     u8          input[wrqu->length];
12252         u8 rf_type,path_nums = 0;
12253         u32 i,j=1,path;
12254         PADAPTER padapter = rtw_netdev_priv(dev);
12255         
12256         pmp_priv = &padapter->mppriv;
12257
12258         if (copy_from_user(input, wrqu->pointer, wrqu->length))
12259                 return -EFAULT;
12260         
12261         if ( strncmp(input, "all", 4)==0 )
12262         {
12263                 mac_reg_dump(RTW_DBGDUMP, padapter);
12264                 bb_reg_dump(RTW_DBGDUMP, padapter);
12265                 rf_reg_dump(RTW_DBGDUMP, padapter);
12266         }
12267         return 0;
12268 }
12269
12270 static int rtw_mp_phypara(struct net_device *dev,
12271                         struct iw_request_info *info,
12272                         struct iw_point *wrqu, char *extra)
12273 {
12274
12275         PADAPTER padapter = rtw_netdev_priv(dev);
12276         HAL_DATA_TYPE   *pHalData       = GET_HAL_DATA(padapter);
12277         char    input[wrqu->length];
12278         u32             valxcap;
12279         
12280         if (copy_from_user(input, wrqu->pointer, wrqu->length))
12281                         return -EFAULT;
12282         
12283         DBG_871X("%s:iwpriv in=%s\n", __func__, input);
12284         
12285         sscanf(input, "xcap=%d", &valxcap);
12286
12287         pHalData->CrystalCap = (u8)valxcap;
12288         Hal_ProSetCrystalCap( padapter , valxcap );
12289
12290         sprintf( extra, "Set xcap=%d",valxcap );
12291         wrqu->length = strlen(extra) + 1;
12292         
12293 return 0;
12294
12295 }
12296
12297 static int rtw_mp_SetRFPath(struct net_device *dev,
12298                         struct iw_request_info *info,
12299                         union iwreq_data *wrqu, char *extra)
12300 {
12301         PADAPTER padapter = rtw_netdev_priv(dev);
12302         char    input[wrqu->data.length];
12303         int             bMain = 1, bTurnoff = 1;
12304         
12305         if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
12306                         return -EFAULT;
12307         DBG_871X("%s:iwpriv in=%s\n", __func__, input); 
12308         
12309         bMain = strncmp(input, "1", 2); // strncmp TRUE is 0
12310         bTurnoff = strncmp(input, "0", 3); // strncmp TRUE is 0
12311
12312         if(bMain==0)
12313         {
12314                 MP_PHY_SetRFPathSwitch(padapter,_TRUE);
12315                 DBG_871X("%s:PHY_SetRFPathSwitch=TRUE\n", __func__);    
12316         }
12317         else if(bTurnoff==0)
12318         {
12319                 MP_PHY_SetRFPathSwitch(padapter,_FALSE);
12320                 DBG_871X("%s:PHY_SetRFPathSwitch=FALSE\n", __func__);   
12321         }
12322         
12323         return 0;
12324 }
12325
12326 static int rtw_mp_QueryDrv(struct net_device *dev,
12327                         struct iw_request_info *info,
12328                         union iwreq_data *wrqu, char *extra)
12329 {
12330         PADAPTER padapter = rtw_netdev_priv(dev);
12331         char    input[wrqu->data.length];
12332         int     qAutoLoad = 1;
12333
12334         PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
12335         
12336         if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
12337                         return -EFAULT;
12338         DBG_871X("%s:iwpriv in=%s\n", __func__, input); 
12339         
12340         qAutoLoad = strncmp(input, "autoload", 8); // strncmp TRUE is 0
12341
12342         if(qAutoLoad==0)
12343         {
12344                 DBG_871X("%s:qAutoLoad\n", __func__);
12345                 
12346                 if(pHalData->bautoload_fail_flag)
12347                         sprintf(extra, "fail");
12348                 else
12349                 sprintf(extra, "ok");      
12350         }
12351                 wrqu->data.length = strlen(extra) + 1;
12352         return 0;
12353 }
12354
12355 /* update Tx AGC offset */
12356 static int rtw_mp_antBdiff(struct net_device *dev,
12357                         struct iw_request_info *info,
12358                         struct iw_point *wrqu, char *extra)
12359 {
12360
12361
12362         // MPT_ProSetTxAGCOffset
12363         return 0;
12364 }
12365
12366
12367 static int rtw_mp_PwrCtlDM(struct net_device *dev,
12368                         struct iw_request_info *info,
12369                         struct iw_point *wrqu, char *extra)
12370 {
12371         PADAPTER padapter = rtw_netdev_priv(dev);
12372         u8              input[wrqu->length];
12373         int             bstart=1;
12374         
12375         if (copy_from_user(input, wrqu->pointer, wrqu->length))
12376                         return -EFAULT;
12377
12378         bstart = strncmp(input, "start", 5); // strncmp TRUE is 0
12379         if(bstart==0){
12380                 sprintf(extra, "PwrCtlDM start \n");
12381                 MPT_PwrCtlDM(padapter,1);
12382         }else{
12383                 sprintf(extra, "PwrCtlDM stop \n");
12384                 MPT_PwrCtlDM(padapter,0);
12385         }
12386         wrqu->length = strlen(extra);
12387
12388         return 0;
12389 }
12390
12391 static int rtw_mp_getver(struct net_device *dev,
12392                         struct iw_request_info *info,
12393                         union iwreq_data *wrqu, char *extra)
12394 {
12395         PADAPTER padapter = rtw_netdev_priv(dev);
12396         struct mp_priv *pmp_priv;
12397         
12398         pmp_priv = &padapter->mppriv;
12399         
12400         if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
12401                         return -EFAULT;
12402
12403         sprintf(extra, "rtwpriv=%d\n",RTWPRIV_VER_INFO);
12404         wrqu->data.length = strlen(extra);
12405         return 0;
12406 }
12407
12408 static int rtw_mp_mon(struct net_device *dev,
12409                         struct iw_request_info *info,
12410                         union iwreq_data *wrqu, char *extra)
12411 {
12412         PADAPTER padapter = rtw_netdev_priv(dev);
12413         struct mp_priv *pmp_priv = &padapter->mppriv;
12414         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
12415         struct hal_ops *pHalFunc = &padapter->HalFunc;
12416         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
12417         int bstart = 1, bstop = 1;
12418         networkType=Ndis802_11Infrastructure;
12419         if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
12420                         return -EFAULT;
12421                         
12422         rtw_pm_set_ips(padapter,IPS_NONE);
12423         LeaveAllPowerSaveMode(padapter);
12424         
12425 #ifdef CONFIG_MP_INCLUDED
12426         if (init_mp_priv(padapter) == _FAIL) {
12427                         DBG_871X("%s: initialize MP private data Fail!\n", __func__);
12428         }
12429         padapter->mppriv.channel = 6;
12430
12431         bstart = strncmp(extra, "start", 5); // strncmp TRUE is 0
12432         bstop = strncmp(extra, "stop", 4); // strncmp TRUE is 0
12433         if(bstart==0)
12434         {
12435                 mp_join(padapter,WIFI_FW_ADHOC_STATE);
12436                 SetPacketRx(padapter, _TRUE, _FALSE);
12437                 Hal_SetChannel(padapter);
12438                 pmp_priv->rx_bindicatePkt= _TRUE;
12439                 pmp_priv->bRTWSmbCfg = _TRUE;
12440                 sprintf(extra, "monitor mode start\n");
12441         }
12442         else if (bstop==0)
12443         {
12444                 SetPacketRx(padapter, _FALSE, _FALSE);
12445                 pmp_priv->rx_bindicatePkt= _FALSE;
12446                 pmp_priv->bRTWSmbCfg = _FALSE;
12447                 padapter->registrypriv.mp_mode=1;
12448                 pHalFunc->hal_deinit(padapter);
12449                 padapter->registrypriv.mp_mode=0;
12450                 pHalFunc->hal_init(padapter);
12451                 //rtw_disassoc_cmd(padapter, 0, _TRUE);
12452                 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
12453                         rtw_disassoc_cmd(padapter, 500, _TRUE);
12454                         rtw_indicate_disconnect(padapter);
12455                         //rtw_free_assoc_resources(padapter, 1);
12456                 }
12457                 rtw_pm_set_ips(padapter,IPS_NORMAL);
12458                 sprintf(extra, "monitor mode Stop\n");
12459         }
12460 #endif
12461         wrqu->data.length = strlen(extra);
12462         return 0;
12463 }
12464
12465 static int rtw_efuse_mask_file(struct net_device *dev,
12466                         struct iw_request_info *info,
12467                         union iwreq_data *wrqu, char *extra)
12468 {
12469         char *rtw_efuse_mask_file_path;
12470         u8 Status;
12471         PADAPTER padapter = rtw_netdev_priv(dev);
12472         _rtw_memset(maskfileBuffer,0x00,sizeof(maskfileBuffer));
12473
12474         if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
12475                         return -EFAULT;
12476
12477         if(strncmp(extra, "off",3) ==0 && strlen(extra)<4)
12478         {       
12479                 padapter->registrypriv.boffefusemask=1;
12480                 sprintf(extra, "Turn off Efuse Mask\n");
12481                 wrqu->data.length = strlen(extra);
12482                 return 0;
12483         }
12484         if(strncmp(extra, "on",2) ==0 && strlen(extra)<3)
12485         {       
12486                 padapter->registrypriv.boffefusemask=0;
12487                 sprintf(extra, "Turn on Efuse Mask\n");
12488                 wrqu->data.length = strlen(extra);
12489                 return 0;
12490         }
12491         rtw_efuse_mask_file_path=extra;
12492         
12493         if (rtw_is_file_readable(rtw_efuse_mask_file_path) == _TRUE)
12494         {
12495                 DBG_871X("%s do rtw_efuse_mask_file_read = %s! ,sizeof maskfileBuffer %zu\n",__FUNCTION__,rtw_efuse_mask_file_path,sizeof(maskfileBuffer));
12496                 Status=rtw_efuse_file_read(padapter,rtw_efuse_mask_file_path,maskfileBuffer,sizeof(maskfileBuffer));
12497                 if(Status==_TRUE)
12498                   padapter->registrypriv.bFileMaskEfuse = _TRUE;
12499                 sprintf(extra, "efuse mask file read OK\n");    
12500         } else {
12501                 padapter->registrypriv.bFileMaskEfuse = _FALSE;
12502                 sprintf(extra, "efuse mask file readable FAIL\n");      
12503                 DBG_871X("%s rtw_is_file_readable fail !\n",__FUNCTION__);
12504         }
12505          wrqu->data.length = strlen(extra);     
12506         return 0;
12507 }
12508
12509
12510 static int rtw_efuse_file_map(struct net_device *dev,
12511                         struct iw_request_info *info,
12512                         union iwreq_data *wrqu, char *extra)
12513 {
12514         char *rtw_efuse_file_map_path;
12515         u8 Status;
12516         PEFUSE_HAL pEfuseHal;
12517         PADAPTER padapter = rtw_netdev_priv(dev);
12518         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
12519         pEfuseHal = &pHalData->EfuseHal;
12520         if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
12521                         return -EFAULT;
12522
12523         rtw_efuse_file_map_path=extra;
12524
12525         if (rtw_is_file_readable(rtw_efuse_file_map_path) == _TRUE)
12526         {
12527                 DBG_871X("%s do rtw_efuse_mask_file_read = %s! \n",__FUNCTION__,rtw_efuse_file_map_path);
12528                 Status=rtw_efuse_file_read(padapter,rtw_efuse_file_map_path,pEfuseHal->fakeEfuseModifiedMap,sizeof(pEfuseHal->fakeEfuseModifiedMap));
12529                 if(Status==_TRUE)
12530                         sprintf(extra, "efuse file file_read OK\n");
12531                 else    
12532                         sprintf(extra, "efuse file file_read FAIL\n");
12533         } else {
12534                 sprintf(extra, "efuse file readable FAIL\n");   
12535                 DBG_871X("%s rtw_is_file_readable fail !\n",__FUNCTION__);
12536         }
12537          wrqu->data.length = strlen(extra);     
12538         return 0;
12539 }
12540
12541
12542 #if defined(CONFIG_RTL8723B)
12543 /* update Tx AGC offset */
12544 static int rtw_mp_SetBT(struct net_device *dev,
12545                         struct iw_request_info *info,
12546                         union iwreq_data *wrqu, char *extra)
12547 {
12548         PADAPTER padapter = rtw_netdev_priv(dev);
12549         struct hal_ops *pHalFunc = &padapter->HalFunc;
12550         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
12551         
12552         BT_REQ_CMD      BtReq;
12553         PMPT_CONTEXT    pMptCtx=&(padapter->mppriv.MptCtx);
12554         PBT_RSP_CMD     pBtRsp=(PBT_RSP_CMD)&pMptCtx->mptOutBuf[0];
12555         char    input[128];
12556         char *pch, *ptmp, *token, *tmp[2]={0x00,0x00};
12557         u8 setdata[100];
12558         u8 resetbt=0x00;
12559         u8 tempval,BTStatus;
12560         u8 H2cSetbtmac[6];
12561         u8 u1H2CBtMpOperParm[4]={0x01};
12562         int testmode = 1, ready = 1, trxparam = 1, setgen = 1, getgen = 1, testctrl = 1, testbt = 1, readtherm = 1, setbtmac = 1;
12563         u32 i = 0, ii = 0, jj = 0, kk = 0, cnts = 0, status = 0;
12564         PRT_MP_FIRMWARE pBTFirmware = NULL;
12565         
12566         if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
12567                         return -EFAULT;
12568         if(strlen(extra)<1) return -EFAULT;
12569         
12570         DBG_871X("%s:iwpriv in=%s\n", __FUNCTION__, extra); 
12571         ready = strncmp(extra, "ready", 5); 
12572         testmode = strncmp(extra, "testmode", 8); // strncmp TRUE is 0
12573         trxparam = strncmp(extra, "trxparam", 8); 
12574         setgen = strncmp(extra, "setgen", 6);
12575         getgen = strncmp(extra, "getgen", 6); 
12576         testctrl = strncmp(extra, "testctrl", 8);
12577         testbt = strncmp(extra, "testbt", 6);
12578         readtherm = strncmp(extra, "readtherm", 9);
12579         setbtmac = strncmp(extra, "setbtmac", 8);
12580
12581         if ( strncmp(extra, "dlbt", 4) == 0)
12582         {
12583                 pHalData->LastHMEBoxNum=0;
12584                 padapter->bBTFWReady = _FALSE;
12585                 rtw_write8(padapter, 0xa3, 0x05);
12586                 BTStatus=rtw_read8(padapter, 0xa0);
12587                 DBG_871X("%s: btwmap before read 0xa0 BT Status =0x%x \n", __FUNCTION__,BTStatus);
12588                 if (BTStatus != 0x04)
12589                 {
12590                         sprintf(extra, "BT Status not Active DLFW FAIL\n");
12591                         goto exit;
12592                 }
12593
12594                 tempval = rtw_read8(padapter, 0x6B);
12595                 tempval |= BIT7;
12596                 rtw_write8(padapter, 0x6B, tempval);
12597
12598                 // Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay
12599                 // So don't wirte 0x6A[14]=1 and 0x6A[15]=0 together!
12600                 rtw_usleep_os(100);
12601                 // disable BT power cut
12602                 // 0x6A[14] = 0
12603                 tempval = rtw_read8(padapter, 0x6B);
12604                 tempval &= ~BIT6;
12605                 rtw_write8(padapter, 0x6B, tempval);
12606                 rtw_usleep_os(100);
12607                 MPT_PwrCtlDM(padapter,0);
12608                 rtw_write32(padapter, 0xcc, (rtw_read32(padapter, 0xcc)| 0x00000004));
12609                 rtw_write32(padapter, 0x6b, (rtw_read32(padapter, 0x6b)& 0xFFFFFFEF));
12610                 rtw_msleep_os(600);
12611                 rtw_write32(padapter, 0x6b, (rtw_read32(padapter, 0x6b)| 0x00000010));
12612                 rtw_write32(padapter, 0xcc, (rtw_read32(padapter, 0xcc)& 0xFFFFFFFB));
12613                 rtw_msleep_os(1200);            
12614                 pBTFirmware = (PRT_MP_FIRMWARE)rtw_zmalloc(sizeof(RT_MP_FIRMWARE));
12615                 if(pBTFirmware==NULL)
12616                         goto exit;
12617                 padapter->bBTFWReady = _FALSE;
12618                 FirmwareDownloadBT(padapter, pBTFirmware);
12619                 if (pBTFirmware)
12620                         rtw_mfree((u8*)pBTFirmware, sizeof(RT_MP_FIRMWARE));
12621                         
12622                 DBG_871X("Wait for FirmwareDownloadBT fw boot!\n");
12623                 rtw_msleep_os(2000);
12624                 _rtw_memset(extra,'\0', wrqu->data.length);
12625                 BtReq.opCodeVer = 1;
12626                 BtReq.OpCode = 0;
12627                 BtReq.paraLength = 0;
12628                 mptbt_BtControlProcess(padapter, &BtReq);
12629                 rtw_msleep_os(100);
12630
12631                 DBG_8192C("FirmwareDownloadBT ready = 0x%x 0x%x", pMptCtx->mptOutBuf[4],pMptCtx->mptOutBuf[5]);
12632                 if ((pMptCtx->mptOutBuf[4] == 0x00) && (pMptCtx->mptOutBuf[5] == 0x00)) {
12633
12634                         if (padapter->mppriv.bTxBufCkFail == _TRUE)
12635                                 sprintf(extra, "check TxBuf Fail.\n");
12636                         else
12637                                 sprintf(extra, "download FW Fail.\n");
12638                 } else {
12639                         sprintf(extra, "download FW OK.\n");
12640                         goto exit;
12641                 }
12642                 goto exit;      
12643         }
12644         if ( strncmp(extra, "dlfw", 4) == 0)
12645         {
12646                 pHalData->LastHMEBoxNum=0;
12647                 padapter->bBTFWReady = _FALSE;
12648                 rtw_write8(padapter, 0xa3, 0x05);
12649                 BTStatus=rtw_read8(padapter, 0xa0);
12650                 DBG_871X("%s: btwmap before read 0xa0 BT Status =0x%x \n", __FUNCTION__,BTStatus);
12651                 if (BTStatus != 0x04)
12652                 {
12653                         sprintf(extra, "BT Status not Active DLFW FAIL\n");
12654                         goto exit;
12655                 }
12656
12657                 tempval = rtw_read8(padapter, 0x6B);
12658                 tempval |= BIT7;
12659                 rtw_write8(padapter, 0x6B, tempval);
12660
12661                 // Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay
12662                 // So don't wirte 0x6A[14]=1 and 0x6A[15]=0 together!
12663                 rtw_usleep_os(100);
12664                 // disable BT power cut
12665                 // 0x6A[14] = 0
12666                 tempval = rtw_read8(padapter, 0x6B);
12667                 tempval &= ~BIT6;
12668                 rtw_write8(padapter, 0x6B, tempval);
12669                 rtw_usleep_os(100);
12670         
12671                 MPT_PwrCtlDM(padapter,0);
12672                 rtw_write32(padapter, 0xcc, (rtw_read32(padapter, 0xcc)| 0x00000004));
12673                 rtw_write32(padapter, 0x6b, (rtw_read32(padapter, 0x6b)& 0xFFFFFFEF));
12674                 rtw_msleep_os(600);
12675                 rtw_write32(padapter, 0x6b, (rtw_read32(padapter, 0x6b)| 0x00000010));
12676                 rtw_write32(padapter, 0xcc, (rtw_read32(padapter, 0xcc)& 0xFFFFFFFB));
12677                 rtw_msleep_os(1200);
12678
12679 #if defined(CONFIG_PLATFORM_SPRD) && (MP_DRIVER == 1)
12680                 // Pull up BT reset pin.
12681                 DBG_871X("%s: pull up BT reset pin when bt start mp test\n", __FUNCTION__);
12682                 rtw_wifi_gpio_wlan_ctrl(WLAN_BT_PWDN_ON);
12683 #endif
12684                 DBG_871X(" FirmwareDownload!\n");
12685
12686 #if defined(CONFIG_RTL8723B)
12687                 status = rtl8723b_FirmwareDownload(padapter, _FALSE);
12688 #endif
12689                 DBG_871X("Wait for FirmwareDownloadBT fw boot!\n");
12690                 rtw_msleep_os(1000);
12691 #ifdef CONFIG_BT_COEXIST
12692                 rtw_btcoex_HaltNotify(padapter);
12693                 DBG_871X("SetBT btcoex HaltNotify !\n");
12694                 //hal_btcoex1ant_SetAntPath(padapter);
12695                 rtw_btcoex_SetManualControl(padapter, _TRUE);
12696 #endif          
12697                 _rtw_memset(extra,'\0', wrqu->data.length);
12698                 BtReq.opCodeVer = 1;
12699                 BtReq.OpCode = 0;
12700                 BtReq.paraLength = 0;
12701                 mptbt_BtControlProcess(padapter, &BtReq);
12702                 rtw_msleep_os(200);
12703
12704                 DBG_8192C("FirmwareDownloadBT ready = 0x%x 0x%x", pMptCtx->mptOutBuf[4],pMptCtx->mptOutBuf[5]);
12705                 if( (pMptCtx->mptOutBuf[4]==0x00) && (pMptCtx->mptOutBuf[5]==0x00))
12706                         {
12707                                 if(padapter->mppriv.bTxBufCkFail==_TRUE)
12708                                         sprintf(extra, "check TxBuf Fail.\n");
12709                                 else
12710                                         sprintf(extra, "download FW Fail.\n");
12711                         }
12712                         else
12713                         {
12714                                 #ifdef CONFIG_BT_COEXIST
12715                                 rtw_btcoex_SwitchBtTRxMask(padapter);
12716                                 #endif
12717                                 rtw_msleep_os(200);
12718                                 sprintf(extra, "download FW OK.\n");
12719                                 goto exit;
12720                         }
12721                 goto exit;
12722         }
12723
12724         if ( strncmp(extra, "down", 4) == 0){
12725                 DBG_871X("SetBT down for to hal_init !\n");
12726 #ifdef CONFIG_BT_COEXIST                
12727                 rtw_btcoex_SetManualControl(padapter, _FALSE);
12728                 rtw_btcoex_Initialize(padapter);
12729 #endif          
12730                 pHalFunc->read_adapter_info(padapter);
12731                 pHalFunc->hal_deinit(padapter);
12732                 pHalFunc->hal_init(padapter);
12733                 rtw_pm_set_ips(padapter,IPS_NONE);
12734                 LeaveAllPowerSaveMode(padapter);
12735                 MPT_PwrCtlDM(padapter,0);
12736                 rtw_write32(padapter, 0xcc, (rtw_read32(padapter, 0xcc)| 0x00000004));
12737                 rtw_write32(padapter, 0x6b, (rtw_read32(padapter, 0x6b)& 0xFFFFFFEF));
12738                 rtw_msleep_os(600);
12739                         //rtw_write32(padapter, 0x6a, (rtw_read32(padapter, 0x6a)& 0xFFFFFFFE));
12740                 rtw_write32(padapter, 0x6b, (rtw_read32(padapter, 0x6b)| 0x00000010));
12741                 rtw_write32(padapter, 0xcc, (rtw_read32(padapter, 0xcc)& 0xFFFFFFFB));
12742                 rtw_msleep_os(1200);
12743                 goto exit;
12744         }
12745         if ( strncmp(extra, "disable", 7) == 0){
12746                 DBG_871X("SetBT disable !\n");
12747                 rtw_write32(padapter, 0x6a, (rtw_read32(padapter, 0x6a)& 0xFFFFFFFB));
12748                 rtw_msleep_os(500);
12749                 goto exit;
12750                 }
12751         if ( strncmp(extra, "enable", 6) == 0){
12752                 DBG_871X("SetBT enable !\n");
12753                 rtw_write32(padapter, 0x6a, (rtw_read32(padapter, 0x6a)| 0x00000004));
12754                 rtw_msleep_os(500);
12755                 goto exit;
12756         }
12757         if ( strncmp(extra, "h2c", 3) == 0){
12758                         DBG_871X("SetBT h2c !\n");
12759                         padapter->bBTFWReady = _TRUE;
12760                         rtw_hal_fill_h2c_cmd(padapter, 0x63, 1, u1H2CBtMpOperParm);
12761                         goto exit;
12762                 }
12763         if ( strncmp(extra, "2ant", 4) == 0){
12764                 DBG_871X("Set BT 2ant use!\n");
12765                 PHY_SetMacReg(padapter,0x67,BIT5,0x1);
12766                 rtw_write32(padapter, 0x948, 0000);
12767                 
12768                 goto exit;
12769         }
12770                 
12771         if( ready!=0 && testmode!=0 && trxparam!=0 && setgen!=0 && getgen!=0 && testctrl!=0 && testbt!=0 && readtherm!=0 &&setbtmac!=0)
12772                 return -EFAULT;
12773                 
12774         if( testbt==0 )
12775         {
12776                         BtReq.opCodeVer=1;
12777                         BtReq.OpCode=6;
12778                         BtReq.paraLength=cnts/2;
12779                         goto todo;
12780         }
12781         if( ready==0 )
12782         {
12783                 BtReq.opCodeVer=1;
12784                 BtReq.OpCode=0;
12785                 BtReq.paraLength=0; 
12786                 goto todo;
12787         }
12788
12789         pch = extra;    
12790         i = 0;
12791         while ((token = strsep(&pch, ",")) != NULL)
12792         {
12793                 if (i > 1) break;
12794                 tmp[i] = token;
12795                 i++;
12796         }
12797
12798         if ((tmp[0]==NULL) && (tmp[1]==NULL))
12799         {
12800                 return -EFAULT;
12801         }
12802         else
12803         {
12804                 cnts = strlen(tmp[1]);
12805                 if (cnts<1) return -EFAULT;
12806         
12807                 DBG_871X("%s: cnts=%d\n", __FUNCTION__, cnts);
12808                 DBG_871X("%s: data=%s\n", __FUNCTION__, tmp[1]);
12809                                 
12810                 for (jj=0, kk=0; jj<cnts; jj++, kk+=2)
12811                 {
12812                         BtReq.pParamStart[jj] = key_2char2num(tmp[1][kk], tmp[1][kk+1]);
12813 //                      DBG_871X("BtReq.pParamStart[%d]=0x%02x\n", jj, BtReq.pParamStart[jj]);
12814                 }
12815         }
12816         
12817         if( testmode==0 )       
12818         {
12819                 BtReq.opCodeVer=1;
12820                 BtReq.OpCode=1;
12821                 BtReq.paraLength=1; 
12822         }
12823         if( trxparam==0 )
12824         {
12825                 BtReq.opCodeVer=1;
12826                 BtReq.OpCode=2;
12827                 BtReq.paraLength=cnts/2; 
12828         }
12829         if( setgen==0 )
12830         {       
12831                 DBG_871X("%s: BT_SET_GENERAL \n", __func__); 
12832                 BtReq.opCodeVer=1;
12833                 BtReq.OpCode=3; //BT_SET_GENERAL        3
12834                 BtReq.paraLength=cnts/2;        
12835         }
12836         if( getgen==0 )
12837         {       
12838                 DBG_871X("%s: BT_GET_GENERAL \n", __func__); 
12839                 BtReq.opCodeVer=1;
12840                 BtReq.OpCode=4;         //BT_GET_GENERAL        4
12841                 BtReq.paraLength=cnts/2;        
12842         }
12843         if( readtherm==0 )
12844         {       
12845                 DBG_871X("%s: BT_GET_GENERAL \n", __func__); 
12846                 BtReq.opCodeVer=1;
12847                 BtReq.OpCode=4;         //BT_GET_GENERAL        4
12848                 BtReq.paraLength=cnts/2;        
12849         }
12850         
12851         if( testctrl==0 )
12852         {       
12853                 DBG_871X("%s: BT_TEST_CTRL \n", __func__);
12854                 BtReq.opCodeVer=1;
12855                 BtReq.OpCode=5;         //BT_TEST_CTRL  5
12856                 BtReq.paraLength=cnts/2;        
12857         }
12858
12859         DBG_871X("%s: Req opCodeVer=%d OpCode=%d paraLength=%d\n",
12860                 __FUNCTION__, BtReq.opCodeVer, BtReq.OpCode, BtReq.paraLength);
12861
12862         if(BtReq.paraLength<1)
12863                 goto todo;
12864         for (i=0; i<BtReq.paraLength; i++)
12865         {
12866                 DBG_871X("%s: BtReq.pParamStart[%d] = 0x%02x \n",
12867                         __FUNCTION__, i, BtReq.pParamStart[i]);
12868         }
12869         
12870 todo:
12871         _rtw_memset(extra,'\0', wrqu->data.length);
12872
12873         if (padapter->bBTFWReady == _FALSE)
12874         {
12875                 sprintf(extra, "BTFWReady = FALSE.\n");
12876                 goto exit;
12877         }
12878
12879         mptbt_BtControlProcess(padapter, &BtReq);
12880
12881         if (readtherm == 0)
12882         {
12883                 sprintf(extra, "BT thermal=");
12884                 for (i=4; i<pMptCtx->mptOutLen; i++)
12885                 {
12886                         if ((pMptCtx->mptOutBuf[i]==0x00) && (pMptCtx->mptOutBuf[i+1]==0x00))
12887                                 goto exit;
12888
12889                         sprintf(extra, "%s %d ", extra, (pMptCtx->mptOutBuf[i]& 0x1f));
12890                 }
12891         }
12892         else
12893         {
12894                 for (i=4; i<pMptCtx->mptOutLen; i++)
12895                 {
12896                         sprintf(extra, "%s 0x%x ", extra, pMptCtx->mptOutBuf[i]);
12897                 }
12898         }
12899         
12900 exit:
12901         wrqu->data.length = strlen(extra) + 1;
12902         DBG_871X("-%s: output len=%d data=%s\n", __FUNCTION__, wrqu->data.length, extra);
12903
12904         return status;
12905 }
12906
12907 #endif //#ifdef CONFIG_RTL8723B
12908
12909 static int rtw_mp_set(struct net_device *dev,
12910                         struct iw_request_info *info,
12911                         union iwreq_data *wdata, char *extra)
12912 {
12913         struct iw_point *wrqu = (struct iw_point *)wdata;
12914         u32 subcmd = wrqu->flags;
12915         PADAPTER padapter = rtw_netdev_priv(dev);
12916
12917         if (padapter == NULL)
12918         {
12919                 return -ENETDOWN;
12920         }
12921
12922         if((padapter->bup == _FALSE ))
12923         {
12924                 DBG_871X(" %s fail =>(padapter->bup == _FALSE )\n",__FUNCTION__);
12925                 return -ENETDOWN;
12926         }
12927
12928         if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE))
12929        {        
12930         DBG_871X("%s fail =>(padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE) \n",__FUNCTION__);
12931              return -ENETDOWN;
12932        }
12933
12934         
12935         //_rtw_memset(extra, 0x00, IW_PRIV_SIZE_MASK);
12936
12937         if (extra == NULL)
12938         {
12939                 wrqu->length = 0;
12940                 return -EIO;
12941         }
12942
12943         switch(subcmd)
12944         {
12945         case MP_START:
12946                         DBG_871X("set case mp_start \n");
12947                         rtw_mp_start (dev,info,wrqu,extra);
12948                          break; 
12949                          
12950         case MP_STOP:
12951                         DBG_871X("set case mp_stop \n");
12952                         rtw_mp_stop (dev,info,wrqu,extra);
12953                          break; 
12954                          
12955         case MP_BANDWIDTH:
12956                         DBG_871X("set case mp_bandwidth \n");
12957                         rtw_mp_bandwidth (dev,info,wrqu,extra);
12958                         break;
12959                                 
12960         case MP_RESET_STATS:
12961                         DBG_871X("set case MP_RESET_STATS \n");
12962                         rtw_mp_reset_stats      (dev,info,wrqu,extra);
12963                         break;
12964         case MP_SetRFPathSwh:           
12965                         DBG_871X("set MP_SetRFPathSwitch \n");
12966                         rtw_mp_SetRFPath  (dev,info,wdata,extra);
12967                         break;
12968         case CTA_TEST:
12969                         DBG_871X("set CTA_TEST\n");
12970                         rtw_cta_test_start (dev, info, wdata, extra);
12971                         break;
12972         case MP_DISABLE_BT_COEXIST:
12973                         DBG_871X("set case MP_DISABLE_BT_COEXIST \n");
12974                         rtw_mp_disable_bt_coexist(dev, info, wdata, extra);
12975                 break;
12976 #ifdef CONFIG_WOWLAN
12977         case MP_WOW_ENABLE:
12978                         DBG_871X("set case MP_WOW_ENABLE: %s \n", extra);
12979                         rtw_wowlan_ctrl(dev, info, wdata, extra);
12980         break;
12981 #endif
12982 #ifdef CONFIG_AP_WOWLAN
12983         case MP_AP_WOW_ENABLE:
12984                         DBG_871X("set case MP_AP_WOW_ENABLE: %s \n", extra);
12985                         rtw_ap_wowlan_ctrl(dev, info, wdata, extra);
12986         break;
12987 #endif
12988         }
12989
12990           
12991         return 0;               
12992 }
12993
12994
12995 static int rtw_mp_get(struct net_device *dev,
12996                         struct iw_request_info *info,
12997                         union iwreq_data *wdata, char *extra)
12998 {
12999         struct iw_point *wrqu = (struct iw_point *)wdata;
13000         u32 subcmd = wrqu->flags;
13001         PADAPTER padapter = rtw_netdev_priv(dev);
13002
13003         //DBG_871X("in mp_get extra= %s \n",extra);
13004
13005         if (padapter == NULL)
13006         {
13007                 return -ENETDOWN;
13008         }
13009         if((padapter->bup == _FALSE ))
13010         {
13011                 DBG_871X(" %s fail =>(padapter->bup == _FALSE )\n",__FUNCTION__);
13012                 return -ENETDOWN;
13013         }
13014
13015         if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE))
13016        {        
13017         DBG_871X("%s fail =>(padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE) \n",__FUNCTION__);
13018              return -ENETDOWN;
13019        }
13020         
13021         if (extra == NULL)
13022         {
13023                 wrqu->length = 0;
13024                 return -EIO;
13025         }
13026         
13027         switch(subcmd)
13028         {
13029         case WRITE_REG :
13030                         rtw_mp_write_reg (dev,info,wrqu,extra);
13031                          break;
13032                          
13033         case WRITE_RF:
13034                         rtw_mp_write_rf (dev,info,wrqu,extra);
13035                          break; 
13036                          
13037         case MP_PHYPARA:
13038                         DBG_871X("mp_get  MP_PHYPARA \n");
13039                         rtw_mp_phypara(dev,info,wrqu,extra);    
13040                         break;
13041
13042         case MP_CHANNEL:
13043                         DBG_871X("set case mp_channel \n");
13044                         rtw_mp_channel (dev,info,wrqu,extra);
13045                         break;
13046                         
13047         case READ_REG:
13048                         DBG_871X("mp_get  READ_REG \n");
13049                         rtw_mp_read_reg (dev,info,wrqu,extra);
13050                          break; 
13051         case READ_RF:
13052                         DBG_871X("mp_get  READ_RF \n");
13053                         rtw_mp_read_rf (dev,info,wrqu,extra);
13054                         break; 
13055                         
13056         case MP_RATE:
13057                         DBG_871X("set case mp_rate \n");
13058                         rtw_mp_rate (dev,info,wrqu,extra);
13059                         break;
13060                         
13061         case MP_TXPOWER:
13062                         DBG_871X("set case MP_TXPOWER \n");
13063                         rtw_mp_txpower (dev,info,wrqu,extra);
13064                         break;
13065                         
13066         case MP_ANT_TX:
13067                         DBG_871X("set case MP_ANT_TX \n");
13068                         rtw_mp_ant_tx (dev,info,wrqu,extra);
13069                         break;
13070                         
13071         case MP_ANT_RX:
13072                         DBG_871X("set case MP_ANT_RX \n");
13073                         rtw_mp_ant_rx (dev,info,wrqu,extra);
13074                         break;
13075                         
13076         case MP_QUERY:
13077                         //DBG_871X("mp_get mp_query MP_QUERY \n");
13078                         rtw_mp_trx_query(dev,info,wrqu,extra);
13079                         break;
13080                                         
13081         case MP_CTX:
13082                         DBG_871X("set case MP_CTX \n");
13083                         rtw_mp_ctx (dev,info,wrqu,extra);
13084                         break;
13085                                         
13086         case MP_ARX:
13087                         DBG_871X("set case MP_ARX \n");
13088                         rtw_mp_arx (dev,info,wrqu,extra);
13089                         break;
13090                         
13091         case EFUSE_GET:
13092                         DBG_871X("efuse get EFUSE_GET \n");
13093                         rtw_mp_efuse_get(dev,info,wdata,extra);
13094                  break; 
13095                  
13096         case MP_DUMP:
13097                         DBG_871X("set case MP_DUMP \n");
13098                         rtw_mp_dump (dev,info,wrqu,extra);
13099                  break; 
13100         case MP_PSD:
13101                         DBG_871X("set case MP_PSD \n");
13102                         rtw_mp_psd (dev,info,wrqu,extra);
13103                  break;
13104         case MP_THER:
13105                         DBG_871X("set case MP_THER \n");
13106                         rtw_mp_thermal (dev,info,wrqu,extra);
13107                 break;
13108         case MP_PwrCtlDM:
13109                         DBG_871X("set MP_PwrCtlDM\n");
13110                         rtw_mp_PwrCtlDM (dev,info,wrqu,extra);
13111                 break;
13112         case MP_QueryDrvStats:          
13113                         DBG_871X("mp_get MP_QueryDrvStats \n");
13114                         rtw_mp_QueryDrv(dev,info,wdata,extra);
13115                         break;
13116                 case MP_PWRTRK:
13117                         DBG_871X("set case MP_PWRTRK \n");
13118                         rtw_mp_pwrtrk(dev,info,wrqu,extra);
13119                         break;                   
13120         case EFUSE_SET:
13121                         DBG_871X("set case efuse set \n");
13122                         rtw_mp_efuse_set(dev,info,wdata,extra);
13123                         break;                   
13124         case MP_GET_TXPOWER_INX:
13125                         DBG_871X("mp_get MP_GET_TXPOWER_INX \n");
13126                         rtw_mp_txpower_index(dev,info,wrqu,extra);
13127                         break;
13128         case MP_GETVER:
13129                         DBG_871X("mp_get MP_GETVER \n");
13130                         rtw_mp_getver(dev,info,wdata,extra);
13131                         break;
13132         case  MP_MON:
13133                         DBG_871X("mp_get MP_MON \n");
13134                         rtw_mp_mon(dev,info,wdata,extra);
13135                         break;
13136         case  EFUSE_MASK:
13137                         DBG_871X("mp_get EFUSE_MASK\n");
13138                         rtw_efuse_mask_file(dev,info,wdata,extra);
13139                         break;
13140          case  EFUSE_FILE:
13141                         DBG_871X("mp_get EFUSE_FILE\n");
13142                         rtw_efuse_file_map(dev,info,wdata,extra);
13143                         break;          
13144 #if defined(CONFIG_RTL8723B)
13145         case MP_SetBT:          
13146                         DBG_871X("set MP_SetBT \n");
13147                         rtw_mp_SetBT(dev,info,wdata,extra);
13148                         break;           
13149 #endif
13150
13151         }
13152
13153         rtw_msleep_os(10); //delay 5ms for sending pkt before exit adb shell operation
13154 return 0;       
13155 }
13156
13157 #endif //#if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_MP_IWPRIV_SUPPORT)
13158
13159 static int rtw_wfd_tdls_enable(struct net_device *dev,
13160                                 struct iw_request_info *info,
13161                                 union iwreq_data *wrqu, char *extra)
13162 {
13163         int ret = 0;
13164
13165 #ifdef CONFIG_TDLS
13166 #ifdef CONFIG_WFD
13167
13168         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13169
13170         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13171
13172         if ( extra[ 0 ] == '0' )
13173                 padapter->wdinfo.wfd_tdls_enable = 0;
13174         else
13175                 padapter->wdinfo.wfd_tdls_enable = 1;
13176
13177 #endif /* CONFIG_WFD */
13178 #endif /* CONFIG_TDLS */
13179         
13180         return ret;
13181 }
13182
13183 static int rtw_tdls_weaksec(struct net_device *dev,
13184                                 struct iw_request_info *info,
13185                                 union iwreq_data *wrqu, char *extra)
13186 {
13187         int ret = 0;
13188
13189 #ifdef CONFIG_TDLS
13190
13191         u8 i, j;
13192         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13193
13194         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13195
13196         if ( extra[ 0 ] == '0' )
13197                 padapter->wdinfo.wfd_tdls_weaksec = 0;
13198         else
13199                 padapter->wdinfo.wfd_tdls_weaksec = 1;
13200
13201 #endif /* CONFIG_TDLS */
13202         
13203         return ret;
13204 }
13205
13206
13207 static int rtw_tdls_enable(struct net_device *dev,
13208                                 struct iw_request_info *info,
13209                                 union iwreq_data *wrqu, char *extra)
13210 {
13211         int ret = 0;
13212
13213 #ifdef CONFIG_TDLS
13214
13215         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13216         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;
13217         _irqL    irqL;
13218         _list   *plist, *phead;
13219         s32     index;
13220         struct sta_info *psta = NULL;
13221         struct  sta_priv *pstapriv = &padapter->stapriv;
13222         u8 tdls_sta[NUM_STA][ETH_ALEN];
13223         u8 empty_hwaddr[ETH_ALEN] = { 0x00 };
13224         struct tdls_txmgmt txmgmt;
13225
13226         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13227
13228         _rtw_memset(tdls_sta, 0x00, sizeof(tdls_sta));
13229         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
13230
13231         if (extra[ 0 ] == '0') {
13232                 ptdlsinfo->tdls_enable = 0;
13233
13234                 if(pstapriv->asoc_sta_count==1)
13235                         return ret;
13236
13237                 _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
13238                 for (index=0; index< NUM_STA; index++) {
13239                         phead = &(pstapriv->sta_hash[index]);
13240                         plist = get_next(phead);
13241                         
13242                         while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
13243                                 psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
13244
13245                                 plist = get_next(plist);
13246
13247                                 if (psta->tdls_sta_state != TDLS_STATE_NONE) {
13248                                         _rtw_memcpy(tdls_sta[index], psta->hwaddr, ETH_ALEN);
13249                                 }
13250                         }
13251                 }
13252                 _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
13253
13254                 for (index=0; index< NUM_STA; index++) {
13255                         if (!_rtw_memcmp(tdls_sta[index], empty_hwaddr, ETH_ALEN)) {
13256                                 DBG_871X("issue tear down to "MAC_FMT"\n", MAC_ARG(tdls_sta[index]));
13257                                 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
13258                                 _rtw_memcpy(txmgmt.peer, tdls_sta[index], ETH_ALEN);
13259                                 issue_tdls_teardown(padapter, &txmgmt, _TRUE);
13260                         }
13261                 }
13262                 rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);
13263                 rtw_reset_tdls_info(padapter);
13264         }       else if (extra[0] == '1') {
13265                 ptdlsinfo->tdls_enable = 1;
13266         }
13267 #endif /* CONFIG_TDLS */
13268         
13269         return ret;
13270 }
13271
13272 static int rtw_tdls_setup(struct net_device *dev,
13273                                 struct iw_request_info *info,
13274                                 union iwreq_data *wrqu, char *extra)
13275 {
13276         int ret = 0;
13277 #ifdef CONFIG_TDLS
13278         u8 i, j;
13279         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13280         struct tdls_txmgmt txmgmt;
13281 #ifdef CONFIG_WFD
13282         struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
13283 #endif /* CONFIG_WFD */
13284
13285         DBG_871X("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1);
13286
13287         if (wrqu->data.length - 1 != 17) {
13288                 DBG_871X("[%s] length:%d != 17\n", __FUNCTION__, (wrqu->data.length -1));
13289                 return ret;
13290         }
13291
13292         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
13293         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
13294                 txmgmt.peer[i]=key_2char2num(*(extra+j), *(extra+j+1));
13295         }
13296
13297 #ifdef CONFIG_WFD
13298         if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {
13299                 /* Weak Security situation with AP. */
13300                 if (0 == pwdinfo->wfd_tdls_weaksec)     {
13301                         /* Can't send the tdls setup request out!! */
13302                         DBG_871X("[%s] Current link is not AES, "
13303                                 "SKIP sending the tdls setup request!!\n", __FUNCTION__);
13304                 } else {
13305                         issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
13306                 }
13307         } else
13308 #endif /* CONFIG_WFD */
13309         {
13310                 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
13311         }
13312 #endif /* CONFIG_TDLS */
13313         
13314         return ret;
13315 }
13316
13317 static int rtw_tdls_teardown(struct net_device *dev,
13318                                 struct iw_request_info *info,
13319                                 union iwreq_data *wrqu, char *extra)
13320 {
13321         int ret = 0;
13322
13323 #ifdef CONFIG_TDLS
13324
13325         u8 i,j;
13326         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13327         struct sta_info *ptdls_sta = NULL;
13328         struct tdls_txmgmt txmgmt;
13329
13330         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13331
13332         if (wrqu->data.length - 1 != 17 && wrqu->data.length - 1 != 19) {
13333                 DBG_871X("[%s] length:%d != 17 or 19\n",
13334                         __FUNCTION__, (wrqu->data.length -1));
13335                 return ret;
13336         }
13337
13338         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
13339         for (i=0, j=0; i < ETH_ALEN; i++, j+=3)
13340                 txmgmt.peer[i]=key_2char2num(*(extra+j), *(extra+j+1));
13341
13342         ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), txmgmt.peer);
13343         
13344         if (ptdls_sta != NULL) {
13345                 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
13346                 if (wrqu->data.length - 1 == 19)
13347                         issue_tdls_teardown(padapter, &txmgmt, _FALSE);
13348                 else 
13349                         issue_tdls_teardown(padapter, &txmgmt, _TRUE);
13350         } else {
13351                 DBG_871X( "TDLS peer not found\n");
13352         }
13353 #endif /* CONFIG_TDLS */
13354         
13355         return ret;
13356 }
13357
13358 static int rtw_tdls_discovery(struct net_device *dev,
13359                                 struct iw_request_info *info,
13360                                 union iwreq_data *wrqu, char *extra)
13361 {
13362         int ret = 0;
13363
13364 #ifdef CONFIG_TDLS
13365         
13366         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13367         struct tdls_txmgmt      txmgmt;
13368         int i = 0, j=0;
13369
13370         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13371
13372         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
13373         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
13374                 txmgmt.peer[i]=key_2char2num(*(extra+j), *(extra+j+1));
13375         }
13376
13377         issue_tdls_dis_req(padapter, &txmgmt);
13378
13379 #endif /* CONFIG_TDLS */
13380
13381         return ret;
13382 }
13383
13384 static int rtw_tdls_ch_switch(struct net_device *dev,
13385                                 struct iw_request_info *info,
13386                                 union iwreq_data *wrqu, char *extra)
13387 {
13388         int ret = 0;
13389
13390 #ifdef CONFIG_TDLS
13391 #ifdef CONFIG_TDLS_CH_SW        
13392         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13393         struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
13394         u8 i, j;
13395         struct sta_info *ptdls_sta = NULL;
13396
13397         DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13398
13399         if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
13400         {
13401                 DBG_871X("Can't do TDLS channel switch since ch_switch_prohibited = _TRUE\n");
13402                 return ret;
13403         }
13404
13405         for( i=0, j=0 ; i < ETH_ALEN; i++, j+=3 ){
13406                 pchsw_info->addr[i] = key_2char2num(*(extra+j), *(extra+j+1));
13407         }
13408
13409         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pchsw_info->addr);
13410         if( ptdls_sta == NULL )
13411                 return ret;
13412
13413         pchsw_info->ch_sw_state |= TDLS_CH_SW_INITIATOR_STATE;
13414
13415         if (ptdls_sta != NULL) {
13416                 if (pchsw_info->off_ch_num == 0)
13417                         pchsw_info->off_ch_num = 11;
13418         }else {
13419                 DBG_871X( "TDLS peer not found\n");
13420         }
13421
13422         
13423         //issue_tdls_ch_switch_req(padapter, ptdls_sta);
13424         /* DBG_871X("issue tdls ch switch req\n"); */
13425
13426 #endif /* CONFIG_TDLS_CH_SW */
13427 #endif /* CONFIG_TDLS */
13428
13429         return ret;
13430 }
13431
13432 static int rtw_tdls_ch_switch_off(struct net_device *dev,
13433                                 struct iw_request_info *info,
13434                                 union iwreq_data *wrqu, char *extra)
13435 {
13436         int ret = 0;
13437
13438 #ifdef CONFIG_TDLS
13439 #ifdef CONFIG_TDLS_CH_SW        
13440         
13441         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13442         struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
13443         u8 i, j, mac_addr[ETH_ALEN];
13444         struct sta_info *ptdls_sta = NULL;
13445         struct tdls_txmgmt txmgmt;
13446
13447         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
13448         
13449         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13450
13451         if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
13452         {
13453                 DBG_871X("Can't do TDLS channel switch since ch_switch_prohibited = _TRUE\n");
13454                 return ret;
13455         }
13456
13457         if (wrqu->data.length >= 17) {
13458                 for (i=0, j=0 ; i < ETH_ALEN; i++, j+=3)
13459                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
13460                         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
13461         }
13462
13463         if (padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)) {   
13464                 SelectChannel(padapter, padapter->mlmeextpriv.cur_channel);
13465         }
13466
13467         pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |
13468                                                                 TDLS_CH_SWITCH_ON_STATE |
13469                                                                 TDLS_PEER_AT_OFF_STATE);
13470         ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
13471         _rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN);
13472
13473         if (ptdls_sta != NULL) {
13474                 ptdls_sta->ch_switch_time = 0;
13475                 ptdls_sta->ch_switch_timeout = 0;
13476                 _cancel_timer_ex(&ptdls_sta->ch_sw_timer);
13477                 _cancel_timer_ex(&ptdls_sta->delay_timer);
13478         }
13479
13480 #endif /* CONFIG_TDLS_CH_SW */
13481 #endif /* CONFIG_TDLS */
13482
13483         return ret;
13484 }
13485
13486 static int rtw_tdls_dump_ch(struct net_device *dev,
13487                                 struct iw_request_info *info,
13488                                 union iwreq_data *wrqu, char *extra)
13489 {
13490         int ret = 0;
13491
13492 #ifdef CONFIG_TDLS
13493 #ifdef CONFIG_TDLS_CH_SW        
13494         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13495         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13496
13497         DBG_8192C("[%s] dump_stack:%s\n", __FUNCTION__, extra);
13498
13499         extra[ wrqu->data.length ] = 0x00;
13500         ptdlsinfo->chsw_info.dump_stack = rtw_atoi( extra );
13501
13502         return ret;
13503
13504 #endif
13505 #endif /* CONFIG_TDLS */
13506
13507         return ret;
13508 }
13509
13510 static int rtw_tdls_off_ch_num(struct net_device *dev,
13511                                 struct iw_request_info *info,
13512                                 union iwreq_data *wrqu, char *extra)
13513 {
13514         int ret = 0;
13515
13516 #ifdef CONFIG_TDLS
13517 #ifdef CONFIG_TDLS_CH_SW        
13518         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13519         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13520
13521         DBG_8192C("[%s] off_ch_num:%s\n", __FUNCTION__, extra);
13522
13523         extra[ wrqu->data.length ] = 0x00;
13524         ptdlsinfo->chsw_info.off_ch_num = rtw_atoi(extra);
13525
13526         return ret;
13527         
13528 #endif
13529 #endif /* CONFIG_TDLS */
13530
13531         return ret;
13532 }
13533
13534 static int rtw_tdls_ch_offset(struct net_device *dev,
13535                                 struct iw_request_info *info,
13536                                 union iwreq_data *wrqu, char *extra)
13537 {
13538         int ret = 0;
13539
13540 #ifdef CONFIG_TDLS
13541 #ifdef CONFIG_TDLS_CH_SW        
13542         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13543         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13544
13545         DBG_8192C("[%s] ch_offset:%s\n", __FUNCTION__, extra);
13546
13547         extra[ wrqu->data.length ] = 0x00;
13548         ptdlsinfo->chsw_info.ch_offset = rtw_atoi( extra );
13549
13550         return ret;
13551
13552 #endif
13553 #endif /* CONFIG_TDLS */
13554
13555                 return ret;
13556 }
13557         
13558 static int rtw_tdls_pson(struct net_device *dev,
13559                                 struct iw_request_info *info,
13560                                 union iwreq_data *wrqu, char *extra)
13561 {
13562         int ret = 0;
13563
13564 #ifdef CONFIG_TDLS
13565         
13566         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13567         u8 i, j, mac_addr[ETH_ALEN];
13568         struct sta_info *ptdls_sta = NULL;
13569
13570         DBG_871X( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13571
13572         for (i=0, j=0; i < ETH_ALEN; i++, j+=3)
13573                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
13574
13575         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
13576
13577         issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 1, 3, 500);
13578
13579 #endif /* CONFIG_TDLS */
13580
13581                 return ret;
13582 }
13583         
13584 static int rtw_tdls_psoff(struct net_device *dev,
13585                                 struct iw_request_info *info,
13586                                 union iwreq_data *wrqu, char *extra)
13587 {
13588         int ret = 0;
13589
13590 #ifdef CONFIG_TDLS
13591         
13592         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13593         u8 i, j, mac_addr[ETH_ALEN];
13594         struct sta_info *ptdls_sta = NULL;
13595         
13596         DBG_8192C( "[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length -1  );
13597
13598         for (i=0, j=0; i < ETH_ALEN; i++, j+=3)
13599                 mac_addr[i]=key_2char2num(*(extra+j), *(extra+j+1));
13600
13601         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
13602
13603         if(ptdls_sta)
13604                 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 3, 500);
13605
13606 #endif /* CONFIG_TDLS */
13607
13608         return ret;
13609 }
13610
13611 static int rtw_tdls_setip(struct net_device *dev,
13612                                 struct iw_request_info *info,
13613                                 union iwreq_data *wrqu, char *extra)
13614 {
13615         int ret = 0;
13616
13617 #ifdef CONFIG_TDLS
13618 #ifdef CONFIG_WFD
13619         
13620         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13621         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13622         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
13623         u8 i=0, j=0, k=0, tag=0;
13624
13625         DBG_871X("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
13626
13627         while (i < 4) {
13628                 for (j=0; j < 4; j++) {
13629                         if (*( extra + j + tag ) == '.' || *( extra + j + tag ) == '\0') {
13630                                 if( j == 1 )
13631                                         pwfd_info->ip_address[i]=convert_ip_addr( '0', '0', *(extra+(j-1)+tag));
13632                                 if( j == 2 )
13633                                         pwfd_info->ip_address[i]=convert_ip_addr( '0', *(extra+(j-2)+tag), *(extra+(j-1)+tag));
13634                                 if( j == 3 )
13635                                         pwfd_info->ip_address[i]=convert_ip_addr( *(extra+(j-3)+tag), *(extra+(j-2)+tag), *(extra+(j-1)+tag));  
13636
13637                                 tag += j + 1;
13638                                 break;
13639                         }
13640                 }
13641                 i++;
13642         }
13643
13644         DBG_871X( "[%s] Set IP = %u.%u.%u.%u \n", __FUNCTION__, 
13645                 ptdlsinfo->wfd_info->ip_address[0],
13646                 ptdlsinfo->wfd_info->ip_address[1],
13647                 ptdlsinfo->wfd_info->ip_address[2],
13648                 ptdlsinfo->wfd_info->ip_address[3]);
13649
13650 #endif /* CONFIG_WFD */
13651 #endif /* CONFIG_TDLS */
13652
13653         return ret;
13654 }
13655
13656 static int rtw_tdls_getip(struct net_device *dev,
13657                                 struct iw_request_info *info,
13658                                 union iwreq_data *wrqu, char *extra)
13659 {
13660         int ret = 0;
13661
13662 #ifdef CONFIG_TDLS
13663 #ifdef CONFIG_WFD
13664         
13665         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13666         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13667         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
13668         
13669         DBG_871X( "[%s]\n", __FUNCTION__);
13670
13671         sprintf( extra, "\n\n%u.%u.%u.%u\n", 
13672                 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1], 
13673                 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
13674
13675         DBG_871X( "[%s] IP=%u.%u.%u.%u\n", __FUNCTION__,
13676                 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1], 
13677                 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
13678         
13679         wrqu->data.length = strlen( extra );
13680
13681 #endif /* CONFIG_WFD */
13682 #endif /* CONFIG_TDLS */
13683
13684         return ret;
13685 }
13686
13687 static int rtw_tdls_getport(struct net_device *dev,
13688                                struct iw_request_info *info,
13689                                union iwreq_data *wrqu, char *extra)
13690 {
13691         
13692         int ret = 0;    
13693
13694 #ifdef CONFIG_TDLS
13695 #ifdef CONFIG_WFD
13696
13697         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13698         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13699         struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
13700
13701         DBG_871X( "[%s]\n", __FUNCTION__);
13702
13703         sprintf( extra, "\n\n%d\n", pwfd_info->peer_rtsp_ctrlport );
13704         DBG_871X( "[%s] remote port = %d\n",
13705                 __FUNCTION__, pwfd_info->peer_rtsp_ctrlport );
13706         
13707         wrqu->data.length = strlen( extra );
13708
13709 #endif /* CONFIG_WFD */
13710 #endif /* CONFIG_TDLS */
13711
13712         return ret;
13713                 
13714 }
13715
13716 /* WFDTDLS, for sigma test */
13717 static int rtw_tdls_dis_result(struct net_device *dev,
13718                                struct iw_request_info *info,
13719                                union iwreq_data *wrqu, char *extra)
13720 {
13721         
13722         int ret = 0;    
13723
13724 #ifdef CONFIG_TDLS
13725 #ifdef CONFIG_WFD
13726
13727         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13728         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13729
13730         DBG_871X( "[%s]\n", __FUNCTION__);
13731
13732         if (ptdlsinfo->dev_discovered == _TRUE) {
13733                 sprintf( extra, "\n\nDis=1\n" );
13734                 ptdlsinfo->dev_discovered = _FALSE;
13735         }
13736         
13737         wrqu->data.length = strlen( extra );
13738
13739 #endif /* CONFIG_WFD */
13740 #endif /* CONFIG_TDLS */
13741
13742         return ret;
13743                 
13744 }
13745
13746 /* WFDTDLS, for sigma test */
13747 static int rtw_wfd_tdls_status(struct net_device *dev,
13748                                struct iw_request_info *info,
13749                                union iwreq_data *wrqu, char *extra)
13750 {
13751         
13752         int ret = 0;    
13753
13754 #ifdef CONFIG_TDLS
13755
13756         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13757         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
13758
13759         DBG_871X("[%s]\n", __FUNCTION__);
13760
13761         sprintf( extra, "\nlink_established:%d \n"
13762                 "sta_cnt:%d \n"
13763                 "sta_maximum:%d \n"
13764                 "cur_channel:%d \n"
13765                 "tdls_enable:%d"
13766 #ifdef CONFIG_TDLS_CH_SW
13767                 "ch_sw_state:%08x\n"
13768                 "chsw_on:%d\n"
13769                 "off_ch_num:%d\n"
13770                 "cur_time:%d\n"
13771                 "ch_offset:%d\n"
13772                 "delay_swtich_back:%d"
13773 #endif
13774                 ,
13775                 ptdlsinfo->link_established, ptdlsinfo->sta_cnt,
13776                 ptdlsinfo->sta_maximum, ptdlsinfo->cur_channel, 
13777                 ptdlsinfo->tdls_enable
13778 #ifdef CONFIG_TDLS_CH_SW
13779 ,
13780                 ptdlsinfo->chsw_info.ch_sw_state,
13781                 ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on),
13782                 ptdlsinfo->chsw_info.off_ch_num,
13783                 ptdlsinfo->chsw_info.cur_time,
13784                 ptdlsinfo->chsw_info.ch_offset,
13785                 ptdlsinfo->chsw_info.delay_switch_back
13786 #endif
13787 );
13788
13789         wrqu->data.length = strlen( extra );
13790
13791 #endif /* CONFIG_TDLS */
13792
13793         return ret;
13794                 
13795         }
13796
13797 static int rtw_tdls_getsta(struct net_device *dev,
13798                                struct iw_request_info *info,
13799                                union iwreq_data *wrqu, char *extra)
13800         {
13801         
13802         int ret = 0;
13803 #ifdef CONFIG_TDLS
13804         u8 i, j;
13805         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13806         u8 addr[ETH_ALEN] = {0};
13807         char charmac[17];
13808         struct sta_info *ptdls_sta = NULL;
13809
13810         DBG_871X("[%s] %s %d\n", __FUNCTION__,
13811                 (char *)wrqu->data.pointer, wrqu->data.length -1);
13812
13813         if(copy_from_user(charmac, wrqu->data.pointer+9, 17)){
13814                 ret = -EFAULT;
13815                 goto exit;
13816         }
13817         
13818         DBG_871X("[%s] %d, charmac:%s\n", __FUNCTION__, __LINE__, charmac);
13819         for (i=0, j=0 ; i < ETH_ALEN; i++, j+=3)
13820                 addr[i]=key_2char2num(*(charmac+j), *(charmac+j+1));
13821
13822         DBG_871X("[%s] %d, charmac:%s, addr:"MAC_FMT"\n",
13823                 __FUNCTION__, __LINE__, charmac, MAC_ARG(addr));
13824         ptdls_sta = rtw_get_stainfo(&padapter->stapriv, addr);  
13825         if(ptdls_sta) {
13826                 sprintf(extra, "\n\ntdls_sta_state=0x%08x\n", ptdls_sta->tdls_sta_state);
13827                 DBG_871X("\n\ntdls_sta_state=%d\n", ptdls_sta->tdls_sta_state);
13828         } else {
13829                 sprintf(extra, "\n\nNot found this sta\n");
13830                 DBG_871X("\n\nNot found this sta\n");
13831         }
13832         wrqu->data.length = strlen( extra );
13833
13834 #endif /* CONFIG_TDLS */
13835 exit:
13836         return ret;
13837                 
13838 }
13839
13840 static int rtw_tdls_get_best_ch(struct net_device *dev,
13841                                 struct iw_request_info *info,
13842                                 union iwreq_data *wrqu, char *extra)
13843 {
13844 #ifdef CONFIG_FIND_BEST_CHANNEL 
13845         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13846         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
13847         u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0;
13848
13849         for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) {
13850                 if (pmlmeext->channel_set[i].ChannelNum == 1)
13851                         index_24G = i;
13852                 if (pmlmeext->channel_set[i].ChannelNum == 36)
13853                         index_5G = i;
13854         }
13855         
13856         for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) {
13857                 /* 2.4G */
13858                 if (pmlmeext->channel_set[i].ChannelNum == 6 || pmlmeext->channel_set[i].ChannelNum == 11) {
13859                         if (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count) {
13860                                 index_24G = i;
13861                                 best_channel_24G = pmlmeext->channel_set[i].ChannelNum;
13862                         }
13863                 }
13864
13865                 /* 5G */
13866                 if (pmlmeext->channel_set[i].ChannelNum >= 36
13867                         && pmlmeext->channel_set[i].ChannelNum < 140) {
13868                          /* Find primary channel */
13869                         if (((pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0)
13870                                 && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
13871                                 index_5G = i;
13872                                 best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
13873                         }
13874                 }
13875
13876                 if (pmlmeext->channel_set[i].ChannelNum >= 149
13877                         && pmlmeext->channel_set[i].ChannelNum < 165) {
13878                          /* Find primary channel */
13879                         if (((pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0)
13880                                 && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
13881                                 index_5G = i;
13882                                 best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
13883                         }
13884                 }
13885 #if 1 /* debug */
13886                 DBG_871X("The rx cnt of channel %3d = %d\n", 
13887                                         pmlmeext->channel_set[i].ChannelNum,
13888                                         pmlmeext->channel_set[i].rx_count);
13889 #endif
13890         }
13891         
13892         sprintf( extra, "\nbest_channel_24G = %d\n", best_channel_24G );
13893         DBG_871X("best_channel_24G = %d\n", best_channel_24G);
13894
13895         if (index_5G != 0) {
13896                 sprintf(extra, "best_channel_5G = %d\n", best_channel_5G);
13897                 DBG_871X("best_channel_5G = %d\n", best_channel_5G);
13898         }
13899
13900         wrqu->data.length = strlen( extra );
13901
13902 #endif
13903
13904         return 0;
13905
13906 }
13907
13908 static int rtw_tdls(struct net_device *dev,
13909                                 struct iw_request_info *info,
13910                                 union iwreq_data *wrqu, char *extra)
13911 {
13912         int ret = 0;
13913
13914 #ifdef CONFIG_TDLS
13915
13916         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
13917
13918         DBG_871X( "[%s] extra = %s\n", __FUNCTION__, extra );
13919         /* WFD Sigma will use the tdls enable command to let the driver know we want to test the tdls now! */
13920         if (_rtw_memcmp(extra, "wfdenable=", 10)) {
13921                 wrqu->data.length -=10;
13922                 rtw_wfd_tdls_enable( dev, info, wrqu, &extra[10] );
13923                 return ret;
13924         } else if (_rtw_memcmp(extra, "weaksec=", 8)) {
13925                 wrqu->data.length -=8;
13926                 rtw_tdls_weaksec( dev, info, wrqu, &extra[8] );
13927                 return ret;
13928         } else if (_rtw_memcmp( extra, "tdlsenable=", 11)) {
13929                 wrqu->data.length -=11;
13930                 rtw_tdls_enable( dev, info, wrqu, &extra[11] );
13931                 return ret;
13932         }
13933
13934         if (padapter->tdlsinfo.tdls_enable == 0) {
13935                 DBG_871X("tdls haven't enabled\n");
13936                 return 0;
13937         }
13938
13939         if (_rtw_memcmp(extra, "setup=", 6)) {
13940                 wrqu->data.length -=6;
13941                 rtw_tdls_setup( dev, info, wrqu, &extra[6] );
13942         } else if (_rtw_memcmp(extra, "tear=", 5)) {
13943                 wrqu->data.length -= 5;
13944                 rtw_tdls_teardown( dev, info, wrqu, &extra[5] );
13945         } else if (_rtw_memcmp(extra, "dis=", 4)) {
13946                 wrqu->data.length -= 4;
13947                 rtw_tdls_discovery( dev, info, wrqu, &extra[4] );
13948         } else if (_rtw_memcmp(extra, "swoff=", 6)) {
13949                 wrqu->data.length -= 6;
13950                 rtw_tdls_ch_switch_off(dev, info, wrqu, &extra[6]);
13951         } else if (_rtw_memcmp(extra, "sw=", 3)) {
13952                 wrqu->data.length -= 3;
13953                 rtw_tdls_ch_switch( dev, info, wrqu, &extra[3] );
13954         } else if (_rtw_memcmp(extra, "dumpstack=", 10)) {
13955                 wrqu->data.length -= 10;
13956                 rtw_tdls_dump_ch(dev, info, wrqu, &extra[10]);
13957         } else if (_rtw_memcmp(extra, "offchnum=", 9)) {
13958                 wrqu->data.length -= 9;
13959                 rtw_tdls_off_ch_num(dev, info, wrqu, &extra[9]);
13960         } else if (_rtw_memcmp(extra, "choffset=", 9)) {
13961                 wrqu->data.length -= 9;
13962                 rtw_tdls_ch_offset(dev, info, wrqu, &extra[9]);
13963         } else if (_rtw_memcmp(extra, "pson=", 5)) {
13964                 wrqu->data.length -= 5;
13965                 rtw_tdls_pson( dev, info, wrqu, &extra[5] );
13966         } else if (_rtw_memcmp(extra, "psoff=", 6)) {
13967                 wrqu->data.length -= 6;
13968                 rtw_tdls_psoff( dev, info, wrqu, &extra[6] );
13969         }
13970 #ifdef CONFIG_WFD
13971         else if (_rtw_memcmp(extra, "setip=", 6)) {
13972                 wrqu->data.length -= 6;
13973                 rtw_tdls_setip( dev, info, wrqu, &extra[6] );
13974         } else if (_rtw_memcmp(extra, "tprobe=", 6)) {
13975                 issue_tunneled_probe_req((_adapter *)rtw_netdev_priv(dev));
13976         }
13977 #endif /* CONFIG_WFD */
13978
13979 #endif /* CONFIG_TDLS */
13980         
13981         return ret;
13982 }
13983
13984
13985 static int rtw_tdls_get(struct net_device *dev,
13986                                 struct iw_request_info *info,
13987                                 union iwreq_data *wrqu, char *extra)
13988 {
13989         int ret = 0;
13990
13991 #ifdef CONFIG_TDLS
13992
13993         DBG_871X( "[%s] extra = %s\n", __FUNCTION__, (char*) wrqu->data.pointer );
13994
13995         if ( _rtw_memcmp( wrqu->data.pointer, "ip", 2 ) )
13996                 rtw_tdls_getip( dev, info, wrqu, extra );
13997         else if (_rtw_memcmp(wrqu->data.pointer, "port", 4))
13998                 rtw_tdls_getport( dev, info, wrqu, extra );
13999         /* WFDTDLS, for sigma test */
14000         else if ( _rtw_memcmp(wrqu->data.pointer, "dis", 3))
14001                 rtw_tdls_dis_result( dev, info, wrqu, extra );
14002         else if ( _rtw_memcmp(wrqu->data.pointer, "status", 6))
14003                 rtw_wfd_tdls_status( dev, info, wrqu, extra );
14004         else if ( _rtw_memcmp(wrqu->data.pointer, "tdls_sta=", 9))
14005                 rtw_tdls_getsta( dev, info, wrqu, extra );
14006         else if (_rtw_memcmp(wrqu->data.pointer, "best_ch", 7))
14007                 rtw_tdls_get_best_ch(dev, info, wrqu, extra);
14008 #endif /* CONFIG_TDLS */
14009
14010         return ret;
14011 }
14012
14013
14014
14015
14016
14017 #ifdef CONFIG_INTEL_WIDI
14018 static int rtw_widi_set(struct net_device *dev,
14019                                struct iw_request_info *info,
14020                                union iwreq_data *wrqu, char *extra)
14021 {
14022         int ret = 0;
14023         _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
14024
14025         process_intel_widi_cmd(padapter, extra);
14026
14027         return ret;
14028 }
14029
14030 static int rtw_widi_set_probe_request(struct net_device *dev,
14031                                struct iw_request_info *info,
14032                                union iwreq_data *wrqu, char *extra)
14033 {
14034         int     ret = 0;
14035         u8      *pbuf = NULL;
14036         _adapter        *padapter = (_adapter *)rtw_netdev_priv(dev);
14037
14038         pbuf = rtw_malloc(sizeof(l2_msg_t));
14039         if(pbuf)
14040         {
14041                 if ( copy_from_user(pbuf, wrqu->data.pointer, wrqu->data.length) )
14042                         ret = -EFAULT;
14043                 //_rtw_memcpy(pbuf, wrqu->data.pointer, wrqu->data.length);
14044
14045                 if( wrqu->data.flags == 0 )
14046                         intel_widi_wk_cmd(padapter, INTEL_WIDI_ISSUE_PROB_WK, pbuf, sizeof(l2_msg_t));
14047                 else if( wrqu->data.flags == 1 )
14048                         rtw_set_wfd_rds_sink_info( padapter, (l2_msg_t *)pbuf );
14049         }
14050         return ret;
14051 }
14052 #endif // CONFIG_INTEL_WIDI
14053
14054 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
14055
14056 #if defined(CONFIG_RTL8188E)
14057 #include <rtl8188e_hal.h>
14058 extern void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
14059 #define cal_txdesc_chksum rtl8188e_cal_txdesc_chksum
14060 #ifdef CONFIG_SDIO_HCI || defined(CONFIG_GSPI_HCI)
14061 extern void rtl8188es_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
14062 #define fill_default_txdesc rtl8188es_fill_default_txdesc
14063 #endif // CONFIG_SDIO_HCI
14064 #endif // CONFIG_RTL8188E
14065 #if defined(CONFIG_RTL8723B)
14066 extern void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc);
14067 #define cal_txdesc_chksum rtl8723b_cal_txdesc_chksum
14068 extern void rtl8723b_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
14069 #define fill_default_txdesc rtl8723b_fill_default_txdesc
14070 #endif // CONFIG_RTL8723B
14071 #if defined(CONFIG_RTL8192E)
14072 extern void rtl8192e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
14073 #define cal_txdesc_chksum rtl8192e_cal_txdesc_chksum
14074 #ifdef CONFIG_SDIO_HCI || defined(CONFIG_GSPI_HCI)
14075 extern void rtl8192es_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
14076 #define fill_default_txdesc rtl8192es_fill_default_txdesc
14077 #endif // CONFIG_SDIO_HCI
14078 #endif //CONFIG_RTL8192E
14079
14080 static s32 initLoopback(PADAPTER padapter)
14081 {
14082         PLOOPBACKDATA ploopback;
14083
14084
14085         if (padapter->ploopback == NULL) {
14086                 ploopback = (PLOOPBACKDATA)rtw_zmalloc(sizeof(LOOPBACKDATA));
14087                 if (ploopback == NULL) return -ENOMEM;
14088
14089                 _rtw_init_sema(&ploopback->sema, 0);
14090                 ploopback->bstop = _TRUE;
14091                 ploopback->cnt = 0;
14092                 ploopback->size = 300;
14093                 _rtw_memset(ploopback->msg, 0, sizeof(ploopback->msg));
14094
14095                 padapter->ploopback = ploopback;
14096         }
14097
14098         return 0;
14099 }
14100
14101 static void freeLoopback(PADAPTER padapter)
14102 {
14103         PLOOPBACKDATA ploopback;
14104
14105
14106         ploopback = padapter->ploopback;
14107         if (ploopback) {
14108                 rtw_mfree((u8*)ploopback, sizeof(LOOPBACKDATA));
14109                 padapter->ploopback = NULL;
14110         }
14111 }
14112
14113 static s32 initpseudoadhoc(PADAPTER padapter)
14114 {
14115         NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
14116         s32 err;
14117
14118         networkType = Ndis802_11IBSS;
14119         err = rtw_set_802_11_infrastructure_mode(padapter, networkType);
14120         if (err == _FALSE) return _FAIL;
14121
14122         err = rtw_setopmode_cmd(padapter, networkType,_TRUE);
14123         if (err == _FAIL) return _FAIL;
14124
14125         return _SUCCESS;
14126 }
14127
14128 static s32 createpseudoadhoc(PADAPTER padapter)
14129 {
14130         NDIS_802_11_AUTHENTICATION_MODE authmode;
14131         struct mlme_priv *pmlmepriv;
14132         NDIS_802_11_SSID *passoc_ssid;
14133         WLAN_BSSID_EX *pdev_network;
14134         u8 *pibss;
14135         u8 ssid[] = "pseduo_ad-hoc";
14136         s32 err;
14137         _irqL irqL;
14138
14139
14140         pmlmepriv = &padapter->mlmepriv;
14141
14142         authmode = Ndis802_11AuthModeOpen;
14143         err = rtw_set_802_11_authentication_mode(padapter, authmode);
14144         if (err == _FALSE) return _FAIL;
14145
14146         passoc_ssid = &pmlmepriv->assoc_ssid;
14147         _rtw_memset(passoc_ssid, 0, sizeof(NDIS_802_11_SSID));
14148         passoc_ssid->SsidLength = sizeof(ssid) - 1;
14149         _rtw_memcpy(passoc_ssid->Ssid, ssid, passoc_ssid->SsidLength);
14150
14151         pdev_network = &padapter->registrypriv.dev_network;
14152         pibss = padapter->registrypriv.dev_network.MacAddress;
14153         _rtw_memcpy(&pdev_network->Ssid, passoc_ssid, sizeof(NDIS_802_11_SSID));
14154
14155         rtw_update_registrypriv_dev_network(padapter);
14156         rtw_generate_random_ibss(pibss);
14157
14158         _enter_critical_bh(&pmlmepriv->lock, &irqL);
14159         pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
14160         _exit_critical_bh(&pmlmepriv->lock, &irqL);
14161
14162 #if 0
14163         err = rtw_createbss_cmd(padapter);
14164         if (err == _FAIL) return _FAIL;
14165 #else
14166 {
14167         struct wlan_network *pcur_network;
14168         struct sta_info *psta;
14169
14170         //3  create a new psta
14171         pcur_network = &pmlmepriv->cur_network;
14172
14173         //clear psta in the cur_network, if any
14174         psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
14175         if (psta) rtw_free_stainfo(padapter, psta);
14176
14177         psta = rtw_alloc_stainfo(&padapter->stapriv, pibss);
14178         if (psta == NULL) return _FAIL;
14179
14180         //3  join psudo AdHoc
14181         pcur_network->join_res = 1;
14182         pcur_network->aid = psta->aid = 1;
14183         _rtw_memcpy(&pcur_network->network, pdev_network, get_WLAN_BSSID_EX_sz(pdev_network));
14184
14185         // set msr to WIFI_FW_ADHOC_STATE
14186 #if 0
14187         Set_NETYPE0_MSR(padapter, WIFI_FW_ADHOC_STATE);
14188 #else
14189         {
14190                 u8 val8;
14191
14192                 val8 = rtw_read8(padapter, MSR);
14193                 val8 &= 0xFC; // clear NETYPE0
14194                 val8 |= WIFI_FW_ADHOC_STATE & 0x3;
14195                 rtw_write8(padapter, MSR, val8);
14196         }
14197 #endif
14198 }
14199 #endif
14200
14201         return _SUCCESS;
14202 }
14203
14204 static struct xmit_frame* createloopbackpkt(PADAPTER padapter, u32 size)
14205 {
14206         struct xmit_priv *pxmitpriv;
14207         struct xmit_frame *pframe;
14208         struct xmit_buf *pxmitbuf;
14209         struct pkt_attrib *pattrib;
14210         struct tx_desc *desc;
14211         u8 *pkt_start, *pkt_end, *ptr;
14212         struct rtw_ieee80211_hdr *hdr;
14213         s32 bmcast;
14214         _irqL irqL;
14215
14216
14217         if ((TXDESC_SIZE + WLANHDR_OFFSET + size) > MAX_XMITBUF_SZ) return NULL;
14218
14219         pxmitpriv = &padapter->xmitpriv;
14220         pframe = NULL;
14221
14222         //2 1. allocate xmit frame
14223         pframe = rtw_alloc_xmitframe(pxmitpriv);
14224         if (pframe == NULL) return NULL;
14225         pframe->padapter = padapter;
14226
14227         //2 2. allocate xmit buffer
14228         _enter_critical_bh(&pxmitpriv->lock, &irqL);
14229         pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
14230         _exit_critical_bh(&pxmitpriv->lock, &irqL);
14231         if (pxmitbuf == NULL) {
14232                 rtw_free_xmitframe(pxmitpriv, pframe);
14233                 return NULL;
14234         }
14235
14236         pframe->pxmitbuf = pxmitbuf;
14237         pframe->buf_addr = pxmitbuf->pbuf;
14238         pxmitbuf->priv_data = pframe;
14239
14240         //2 3. update_attrib()
14241         pattrib = &pframe->attrib;
14242
14243         // init xmitframe attribute
14244         _rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
14245
14246         pattrib->ether_type = 0x8723;
14247         _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
14248         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
14249         _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
14250         _rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
14251
14252 //      pattrib->dhcp_pkt = 0;
14253 //      pattrib->pktlen = 0;
14254         pattrib->ack_policy = 0;
14255 //      pattrib->pkt_hdrlen = ETH_HLEN;
14256         pattrib->hdrlen = WLAN_HDR_A3_LEN;
14257         pattrib->subtype = WIFI_DATA;
14258         pattrib->priority = 0;
14259         pattrib->qsel = pattrib->priority;
14260 //      do_queue_select(padapter, pattrib);
14261         pattrib->nr_frags = 1;
14262         pattrib->encrypt = 0;
14263         pattrib->bswenc = _FALSE;
14264         pattrib->qos_en = _FALSE;
14265
14266         bmcast = IS_MCAST(pattrib->ra);
14267         if (bmcast) {
14268                 pattrib->mac_id = 1;
14269                 pattrib->psta = rtw_get_bcmc_stainfo(padapter);
14270         } else {
14271                 pattrib->mac_id = 0;
14272                 pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
14273         }
14274
14275         pattrib->pktlen = size;
14276         pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
14277
14278         //2 4. fill TX descriptor
14279         desc = (struct tx_desc*)pframe->buf_addr;
14280         _rtw_memset(desc, 0, TXDESC_SIZE);
14281
14282         fill_default_txdesc(pframe, (u8*)desc);
14283
14284         // Hw set sequence number
14285         ((PTXDESC)desc)->hwseq_en = 0; // HWSEQ_EN, 0:disable, 1:enable
14286 //      ((PTXDESC)desc)->hwseq_sel = 0; // HWSEQ_SEL
14287
14288         ((PTXDESC)desc)->disdatafb = 1;
14289
14290         // convert to little endian
14291         desc->txdw0 = cpu_to_le32(desc->txdw0);
14292         desc->txdw1 = cpu_to_le32(desc->txdw1);
14293         desc->txdw2 = cpu_to_le32(desc->txdw2);
14294         desc->txdw3 = cpu_to_le32(desc->txdw3);
14295         desc->txdw4 = cpu_to_le32(desc->txdw4);
14296         desc->txdw5 = cpu_to_le32(desc->txdw5);
14297         desc->txdw6 = cpu_to_le32(desc->txdw6);
14298         desc->txdw7 = cpu_to_le32(desc->txdw7);
14299 #ifdef CONFIG_PCI_HCI
14300         desc->txdw8 = cpu_to_le32(desc->txdw8);
14301         desc->txdw9 = cpu_to_le32(desc->txdw9);
14302         desc->txdw10 = cpu_to_le32(desc->txdw10);
14303         desc->txdw11 = cpu_to_le32(desc->txdw11);
14304         desc->txdw12 = cpu_to_le32(desc->txdw12);
14305         desc->txdw13 = cpu_to_le32(desc->txdw13);
14306         desc->txdw14 = cpu_to_le32(desc->txdw14);
14307         desc->txdw15 = cpu_to_le32(desc->txdw15);
14308 #endif
14309
14310         cal_txdesc_chksum(desc);
14311
14312         //2 5. coalesce
14313         pkt_start = pframe->buf_addr + TXDESC_SIZE;
14314         pkt_end = pkt_start + pattrib->last_txcmdsz;
14315
14316         //3 5.1. make wlan header, make_wlanhdr()
14317         hdr = (struct rtw_ieee80211_hdr *)pkt_start;
14318         SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
14319         _rtw_memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); // DA
14320         _rtw_memcpy(hdr->addr2, pattrib->src, ETH_ALEN); // SA
14321         _rtw_memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); // RA, BSSID
14322
14323         //3 5.2. make payload
14324         ptr = pkt_start + pattrib->hdrlen;
14325         get_random_bytes(ptr, pkt_end - ptr);
14326
14327         pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
14328         pxmitbuf->ptail += pxmitbuf->len;
14329
14330         return pframe;
14331 }
14332
14333 static void freeloopbackpkt(PADAPTER padapter, struct xmit_frame *pframe)
14334 {
14335         struct xmit_priv *pxmitpriv;
14336         struct xmit_buf *pxmitbuf;
14337
14338
14339         pxmitpriv = &padapter->xmitpriv;
14340         pxmitbuf = pframe->pxmitbuf;
14341
14342         rtw_free_xmitframe(pxmitpriv, pframe);
14343         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
14344 }
14345
14346 static void printdata(u8 *pbuf, u32 len)
14347 {
14348         u32 i, val;
14349
14350
14351         for (i = 0; (i+4) <= len; i+=4) {
14352                 printk("%08X", *(u32*)(pbuf + i));
14353                 if ((i+4) & 0x1F) printk(" ");
14354                 else printk("\n");
14355         }
14356
14357         if (i < len)
14358         {
14359 #ifdef CONFIG_BIG_ENDIAN
14360                 for (; i < len, i++)
14361                         printk("%02X", pbuf+i);
14362 #else // CONFIG_LITTLE_ENDIAN
14363 #if 0
14364                 val = 0;
14365                 _rtw_memcpy(&val, pbuf + i, len - i);
14366                 printk("%8X", val);
14367 #else
14368                 u8 str[9];
14369                 u8 n;
14370                 val = 0;
14371                 n = len - i;
14372                 _rtw_memcpy(&val, pbuf+i, n);
14373                 sprintf(str, "%08X", val);
14374                 n = (4 - n) * 2;
14375                 printk("%8s", str+n);
14376 #endif
14377 #endif // CONFIG_LITTLE_ENDIAN
14378         }
14379         printk("\n");
14380 }
14381
14382 static u8 pktcmp(PADAPTER padapter, u8 *txbuf, u32 txsz, u8 *rxbuf, u32 rxsz)
14383 {
14384         PHAL_DATA_TYPE phal;
14385         struct recv_stat *prxstat;
14386         struct recv_stat report;
14387         PRXREPORT prxreport;
14388         u32 drvinfosize;
14389         u32 rxpktsize;
14390         u8 fcssize;
14391         u8 ret = _FALSE;
14392
14393         prxstat = (struct recv_stat*)rxbuf;
14394         report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
14395         report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
14396         report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
14397         report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
14398         report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
14399         report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
14400
14401         prxreport = (PRXREPORT)&report;
14402         drvinfosize = prxreport->drvinfosize << 3;
14403         rxpktsize = prxreport->pktlen;
14404
14405         phal = GET_HAL_DATA(padapter);
14406         if (phal->ReceiveConfig & RCR_APPFCS) fcssize = IEEE80211_FCS_LEN;
14407         else fcssize = 0;
14408
14409         if ((txsz - TXDESC_SIZE) != (rxpktsize - fcssize)) {
14410                 DBG_8192C("%s: ERROR! size not match tx/rx=%d/%d !\n",
14411                         __func__, txsz - TXDESC_SIZE, rxpktsize - fcssize);
14412                 ret = _FALSE;
14413         } else {
14414                 ret = _rtw_memcmp(txbuf + TXDESC_SIZE,\
14415                                                   rxbuf + RXDESC_SIZE + drvinfosize,\
14416                                                   txsz - TXDESC_SIZE);
14417                 if (ret == _FALSE) {
14418                         DBG_8192C("%s: ERROR! pkt content mismatch!\n", __func__);
14419                 }
14420         }
14421
14422         if (ret == _FALSE)
14423         {
14424                 DBG_8192C("\n%s: TX PKT total=%d, desc=%d, content=%d\n",
14425                         __func__, txsz, TXDESC_SIZE, txsz - TXDESC_SIZE);
14426                 DBG_8192C("%s: TX DESC size=%d\n", __func__, TXDESC_SIZE);
14427                 printdata(txbuf, TXDESC_SIZE);
14428                 DBG_8192C("%s: TX content size=%d\n", __func__, txsz - TXDESC_SIZE);
14429                 printdata(txbuf + TXDESC_SIZE, txsz - TXDESC_SIZE);
14430
14431                 DBG_8192C("\n%s: RX PKT read=%d offset=%d(%d,%d) content=%d\n",
14432                         __func__, rxsz, RXDESC_SIZE + drvinfosize, RXDESC_SIZE, drvinfosize, rxpktsize);
14433                 if (rxpktsize != 0)
14434                 {
14435                         DBG_8192C("%s: RX DESC size=%d\n", __func__, RXDESC_SIZE);
14436                         printdata(rxbuf, RXDESC_SIZE);
14437                         DBG_8192C("%s: RX drvinfo size=%d\n", __func__, drvinfosize);
14438                         printdata(rxbuf + RXDESC_SIZE, drvinfosize);
14439                         DBG_8192C("%s: RX content size=%d\n", __func__, rxpktsize);
14440                         printdata(rxbuf + RXDESC_SIZE + drvinfosize, rxpktsize);
14441                 } else {
14442                         DBG_8192C("%s: RX data size=%d\n", __func__, rxsz);
14443                         printdata(rxbuf, rxsz);
14444                 }
14445         }
14446
14447         return ret;
14448 }
14449
14450 thread_return lbk_thread(thread_context context)
14451 {
14452         s32 err;
14453         PADAPTER padapter;
14454         PLOOPBACKDATA ploopback;
14455         struct xmit_frame *pxmitframe;
14456         u32 cnt, ok, fail, headerlen;
14457         u32 pktsize;
14458         u32 ff_hwaddr;
14459
14460
14461         padapter = (PADAPTER)context;
14462         ploopback = padapter->ploopback;
14463         if (ploopback == NULL) return -1;
14464         cnt = 0;
14465         ok = 0;
14466         fail = 0;
14467
14468         daemonize("%s", "RTW_LBK_THREAD");
14469         allow_signal(SIGTERM);
14470
14471         do {
14472                 if (ploopback->size == 0) {
14473                         get_random_bytes(&pktsize, 4);
14474                         pktsize = (pktsize % 1535) + 1; // 1~1535
14475                 } else
14476                         pktsize = ploopback->size;
14477                 
14478                 pxmitframe = createloopbackpkt(padapter, pktsize);
14479                 if (pxmitframe == NULL) {
14480                         sprintf(ploopback->msg, "loopback FAIL! 3. create Packet FAIL!");
14481                         break;
14482                 }
14483
14484                 ploopback->txsize = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
14485                 _rtw_memcpy(ploopback->txbuf, pxmitframe->buf_addr, ploopback->txsize);
14486                 ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
14487                 cnt++;
14488                 DBG_8192C("%s: wirte port cnt=%d size=%d\n", __func__, cnt, ploopback->txsize);
14489                 pxmitframe->pxmitbuf->pdata = ploopback->txbuf;
14490                 rtw_write_port(padapter, ff_hwaddr, ploopback->txsize, (u8 *)pxmitframe->pxmitbuf);
14491
14492                 // wait for rx pkt
14493                 _rtw_down_sema(&ploopback->sema);
14494
14495                 err = pktcmp(padapter, ploopback->txbuf, ploopback->txsize, ploopback->rxbuf, ploopback->rxsize);
14496                 if (err == _TRUE)
14497                         ok++;
14498                 else
14499                         fail++;
14500
14501                 ploopback->txsize = 0;
14502                 _rtw_memset(ploopback->txbuf, 0, 0x8000);
14503                 ploopback->rxsize = 0;
14504                 _rtw_memset(ploopback->rxbuf, 0, 0x8000);
14505
14506                 freeloopbackpkt(padapter, pxmitframe);
14507                 pxmitframe = NULL;
14508
14509                 if (signal_pending(current)) {
14510                         flush_signals(current);
14511                 }
14512
14513                 if ((ploopback->bstop == _TRUE) ||
14514                         ((ploopback->cnt != 0) && (ploopback->cnt == cnt)))
14515                 {
14516                         u32 ok_rate, fail_rate, all;
14517                         all = cnt;
14518                         ok_rate = (ok*100)/all;
14519                         fail_rate = (fail*100)/all;
14520                         sprintf(ploopback->msg,\
14521                                         "loopback result: ok=%d%%(%d/%d),error=%d%%(%d/%d)",\
14522                                         ok_rate, ok, all, fail_rate, fail, all);
14523                         break;
14524                 }
14525         } while (1);
14526
14527         ploopback->bstop = _TRUE;
14528
14529         thread_exit();
14530 }
14531
14532 static void loopbackTest(PADAPTER padapter, u32 cnt, u32 size, u8* pmsg)
14533 {
14534         PLOOPBACKDATA ploopback;
14535         u32 len;
14536         s32 err;
14537
14538
14539         ploopback = padapter->ploopback;
14540
14541         if (ploopback)
14542         {
14543                 if (ploopback->bstop == _FALSE) {
14544                         ploopback->bstop = _TRUE;
14545                         _rtw_up_sema(&ploopback->sema);
14546                 }
14547                 len = 0;
14548                 do {
14549                         len = strlen(ploopback->msg);
14550                         if (len) break;
14551                         rtw_msleep_os(1);
14552                 } while (1);
14553                 _rtw_memcpy(pmsg, ploopback->msg, len+1);
14554                 freeLoopback(padapter);
14555
14556                 return;
14557         }
14558
14559         // disable dynamic algorithm    
14560         Save_DM_Func_Flag(padapter);
14561         Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
14562
14563         // create pseudo ad-hoc connection
14564         err = initpseudoadhoc(padapter);
14565         if (err == _FAIL) {
14566                 sprintf(pmsg, "loopback FAIL! 1.1 init ad-hoc FAIL!");
14567                 return;
14568         }
14569
14570         err = createpseudoadhoc(padapter);
14571         if (err == _FAIL) {
14572                 sprintf(pmsg, "loopback FAIL! 1.2 create ad-hoc master FAIL!");
14573                 return;
14574         }
14575
14576         err = initLoopback(padapter);
14577         if (err) {
14578                 sprintf(pmsg, "loopback FAIL! 2. init FAIL! error code=%d", err);
14579                 return;
14580         }
14581
14582         ploopback = padapter->ploopback;
14583
14584         ploopback->bstop = _FALSE;
14585         ploopback->cnt = cnt;
14586         ploopback->size = size;
14587         ploopback->lbkthread = kthread_run(lbk_thread, padapter, "RTW_LBK_THREAD");
14588         if (IS_ERR(padapter->lbkthread))
14589         {
14590                 freeLoopback(padapter);
14591                 sprintf(pmsg, "loopback start FAIL! cnt=%d", cnt);
14592                 return;
14593         }
14594
14595         sprintf(pmsg, "loopback start! cnt=%d", cnt);
14596 }
14597 #endif // CONFIG_MAC_LOOPBACK_DRIVER
14598
14599 static int rtw_test(
14600         struct net_device *dev,
14601         struct iw_request_info *info,
14602         union iwreq_data *wrqu, char *extra)
14603 {
14604         u32 len;
14605         u8 *pbuf, *pch;
14606         char *ptmp;
14607         u8 *delim = ",";
14608         PADAPTER padapter = rtw_netdev_priv(dev);
14609
14610
14611         DBG_871X("+%s\n", __func__);
14612         len = wrqu->data.length;
14613
14614         pbuf = (u8*)rtw_zmalloc(len);
14615         if (pbuf == NULL) {
14616                 DBG_871X("%s: no memory!\n", __func__);
14617                 return -ENOMEM;
14618         }
14619
14620         if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
14621                 rtw_mfree(pbuf, len);
14622                 DBG_871X("%s: copy from user fail!\n", __func__);
14623                 return -EFAULT;
14624         }
14625         DBG_871X("%s: string=\"%s\"\n", __func__, pbuf);
14626
14627         ptmp = (char*)pbuf;
14628         pch = strsep(&ptmp, delim);
14629         if ((pch == NULL) || (strlen(pch) == 0)) {
14630                 rtw_mfree(pbuf, len);
14631                 DBG_871X("%s: parameter error(level 1)!\n", __func__);
14632                 return -EFAULT;
14633         }
14634
14635 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
14636         if (strcmp(pch, "loopback") == 0)
14637         {
14638                 s32 cnt = 0;
14639                 u32 size = 64;
14640
14641                 pch = strsep(&ptmp, delim);
14642                 if ((pch == NULL) || (strlen(pch) == 0)) {
14643                         rtw_mfree(pbuf, len);
14644                         DBG_871X("%s: parameter error(level 2)!\n", __func__);
14645                         return -EFAULT;
14646                 }
14647
14648                 sscanf(pch, "%d", &cnt);
14649                 DBG_871X("%s: loopback cnt=%d\n", __func__, cnt);
14650
14651                 pch = strsep(&ptmp, delim);
14652                 if ((pch == NULL) || (strlen(pch) == 0)) {
14653                         rtw_mfree(pbuf, len);
14654                         DBG_871X("%s: parameter error(level 2)!\n", __func__);
14655                         return -EFAULT;
14656                 }
14657
14658                 sscanf(pch, "%d", &size);
14659                 DBG_871X("%s: loopback size=%d\n", __func__, size);
14660
14661                 loopbackTest(padapter, cnt, size, extra);
14662                 wrqu->data.length = strlen(extra) + 1;
14663
14664                 rtw_mfree(pbuf, len);
14665                 return 0;
14666         }
14667 #endif
14668
14669
14670 #ifdef CONFIG_BT_COEXIST
14671         if (strcmp(pch, "bton") == 0)
14672         {
14673                 rtw_btcoex_SetManualControl(padapter, _FALSE);
14674         }
14675         else if (strcmp(pch, "btoff") == 0)
14676         {
14677                 rtw_btcoex_SetManualControl(padapter, _TRUE);
14678         }
14679         else if (strcmp(pch, "h2c") == 0)
14680         {
14681                 u8 param[8];
14682                 u8 count = 0;
14683                 u32 tmp;
14684                 u8 i;
14685                 u32 pos;
14686                 s32 ret;
14687
14688
14689                 do {
14690                         pch = strsep(&ptmp, delim);
14691                         if ((pch == NULL) || (strlen(pch) == 0))
14692                                 break;
14693
14694                         sscanf(pch, "%x", &tmp);
14695                         param[count++] = (u8)tmp;
14696                 } while (count < 8);
14697
14698                 if (count == 0) {
14699                         rtw_mfree(pbuf, len);
14700                         DBG_871X("%s: parameter error(level 2)!\n", __func__);
14701                         return -EFAULT;
14702                 }
14703
14704                 ret = rtw_hal_fill_h2c_cmd(padapter, param[0], count-1, &param[1]);
14705
14706                 pos = sprintf(extra, "H2C ID=0x%02x content=", param[0]);
14707                 for (i=1; i<count; i++) {
14708                         pos += sprintf(extra+pos, "%02x,", param[i]);
14709                 }
14710                 extra[pos] = 0;
14711                 pos--;
14712                 pos += sprintf(extra+pos, " %s", ret==_FAIL?"FAIL":"OK");
14713
14714                 wrqu->data.length = strlen(extra) + 1;
14715         }
14716 #endif // CONFIG_BT_COEXIST
14717
14718         rtw_mfree(pbuf, len);
14719         return 0;
14720 }
14721
14722 static iw_handler rtw_handlers[] =
14723 {
14724         NULL,                                   /* SIOCSIWCOMMIT */
14725         rtw_wx_get_name,                /* SIOCGIWNAME */
14726         dummy,                                  /* SIOCSIWNWID */
14727         dummy,                                  /* SIOCGIWNWID */
14728         rtw_wx_set_freq,                /* SIOCSIWFREQ */
14729         rtw_wx_get_freq,                /* SIOCGIWFREQ */
14730         rtw_wx_set_mode,                /* SIOCSIWMODE */
14731         rtw_wx_get_mode,                /* SIOCGIWMODE */
14732         dummy,                                  /* SIOCSIWSENS */
14733         rtw_wx_get_sens,                /* SIOCGIWSENS */
14734         NULL,                                   /* SIOCSIWRANGE */
14735         rtw_wx_get_range,               /* SIOCGIWRANGE */
14736         rtw_wx_set_priv,                /* SIOCSIWPRIV */
14737         NULL,                                   /* SIOCGIWPRIV */
14738         NULL,                                   /* SIOCSIWSTATS */
14739         NULL,                                   /* SIOCGIWSTATS */
14740         dummy,                                  /* SIOCSIWSPY */
14741         dummy,                                  /* SIOCGIWSPY */
14742         NULL,                                   /* SIOCGIWTHRSPY */
14743         NULL,                                   /* SIOCWIWTHRSPY */
14744         rtw_wx_set_wap,         /* SIOCSIWAP */
14745         rtw_wx_get_wap,         /* SIOCGIWAP */
14746         rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
14747         dummy,                                  /* SIOCGIWAPLIST -- depricated */
14748         rtw_wx_set_scan,                /* SIOCSIWSCAN */
14749         rtw_wx_get_scan,                /* SIOCGIWSCAN */
14750         rtw_wx_set_essid,               /* SIOCSIWESSID */
14751         rtw_wx_get_essid,               /* SIOCGIWESSID */
14752         dummy,                                  /* SIOCSIWNICKN */
14753         rtw_wx_get_nick,                /* SIOCGIWNICKN */
14754         NULL,                                   /* -- hole -- */
14755         NULL,                                   /* -- hole -- */
14756         rtw_wx_set_rate,                /* SIOCSIWRATE */
14757         rtw_wx_get_rate,                /* SIOCGIWRATE */
14758         rtw_wx_set_rts,                 /* SIOCSIWRTS */
14759         rtw_wx_get_rts,                 /* SIOCGIWRTS */
14760         rtw_wx_set_frag,                /* SIOCSIWFRAG */
14761         rtw_wx_get_frag,                /* SIOCGIWFRAG */
14762         dummy,                                  /* SIOCSIWTXPOW */
14763         dummy,                                  /* SIOCGIWTXPOW */
14764         dummy,                                  /* SIOCSIWRETRY */
14765         rtw_wx_get_retry,               /* SIOCGIWRETRY */
14766         rtw_wx_set_enc,                 /* SIOCSIWENCODE */
14767         rtw_wx_get_enc,                 /* SIOCGIWENCODE */
14768         dummy,                                  /* SIOCSIWPOWER */
14769         rtw_wx_get_power,               /* SIOCGIWPOWER */
14770         NULL,                                   /*---hole---*/
14771         NULL,                                   /*---hole---*/
14772         rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
14773         NULL,                                   /* SIOCGWGENIE */
14774         rtw_wx_set_auth,                /* SIOCSIWAUTH */
14775         NULL,                                   /* SIOCGIWAUTH */
14776         rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
14777         NULL,                                   /* SIOCGIWENCODEEXT */
14778         rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
14779         NULL,                                   /*---hole---*/
14780 }; 
14781
14782
14783 static const struct iw_priv_args rtw_private_args[] = {
14784         {
14785                 SIOCIWFIRSTPRIV + 0x0,
14786                 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
14787         },
14788         {
14789                 SIOCIWFIRSTPRIV + 0x1,
14790                 IW_PRIV_TYPE_CHAR | 0x7FF,
14791                 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
14792         },
14793         {
14794                 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
14795         },
14796         {
14797                 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
14798         },
14799         {
14800                 SIOCIWFIRSTPRIV + 0x4,
14801                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
14802         },
14803         {
14804                 SIOCIWFIRSTPRIV + 0x5,
14805                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
14806         },
14807         {
14808                 SIOCIWFIRSTPRIV + 0x6,
14809                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
14810         },
14811 //for PLATFORM_MT53XX   
14812         {
14813                 SIOCIWFIRSTPRIV + 0x7,
14814                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
14815         },
14816         {
14817                 SIOCIWFIRSTPRIV + 0x8,
14818                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
14819         },
14820         {
14821                 SIOCIWFIRSTPRIV + 0x9,
14822                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
14823         },
14824
14825 //for RTK_DMP_PLATFORM  
14826         {
14827                 SIOCIWFIRSTPRIV + 0xA,
14828                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
14829         },
14830
14831         {
14832                 SIOCIWFIRSTPRIV + 0xB,
14833                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
14834         },      
14835         {
14836                 SIOCIWFIRSTPRIV + 0xC,
14837                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
14838         },
14839         {
14840                 SIOCIWFIRSTPRIV + 0xD,
14841                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
14842         },
14843 #if 0
14844         {
14845                 SIOCIWFIRSTPRIV + 0xE,0,0, "wowlan_ctrl"
14846         },
14847 #endif
14848         {
14849                 SIOCIWFIRSTPRIV + 0x10,
14850                 IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
14851         },
14852         {
14853                 SIOCIWFIRSTPRIV + 0x11,
14854                 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "p2p_get"
14855         },
14856         {
14857                 SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
14858         },
14859         {
14860                 SIOCIWFIRSTPRIV + 0x13,
14861                 IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2"
14862         },      
14863         {
14864                 SIOCIWFIRSTPRIV + 0x14,
14865                 IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
14866         },
14867         {
14868                 SIOCIWFIRSTPRIV + 0x15,
14869                 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "tdls_get"
14870         },      
14871         {
14872                 SIOCIWFIRSTPRIV + 0x16,
14873                 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
14874         },
14875
14876         {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
14877 #ifdef CONFIG_MP_INCLUDED
14878         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0,  "NULL"},
14879         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "NULL"},
14880 #else
14881         {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
14882         {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
14883 #endif
14884         {
14885                 SIOCIWFIRSTPRIV + 0x1D,
14886                 IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
14887         },
14888
14889 #ifdef CONFIG_INTEL_WIDI
14890         {
14891                 SIOCIWFIRSTPRIV + 0x1E,
14892                 IW_PRIV_TYPE_CHAR | 1024, 0, "widi_set"
14893         },
14894         {
14895                 SIOCIWFIRSTPRIV + 0x1F,
14896                 IW_PRIV_TYPE_CHAR | 128, 0, "widi_prob_req"
14897         },
14898 #endif // CONFIG_INTEL_WIDI
14899
14900 #ifdef CONFIG_MP_INCLUDED
14901         { SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0 , ""},  //set 
14902         { SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , ""},//get
14903 /* --- sub-ioctls definitions --- */   
14904                 { MP_START , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start" }, //set
14905                 { MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara" },//get
14906                 { MP_STOP , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop" }, //set
14907                 { MP_CHANNEL , IW_PRIV_TYPE_CHAR | 1024 , IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel" },//get
14908                 { MP_BANDWIDTH , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, //set
14909                 { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },//get
14910                 { MP_RESET_STATS , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
14911                 { MP_QUERY , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "mp_query"}, //get
14912                 { READ_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg" },
14913                 { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
14914                 { READ_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf" },
14915                 { MP_PSD , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"}, 
14916                 { MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump" },
14917                 { MP_TXPOWER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
14918                 { MP_ANT_TX , IW_PRIV_TYPE_CHAR | 1024,  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
14919                 { MP_ANT_RX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
14920                 { WRITE_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg" },
14921                 { WRITE_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf" },
14922                 { MP_CTX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
14923                 { MP_ARX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
14924                 { MP_THER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
14925                 { EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set" },
14926                 { EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get" },
14927                 { MP_PWRTRK , IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
14928                 { MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery" },
14929                 { MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, // mp_ioctl       
14930                 { MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath" },               
14931                 { MP_PwrCtlDM, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrctldm" },                
14932                 { MP_GET_TXPOWER_INX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_get_txpower" },
14933                 { MP_GETVER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_priv_ver" },
14934                 { MP_MON, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_mon" },
14935                 { EFUSE_MASK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_mask" },
14936                 { EFUSE_FILE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_file" },
14937 #if defined(CONFIG_RTL8723B)
14938                 { MP_SetBT, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_setbt" },
14939         { MP_DISABLE_BT_COEXIST, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_disa_btcoex"},
14940 #endif
14941                 { CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
14942 #endif
14943 #ifdef CONFIG_WOWLAN
14944                 { MP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" }, //set 
14945 #endif
14946 #ifdef CONFIG_AP_WOWLAN
14947                 { MP_AP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, //set 
14948 #endif
14949 };
14950
14951 static iw_handler rtw_private_handler[] = 
14952 {
14953         rtw_wx_write32,                                 //0x00
14954         rtw_wx_read32,                                  //0x01
14955         rtw_drvext_hdl,                                 //0x02
14956         rtw_mp_ioctl_hdl,                               //0x03
14957
14958 // for MM DTV platform
14959         rtw_get_ap_info,                                        //0x04
14960
14961         rtw_set_pid,                                            //0x05
14962         rtw_wps_start,                                  //0x06
14963
14964 // for PLATFORM_MT53XX
14965         rtw_wx_get_sensitivity,                 //0x07
14966         rtw_wx_set_mtk_wps_probe_ie,    //0x08
14967         rtw_wx_set_mtk_wps_ie,                  //0x09
14968
14969 // for RTK_DMP_PLATFORM
14970 // Set Channel depend on the country code
14971         rtw_wx_set_channel_plan,                //0x0A
14972
14973         rtw_dbg_port,                                   //0x0B
14974         rtw_wx_write_rf,                                        //0x0C
14975         rtw_wx_read_rf,                                 //0x0D
14976 #ifdef CONFIG_MP_INCLUDED
14977         rtw_mp_set,                                     //0x0E
14978         rtw_mp_get,                                     //0x0F
14979 #else
14980         rtw_wx_priv_null,                               //0x0E
14981         rtw_wx_priv_null,                               //0x0F
14982 #endif
14983         rtw_p2p_set,                                    //0x10
14984         rtw_p2p_get,                                    //0x11
14985         NULL,                                                   //0x12
14986         rtw_p2p_get2,                                   //0x13
14987
14988         rtw_tdls,                                               //0x14
14989         rtw_tdls_get,                                   //0x15
14990
14991         rtw_pm_set,                                             //0x16
14992         rtw_wx_priv_null,                               //0x17
14993         rtw_rereg_nd_name,                              //0x18
14994         rtw_wx_priv_null,                               //0x19
14995 #ifdef CONFIG_MP_INCLUDED
14996         rtw_wx_priv_null,                               //0x1A
14997         rtw_wx_priv_null,                               //0x1B
14998 #else
14999         rtw_mp_efuse_set,                               //0x1A
15000         rtw_mp_efuse_get,                               //0x1B
15001 #endif
15002         NULL,                                                   // 0x1C is reserved for hostapd
15003         rtw_test,                                               // 0x1D
15004 #ifdef CONFIG_INTEL_WIDI
15005         rtw_widi_set,                                   //0x1E
15006         rtw_widi_set_probe_request,             //0x1F
15007 #endif // CONFIG_INTEL_WIDI
15008 };
15009
15010
15011 #if WIRELESS_EXT >= 17  
15012 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
15013 {
15014        _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
15015            struct iw_statistics *piwstats=&padapter->iwstats;
15016         int tmp_level = 0;
15017         int tmp_qual = 0;
15018         int tmp_noise = 0;
15019
15020         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != _TRUE)
15021         {
15022                 piwstats->qual.qual = 0;
15023                 piwstats->qual.level = 0;
15024                 piwstats->qual.noise = 0;
15025                 //DBG_871X("No link  level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
15026         }
15027         else{
15028                 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
15029                 tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength); 
15030                 #else
15031                 #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
15032                 {
15033                         /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
15034                         
15035                         HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
15036                         
15037                         tmp_level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, padapter->recvpriv.signal_strength);
15038                 }
15039                 #else
15040                 tmp_level = padapter->recvpriv.signal_strength;
15041                 #endif
15042                 #endif
15043                 
15044                 tmp_qual = padapter->recvpriv.signal_qual;
15045                 rtw_get_noise(padapter);
15046                 tmp_noise = padapter->recvpriv.noise;
15047                 //DBG_871X("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise,padapter->recvpriv.rssi);
15048
15049                 piwstats->qual.level = tmp_level;
15050                 piwstats->qual.qual = tmp_qual;
15051                 piwstats->qual.noise = tmp_noise;
15052         }
15053 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
15054         piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;//|IW_QUAL_DBM;
15055 #else
15056 #ifdef RTK_DMP_PLATFORM
15057         //IW_QUAL_DBM= 0x8, if driver use this flag, wireless extension will show value of dbm.
15058         //remove this flag for show percentage 0~100
15059         piwstats->qual.updated = 0x07;
15060 #else
15061         piwstats->qual.updated = 0x0f;
15062 #endif
15063 #endif
15064
15065         #ifdef CONFIG_SIGNAL_DISPLAY_DBM
15066         piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
15067         #endif
15068
15069         return &padapter->iwstats;
15070 }
15071 #endif
15072
15073 #ifdef CONFIG_WIRELESS_EXT
15074 struct iw_handler_def rtw_handlers_def =
15075 {
15076         .standard = rtw_handlers,
15077         .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
15078 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) || defined(CONFIG_WEXT_PRIV)
15079         .private = rtw_private_handler,
15080         .private_args = (struct iw_priv_args *)rtw_private_args,
15081         .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
15082         .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
15083 #endif
15084 #if WIRELESS_EXT >= 17
15085         .get_wireless_stats = rtw_get_wireless_stats,
15086 #endif
15087 };
15088 #endif
15089
15090 // copy from net/wireless/wext.c start
15091 /* ---------------------------------------------------------------- */
15092 /*
15093  * Calculate size of private arguments
15094  */
15095 static const char iw_priv_type_size[] = {
15096         0,                              /* IW_PRIV_TYPE_NONE */
15097         1,                              /* IW_PRIV_TYPE_BYTE */
15098         1,                              /* IW_PRIV_TYPE_CHAR */
15099         0,                              /* Not defined */
15100         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
15101         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
15102         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
15103         0,                              /* Not defined */
15104 };
15105
15106 static int get_priv_size(__u16 args)
15107 {
15108         int num = args & IW_PRIV_SIZE_MASK;
15109         int type = (args & IW_PRIV_TYPE_MASK) >> 12;
15110
15111         return num * iw_priv_type_size[type];
15112 }
15113 // copy from net/wireless/wext.c end
15114
15115
15116 static int _rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
15117 {
15118         int err = 0;
15119         u8 *input = NULL;
15120         u32 input_len = 0;
15121         const char delim[] = " ";
15122         u8 *output = NULL;
15123         u32 output_len = 0;
15124         u32 count = 0;
15125         u8 *buffer= NULL;
15126         u32 buffer_len = 0;
15127         char *ptr = NULL;
15128         u8 cmdname[17] = {0}; // IFNAMSIZ+1
15129         u32 cmdlen;
15130         s32 len;
15131         u8 *extra = NULL;
15132         u32 extra_size = 0;
15133
15134         s32 k;
15135         const iw_handler *priv;         /* Private ioctl */
15136         const struct iw_priv_args *priv_args;   /* Private ioctl description */
15137         u32 num_priv;                           /* Number of ioctl */
15138         u32 num_priv_args;                      /* Number of descriptions */
15139         iw_handler handler;
15140         int temp;
15141         int subcmd = 0;                         /* sub-ioctl index */
15142         int offset = 0;                         /* Space for sub-ioctl index */
15143
15144         union iwreq_data wdata;
15145
15146         _rtw_memcpy(&wdata, wrq_data, sizeof(wdata));
15147
15148         input_len = wdata.data.length;
15149         input = rtw_zmalloc(input_len);
15150         if (NULL == input || input_len == 0)
15151                 return -ENOMEM;
15152         if (copy_from_user(input, wdata.data.pointer, input_len)) {
15153                 err = -EFAULT;
15154                 goto exit;
15155         }
15156         input[input_len - 1] = '\0';
15157         ptr = input;
15158         len = input_len;
15159         sscanf(ptr, "%16s", cmdname);
15160         cmdlen = strlen(cmdname);
15161         DBG_871X("%s: cmd=%s\n", __func__, cmdname);
15162
15163         // skip command string
15164         if (cmdlen > 0)
15165                 cmdlen += 1; // skip one space
15166         ptr += cmdlen;
15167         len -= cmdlen;
15168         DBG_871X("%s: parameters=%s\n", __func__, ptr);
15169
15170         priv = rtw_private_handler;
15171         priv_args = rtw_private_args;
15172         num_priv = sizeof(rtw_private_handler) / sizeof(iw_handler);
15173         num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
15174
15175         if (num_priv_args == 0) {
15176                 err = -EOPNOTSUPP;
15177                 goto exit;
15178         }
15179
15180         /* Search the correct ioctl */
15181         k = -1;
15182         while((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
15183
15184         /* If not found... */
15185         if (k == num_priv_args) {
15186                 err = -EOPNOTSUPP;
15187                 goto exit;
15188         }
15189
15190         /* Watch out for sub-ioctls ! */
15191         if (priv_args[k].cmd < SIOCDEVPRIVATE)
15192         {
15193                 int j = -1;
15194
15195                 /* Find the matching *real* ioctl */
15196                 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
15197                         (priv_args[j].set_args != priv_args[k].set_args) ||
15198                         (priv_args[j].get_args != priv_args[k].get_args)));
15199
15200                 /* If not found... */
15201                 if (j == num_priv_args) {
15202                         err = -EINVAL;
15203                         goto exit;
15204                 }
15205
15206                 /* Save sub-ioctl number */
15207                 subcmd = priv_args[k].cmd;
15208                 /* Reserve one int (simplify alignment issues) */
15209                 offset = sizeof(__u32);
15210                 /* Use real ioctl definition from now on */
15211                 k = j;
15212         }
15213
15214         buffer = rtw_zmalloc(4096);
15215         if (NULL == buffer) {
15216                 err = -ENOMEM;
15217                 goto exit;
15218         }
15219
15220         /* If we have to set some data */
15221         if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
15222                 (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
15223         {
15224                 u8 *str;
15225
15226                 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK)
15227                 {
15228                         case IW_PRIV_TYPE_BYTE:
15229                                 /* Fetch args */
15230                                 count = 0;
15231                                 do {
15232                                         str = strsep(&ptr, delim);
15233                                         if (NULL == str) break;
15234                                         sscanf(str, "%i", &temp);
15235                                         buffer[count++] = (u8)temp;
15236                                 } while (1);
15237                                 buffer_len = count;
15238
15239                                 /* Number of args to fetch */
15240                                 wdata.data.length = count;
15241                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
15242                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
15243
15244                                 break;
15245
15246                         case IW_PRIV_TYPE_INT:
15247                                 /* Fetch args */
15248                                 count = 0;
15249                                 do {
15250                                         str = strsep(&ptr, delim);
15251                                         if (NULL == str) break;
15252                                         sscanf(str, "%i", &temp);
15253                                         ((s32*)buffer)[count++] = (s32)temp;
15254                                 } while (1);
15255                                 buffer_len = count * sizeof(s32);
15256
15257                                 /* Number of args to fetch */
15258                                 wdata.data.length = count;
15259                                 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
15260                                         wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
15261
15262                                 break;
15263
15264                         case IW_PRIV_TYPE_CHAR:
15265                                 if (len > 0)
15266                                 {
15267                                         /* Size of the string to fetch */
15268                                         wdata.data.length = len;
15269                                         if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
15270                                                 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
15271
15272                                         /* Fetch string */
15273                                         _rtw_memcpy(buffer, ptr, wdata.data.length);
15274                                 }
15275                                 else
15276                                 {
15277                                         wdata.data.length = 1;
15278                                         buffer[0] = '\0';
15279                                 }
15280                                 buffer_len = wdata.data.length;
15281                                 break;
15282
15283                         default:
15284                                 DBG_8192C("%s: Not yet implemented...\n", __func__);
15285                                 err = -1;
15286                                 goto exit;
15287                 }
15288
15289                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
15290                         (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK)))
15291                 {
15292                         DBG_8192C("%s: The command %s needs exactly %d argument(s)...\n",
15293                                         __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
15294                         err = -EINVAL;
15295                         goto exit;
15296                 }
15297         }   /* if args to set */
15298         else
15299         {
15300                 wdata.data.length = 0L;
15301         }
15302
15303         /* Those two tests are important. They define how the driver
15304         * will have to handle the data */
15305         if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
15306                 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ))
15307         {
15308                 /* First case : all SET args fit within wrq */
15309                 if (offset)
15310                         wdata.mode = subcmd;
15311                 _rtw_memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
15312         }
15313         else
15314         {
15315                 if ((priv_args[k].set_args == 0) &&
15316                         (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
15317                         (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
15318                 {
15319                         /* Second case : no SET args, GET args fit within wrq */
15320                         if (offset)
15321                                 wdata.mode = subcmd;
15322                 }
15323                 else
15324                 {
15325                         /* Third case : args won't fit in wrq, or variable number of args */
15326                         if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
15327                                 err = -EFAULT;
15328                                 goto exit;
15329                         }
15330                         wdata.data.flags = subcmd;
15331                 }
15332         }
15333
15334         rtw_mfree(input, input_len);
15335         input = NULL;
15336
15337         extra_size = 0;
15338         if (IW_IS_SET(priv_args[k].cmd))
15339         {
15340                 /* Size of set arguments */
15341                 extra_size = get_priv_size(priv_args[k].set_args);
15342
15343                 /* Does it fits in iwr ? */
15344                 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
15345                         ((extra_size + offset) <= IFNAMSIZ))
15346                         extra_size = 0;
15347         } else {
15348                 /* Size of get arguments */
15349                 extra_size = get_priv_size(priv_args[k].get_args);
15350
15351                 /* Does it fits in iwr ? */
15352                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
15353                         (extra_size <= IFNAMSIZ))
15354                         extra_size = 0;
15355         }
15356
15357         if (extra_size == 0) {
15358                 extra = (u8*)&wdata;
15359                 rtw_mfree(buffer, 4096);
15360                 buffer = NULL;
15361         } else
15362                 extra = buffer;
15363
15364         handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
15365         err = handler(dev, NULL, &wdata, extra);
15366
15367         /* If we have to get some data */
15368         if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
15369                 (priv_args[k].get_args & IW_PRIV_SIZE_MASK))
15370         {
15371                 int j;
15372                 int n = 0;      /* number of args */
15373                 u8 str[20] = {0};
15374
15375                 /* Check where is the returned data */
15376                 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
15377                         (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
15378                         n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
15379                 else
15380                         n = wdata.data.length;
15381
15382                 output = rtw_zmalloc(4096);
15383                 if (NULL == output) {
15384                         err =  -ENOMEM;
15385                         goto exit;
15386                 }
15387
15388                 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK)
15389                 {
15390                         case IW_PRIV_TYPE_BYTE:
15391                                 /* Display args */
15392                                 for (j = 0; j < n; j++)
15393                                 {
15394                                         sprintf(str, "%d  ", extra[j]);
15395                                         len = strlen(str);
15396                                         output_len = strlen(output);
15397                                         if ((output_len + len + 1) > 4096) {
15398                                                 err = -E2BIG;
15399                                                 goto exit;
15400                                         }
15401                                         _rtw_memcpy(output+output_len, str, len);
15402                                 }
15403                                 break;
15404
15405                         case IW_PRIV_TYPE_INT:
15406                                 /* Display args */
15407                                 for (j = 0; j < n; j++)
15408                                 {
15409                                         sprintf(str, "%d  ", ((__s32*)extra)[j]);
15410                                         len = strlen(str);
15411                                         output_len = strlen(output);
15412                                         if ((output_len + len + 1) > 4096) {
15413                                                 err = -E2BIG;
15414                                                 goto exit;
15415                                         }
15416                                         _rtw_memcpy(output+output_len, str, len);
15417                                 }
15418                                 break;
15419
15420                         case IW_PRIV_TYPE_CHAR:
15421                                 /* Display args */
15422                                 _rtw_memcpy(output, extra, n);
15423                                 break;
15424
15425                         default:
15426                                 DBG_8192C("%s: Not yet implemented...\n", __func__);
15427                                 err = -1;
15428                                 goto exit;
15429                 }
15430
15431                 output_len = strlen(output) + 1;
15432                 wrq_data->data.length = output_len;
15433                 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
15434                         err = -EFAULT;
15435                         goto exit;
15436                 }
15437         }   /* if args to set */
15438         else
15439         {
15440                 wrq_data->data.length = 0;
15441         }
15442
15443 exit:
15444         if (input)
15445                 rtw_mfree(input, input_len);
15446         if (buffer)
15447                 rtw_mfree(buffer, 4096);
15448         if (output)
15449                 rtw_mfree(output, 4096);
15450
15451         return err;
15452 }
15453
15454 #ifdef CONFIG_COMPAT
15455 static int rtw_ioctl_compat_wext_private(struct net_device *dev, struct ifreq *rq)
15456 {
15457         struct compat_iw_point iwp_compat;
15458         union iwreq_data wrq_data;
15459         int err = 0;
15460         DBG_871X("%s:...\n", __func__);
15461         if (copy_from_user(&iwp_compat, rq->ifr_ifru.ifru_data, sizeof(struct compat_iw_point)))
15462                         return -EFAULT;
15463         
15464         wrq_data.data.pointer = compat_ptr(iwp_compat.pointer);
15465         wrq_data.data.length = iwp_compat.length;
15466         wrq_data.data.flags = iwp_compat.flags;
15467
15468         err = _rtw_ioctl_wext_private(dev, &wrq_data);
15469
15470         iwp_compat.pointer = ptr_to_compat(wrq_data.data.pointer);
15471         iwp_compat.length = wrq_data.data.length;
15472         iwp_compat.flags = wrq_data.data.flags;
15473         if (copy_to_user(rq->ifr_ifru.ifru_data, &iwp_compat, sizeof(struct compat_iw_point)))
15474                         return -EFAULT;
15475
15476         return err;
15477 }
15478 #endif // CONFIG_COMPAT
15479
15480 static int rtw_ioctl_standard_wext_private(struct net_device *dev, struct ifreq *rq)
15481 {
15482         struct iw_point *iwp;
15483         struct ifreq ifrq;
15484         union iwreq_data wrq_data;
15485         int err = 0;
15486         iwp = &wrq_data.data;
15487         DBG_871X("%s:...\n", __func__);
15488         if (copy_from_user(iwp, rq->ifr_ifru.ifru_data, sizeof(struct iw_point)))
15489                 return -EFAULT;
15490
15491         err = _rtw_ioctl_wext_private(dev, &wrq_data);
15492
15493         if (copy_to_user(rq->ifr_ifru.ifru_data, iwp, sizeof(struct iw_point)))
15494                 return -EFAULT;
15495
15496         return err;
15497 }
15498  
15499 static int rtw_ioctl_wext_private(struct net_device *dev, struct ifreq *rq)
15500 {
15501 #ifdef CONFIG_COMPAT
15502         if(is_compat_task())
15503                 return rtw_ioctl_compat_wext_private( dev, rq );
15504         else
15505 #endif // CONFIG_COMPAT
15506                 return rtw_ioctl_standard_wext_private( dev, rq );
15507 }
15508
15509 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
15510 {
15511         struct iwreq *wrq = (struct iwreq *)rq;
15512         int ret=0;
15513
15514         switch (cmd)
15515         {
15516                 case RTL_IOCTL_WPA_SUPPLICANT:
15517                         ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
15518                         break;
15519 #ifdef CONFIG_AP_MODE
15520                 case RTL_IOCTL_HOSTAPD:
15521                         ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
15522                         break;
15523 #ifdef CONFIG_WIRELESS_EXT
15524                 case SIOCSIWMODE:
15525                         ret = rtw_wx_set_mode(dev, NULL, &wrq->u, NULL);
15526                         break;
15527 #endif
15528 #endif // CONFIG_AP_MODE
15529                 case SIOCDEVPRIVATE:                            
15530                          ret = rtw_ioctl_wext_private(dev, rq);
15531                         break;
15532                 case (SIOCDEVPRIVATE+1):
15533                         ret = rtw_android_priv_cmd(dev, rq, cmd);
15534                         break;
15535                 default:
15536                         ret = -EOPNOTSUPP;
15537                         break;
15538         }
15539
15540         return ret;
15541 }
15542
15543